Skip to content

Commit

Permalink
Serialize more fields using MatchingSerializer #224
Browse files Browse the repository at this point in the history
Signed-off-by: Jono Yang <[email protected]>
  • Loading branch information
JonoYang committed Dec 1, 2023
1 parent 4bbc611 commit bb0e288
Showing 1 changed file with 89 additions and 5 deletions.
94 changes: 89 additions & 5 deletions matchcode/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
# See https://github.com/nexB/purldb for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#

from uuid import uuid4
from django.db.models import Q
from django.forms import widgets
from django.forms.fields import MultipleChoiceField
from django_filters.filters import MultipleChoiceFilter
from django_filters.rest_framework import FilterSet
from rest_framework import mixins
from rest_framework import renderers
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
Expand All @@ -34,10 +35,14 @@
from matchcode.models import ApproximateDirectoryContentIndex
from matchcode.models import ApproximateDirectoryStructureIndex

from scanpipe.api.serializers import ProjectSerializer
from scanpipe.api.serializers import RunSerializer
from scanpipe.api.serializers import StrListField
from scanpipe.api.views import ProjectFilterSet
from scanpipe.models import Project
from scanpipe.pipes import count_group_by
from scanpipe.pipes.fetch import fetch_urls
from scanpipe.views import project_results_json_response


class BaseFileIndexSerializer(ModelSerializer):
sha1 = CharField(source='fingerprint')
Expand Down Expand Up @@ -316,12 +321,73 @@ class ApproximateDirectoryStructureIndexViewSet(BaseDirectoryIndexViewSet):
filterset_class = ApproximateDirectoryStructureFilterSet


class MatchingSerializer(ProjectSerializer):
def create(self, validated_data, matching_pipeline_name='matching2'):
class MatchingSerializer(serializers.ModelSerializer):
upload_file = serializers.FileField(write_only=True, required=False)
input_urls = StrListField(
write_only=True,
required=False,
style={"base_template": "textarea.html"},
)
webhook_url = serializers.CharField(write_only=True, required=False)
runs = RunSerializer(many=True, read_only=True)
input_sources = serializers.JSONField(source="input_sources_list", read_only=True)
codebase_resources_summary = serializers.SerializerMethodField()
discovered_packages_summary = serializers.SerializerMethodField()
discovered_dependencies_summary = serializers.SerializerMethodField()
codebase_relations_summary = serializers.SerializerMethodField()

class Meta:
model = Project
fields = (
'url',
'uuid',
"upload_file",
"input_urls",
"webhook_url",
"created_date",
"input_sources",
"runs",
"resource_count",
"package_count",
"dependency_count",
"relation_count",
"codebase_resources_summary",
"discovered_packages_summary",
"discovered_dependencies_summary",
"codebase_relations_summary",
)

def get_codebase_resources_summary(self, project):
queryset = project.codebaseresources.all()
return count_group_by(queryset, "status")

def get_discovered_packages_summary(self, project):
base_qs = project.discoveredpackages
return {
"total": base_qs.count(),
"with_missing_resources": base_qs.exclude(missing_resources=[]).count(),
"with_modified_resources": base_qs.exclude(modified_resources=[]).count(),
}

def get_discovered_dependencies_summary(self, project):
base_qs = project.discovereddependencies
return {
"total": base_qs.count(),
"is_runtime": base_qs.filter(is_runtime=True).count(),
"is_optional": base_qs.filter(is_optional=True).count(),
"is_resolved": base_qs.filter(is_resolved=True).count(),
}

def get_codebase_relations_summary(self, project):
queryset = project.codebaserelations.all()
return count_group_by(queryset, "map_type")

def create(self, validated_data, matching_pipeline_name='matching'):
"""
Create a new `project` with `upload_file`, using the `matching2` pipeline
Create a new `project` with `upload_file`, using the `matching` pipeline
"""
execute_now = True
validated_data['name'] = uuid4()
upload_file = validated_data.pop("upload_file", None)
input_urls = validated_data.pop("input_urls", [])
webhook_url = validated_data.pop("webhook_url", None)
Expand Down Expand Up @@ -356,3 +422,21 @@ class MatchingViewSet(
queryset = Project.objects.all()
serializer_class = MatchingSerializer
filterset_class = ProjectFilterSet

def get_queryset(self):
return (
super()
.get_queryset()
.prefetch_related(
"runs",
)
)

@action(detail=True, renderer_classes=[renderers.JSONRenderer])
def results(self, request, *args, **kwargs):
"""
Return the results compatible with ScanCode data format.
The content is returned as a stream of JSON content using the
JSONResultsGenerator class.
"""
return project_results_json_response(self.get_object())

0 comments on commit bb0e288

Please sign in to comment.