88#
99
1010import logging
11+
12+ import django_filters
1113from django .core .exceptions import ValidationError
12- from django .db .models import OuterRef
13- from django .db .models import Q
14- from django .db .models import Subquery
14+ from django .db .models import OuterRef , Q , Subquery
15+ from django_filters .filters import Filter , OrderingFilter
1516from django_filters .rest_framework import FilterSet
16- from django_filters .filters import Filter
17- from django_filters .filters import OrderingFilter
18- import django_filters
19-
2017from packageurl import PackageURL
2118from packageurl .contrib .django .utils import purl_to_lookups
22- from rest_framework import status
23- from rest_framework import viewsets
19+ from rest_framework import status , viewsets
2420from rest_framework .decorators import action
2521from rest_framework .response import Response
22+ from univers .version_constraint import InvalidConstraintsError
23+ from univers .version_range import RANGE_CLASS_BY_SCHEMES , VersionRange
24+ from univers .versions import InvalidVersion
2625
27- from matchcode .api import MultipleCharFilter
28- from matchcode .api import MultipleCharInFilter
26+ from matchcode .api import MultipleCharFilter , MultipleCharInFilter
2927# UnusedImport here!
3028# But importing the mappers and visitors module triggers routes registration
3129from minecode import visitors # NOQA
3230from minecode import priority_router
33- from minecode .models import PriorityResourceURI
34- from minecode .models import ScannableURI
31+ from minecode .models import PriorityResourceURI , ScannableURI
3532from minecode .route import NoRouteAvailable
36- from packagedb .models import Package
37- from packagedb .models import PackageContentType
38- from packagedb .models import PackageSet
39- from packagedb .models import Resource
40- from packagedb .serializers import DependentPackageSerializer
41- from packagedb .serializers import ResourceAPISerializer
42- from packagedb .serializers import PackageAPISerializer
43- from packagedb .serializers import PackageSetAPISerializer
44- from packagedb .serializers import PartySerializer
45- from packagedb .package_managers import get_api_package_name
46- from packagedb .package_managers import get_version_fetcher
47- from packagedb .package_managers import VERSION_API_CLASSES_BY_PACKAGE_TYPE
48-
49- from univers import versions
50- from univers .version_range import RANGE_CLASS_BY_SCHEMES
51- from univers .versions import InvalidVersion
52- from univers .version_range import VersionRange
53- from univers .version_constraint import InvalidConstraintsError
33+ from packagedb .filters import PackageSearchFilter
34+ from packagedb .models import Package , PackageContentType , PackageSet , Resource
35+ from packagedb .package_managers import (VERSION_API_CLASSES_BY_PACKAGE_TYPE ,
36+ get_api_package_name ,
37+ get_version_fetcher )
38+ from packagedb .serializers import (DependentPackageSerializer ,
39+ PackageAPISerializer ,
40+ PackageSetAPISerializer , PartySerializer ,
41+ ResourceAPISerializer )
5442
5543logger = logging .getLogger (__name__ )
5644
@@ -84,21 +72,21 @@ def filter(self, qs, value):
8472 return qs .filter (package = package )
8573
8674
87- class ResourceFilter (FilterSet ):
75+ class ResourceFilterSet (FilterSet ):
8876 package = PackageResourceUUIDFilter (label = 'Package UUID' )
8977 purl = PackageResourcePurlFilter (label = 'Package pURL' )
9078 md5 = MultipleCharInFilter (
91- help_text = " Exact MD5. Multi-value supported." ,
79+ help_text = ' Exact MD5. Multi-value supported.' ,
9280 )
9381 sha1 = MultipleCharInFilter (
94- help_text = " Exact SHA1. Multi-value supported." ,
82+ help_text = ' Exact SHA1. Multi-value supported.' ,
9583 )
9684
9785
9886class ResourceViewSet (viewsets .ReadOnlyModelViewSet ):
9987 queryset = Resource .objects .select_related ('package' )
10088 serializer_class = ResourceAPISerializer
101- filterset_class = ResourceFilter
89+ filterset_class = ResourceFilterSet
10290 lookup_field = 'sha1'
10391
10492 @action (detail = False , methods = ['post' ])
@@ -169,70 +157,63 @@ def filter_by_checksums(self, request, *args, **kwargs):
169157 return self .get_paginated_response (serializer .data )
170158
171159
172- class MultiplePackageURLFilter (Filter ):
160+ class MultiplePackageURLFilter (MultipleCharFilter ):
173161 def filter (self , qs , value ):
174- try :
175- request = self .parent .request
176- except AttributeError :
177- return None
162+ if not value :
163+ # Even though not a noop, no point filtering if empty.
164+ return qs
178165
179- values = request .GET .getlist (self .field_name )
180- if all (v == '' for v in values ):
166+ if self .is_noop (qs , value ):
181167 return qs
182168
183- values = {item for item in values }
169+ if all (v == '' for v in value ):
170+ return qs
184171
185172 q = Q ()
186- for val in values :
173+ for val in value :
187174 lookups = purl_to_lookups (val )
188175 if not lookups :
189176 continue
190-
191177 q .add (Q (** lookups ), Q .OR )
192178
193- if not q :
194- return qs .none ()
195-
196- return qs .filter (q )
197-
198-
199- class PackageSearchFilter (Filter ):
200- def filter (self , qs , value ):
201- try :
202- request = self .parent .request
203- except AttributeError :
204- return None
205-
206- if not value :
207- return qs
179+ if q :
180+ qs = self .get_method (qs )(q )
181+ else :
182+ qs = qs .none ()
208183
209- return Package . objects . filter ( search_vector = value )
184+ return qs . distinct () if self . distinct else qs
210185
211186
212- class PackageFilter (FilterSet ):
187+ class PackageFilterSet (FilterSet ):
213188 type = django_filters .CharFilter (
214- lookup_expr = " iexact" ,
215- help_text = " Exact type. (case-insensitive)" ,
189+ lookup_expr = ' iexact' ,
190+ help_text = ' Exact type. (case-insensitive)' ,
216191 )
217192 namespace = django_filters .CharFilter (
218- lookup_expr = " iexact" ,
219- help_text = " Exact namespace. (case-insensitive)" ,
193+ lookup_expr = ' iexact' ,
194+ help_text = ' Exact namespace. (case-insensitive)' ,
220195 )
221196 name = MultipleCharFilter (
222- lookup_expr = " iexact" ,
223- help_text = " Exact name. Multi-value supported. (case-insensitive)" ,
197+ lookup_expr = ' iexact' ,
198+ help_text = ' Exact name. Multi-value supported. (case-insensitive)' ,
224199 )
225200 version = MultipleCharFilter (
226- help_text = " Exact version. Multi-value supported." ,
201+ help_text = ' Exact version. Multi-value supported.' ,
227202 )
228203 md5 = MultipleCharInFilter (
229- help_text = " Exact MD5. Multi-value supported." ,
204+ help_text = ' Exact MD5. Multi-value supported.' ,
230205 )
231206 sha1 = MultipleCharInFilter (
232- help_text = "Exact SHA1. Multi-value supported." ,
207+ help_text = 'Exact SHA1. Multi-value supported.' ,
208+ )
209+ purl = MultiplePackageURLFilter (
210+ label = 'Package URL' ,
211+ )
212+ search = PackageSearchFilter (
213+ label = 'Search' ,
214+ field_name = 'name' ,
215+ lookup_expr = 'icontains' ,
233216 )
234- purl = MultiplePackageURLFilter (label = 'Package URL' )
235- search = PackageSearchFilter (label = 'Search' )
236217
237218 sort = OrderingFilter (fields = [
238219 'type' ,
@@ -250,6 +231,7 @@ class PackageFilter(FilterSet):
250231 class Meta :
251232 model = Package
252233 fields = (
234+ 'search' ,
253235 'type' ,
254236 'namespace' ,
255237 'name' ,
@@ -270,7 +252,7 @@ class PackageViewSet(viewsets.ReadOnlyModelViewSet):
270252 queryset = Package .objects .prefetch_related ('dependencies' , 'parties' )
271253 serializer_class = PackageAPISerializer
272254 lookup_field = 'uuid'
273- filterset_class = PackageFilter
255+ filterset_class = PackageFilterSet
274256
275257 @action (detail = True , methods = ['get' ])
276258 def latest_version (self , request , * args , ** kwargs ):
@@ -429,7 +411,7 @@ def index_packages(self, request, *args, **kwargs):
429411 packages = request .data .get ('packages' ) or []
430412 queued_packages = []
431413 unqueued_packages = []
432- supported_ecosystems = [" maven" , " npm" ]
414+ supported_ecosystems = [' maven' , ' npm' ]
433415
434416 unique_purls , unsupported_packages , unsupported_vers = get_resolved_purls (packages , supported_ecosystems )
435417
0 commit comments