Multi-platform: support multiple files per version #201
@ -5,8 +5,9 @@ from django.urls import reverse
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase, APIClient
|
||||
|
||||
from common.tests.factories.users import UserFactory
|
||||
from common.tests.factories.extensions import create_approved_version, create_version
|
||||
from common.tests.factories.files import FileFactory
|
||||
from common.tests.factories.users import UserFactory
|
||||
from common.tests.utils import create_user_token
|
||||
|
||||
from extensions.models import Extension, Version
|
||||
@ -176,6 +177,39 @@ class FiltersTest(APITestCase):
|
||||
).json()
|
||||
self.assertEqual(len(json['data']), 1)
|
||||
|
||||
def test_platform_filter_same_version(self):
|
||||
version = create_approved_version(
|
||||
metadata__id='filter_test',
|
||||
metadata__platforms=['linux-x64'],
|
||||
metadata__version='1.0.0',
|
||||
)
|
||||
version = version.add_file(
|
||||
FileFactory(
|
||||
metadata__id='filter_test',
|
||||
metadata__platforms=['windows-x64'],
|
||||
metadata__version='1.0.0',
|
||||
)
|
||||
)
|
||||
|
||||
url = reverse('extensions:api')
|
||||
json = self.client.get(
|
||||
url + '?platform=linux-x64',
|
||||
HTTP_ACCEPT='application/json',
|
||||
).json()
|
||||
self.assertEqual(len(json['data']), 1)
|
||||
|
||||
json = self.client.get(
|
||||
url + '?platform=windows-x64',
|
||||
HTTP_ACCEPT='application/json',
|
||||
).json()
|
||||
self.assertEqual(len(json['data']), 1)
|
||||
|
||||
json = self.client.get(
|
||||
url,
|
||||
HTTP_ACCEPT='application/json',
|
||||
).json()
|
||||
self.assertEqual(len(json['data']), 2)
|
||||
|
||||
def test_blender_version_filter_latest_not_max_version(self):
|
||||
version = create_approved_version(metadata__blender_version_min='4.0.1')
|
||||
date_created = version.date_created
|
||||
|
@ -54,7 +54,7 @@ class ListedExtensionsSerializer(serializers.ModelSerializer):
|
||||
except Platform.DoesNotExist:
|
||||
self.platform = self.UNKNOWN_PLATFORM
|
||||
|
||||
def find_matching_file_and_version(self, instance):
|
||||
def find_matching_files_and_version(self, instance):
|
||||
# avoid triggering additional db queries, reuse the prefetched queryset
|
||||
versions = sorted(
|
||||
[v for v in instance.versions.all() if v.is_listed],
|
||||
@ -62,7 +62,7 @@ class ListedExtensionsSerializer(serializers.ModelSerializer):
|
||||
reverse=True,
|
||||
)
|
||||
if not versions:
|
||||
return (None, None)
|
||||
return ([], None)
|
||||
|
||||
for v in versions:
|
||||
if self.blender_version and not is_in_version_range(
|
||||
@ -71,24 +71,26 @@ class ListedExtensionsSerializer(serializers.ModelSerializer):
|
||||
v.blender_version_max,
|
||||
):
|
||||
continue
|
||||
if self.platform:
|
||||
if file := v.get_file_for_platform(self.platform):
|
||||
return (file, v)
|
||||
return ([file], v)
|
||||
else:
|
||||
return (v.files.all(), v)
|
||||
|
||||
return (None, None)
|
||||
return ([], None)
|
||||
|
||||
def to_representation(self, instance):
|
||||
# TODO? return all matching files (when no self.platform is passed)?
|
||||
matching_file, matching_version = self.find_matching_file_and_version(instance)
|
||||
if not matching_file:
|
||||
return None
|
||||
matching_files, matching_version = self.find_matching_files_and_version(instance)
|
||||
result = []
|
||||
for file in matching_files:
|
||||
data = {
|
||||
'id': instance.extension_id,
|
||||
'schema_version': matching_version.schema_version,
|
||||
'name': instance.name,
|
||||
'version': matching_version.version,
|
||||
'tagline': matching_version.tagline,
|
||||
'archive_hash': matching_file.original_hash,
|
||||
'archive_size': matching_file.size_bytes,
|
||||
'archive_hash': file.original_hash,
|
||||
'archive_size': file.size_bytes,
|
||||
'archive_url': self.request.build_absolute_uri(
|
||||
matching_version.get_download_url(
|
||||
platform=self.platform,
|
||||
@ -100,15 +102,17 @@ class ListedExtensionsSerializer(serializers.ModelSerializer):
|
||||
'blender_version_max': matching_version.blender_version_max,
|
||||
'website': self.request.build_absolute_uri(instance.get_absolute_url()),
|
||||
# avoid triggering additional db queries, reuse the prefetched queryset
|
||||
'maintainer': instance.team and instance.team.name or str(instance.authors.all()[0]),
|
||||
'maintainer': (
|
||||
instance.team and instance.team.name or str(instance.authors.all()[0])
|
||||
),
|
||||
'license': [license_iter.slug for license_iter in matching_version.licenses.all()],
|
||||
'permissions': matching_file.metadata.get('permissions'),
|
||||
# listing all platforms for matching_version, not matching_file (see TODO? above)
|
||||
'platforms': [platform.slug for platform in matching_version.platforms.all()],
|
||||
'permissions': file.metadata.get('permissions'),
|
||||
'platforms': file.get_platforms(),
|
||||
# TODO: handle copyright
|
||||
'tags': [str(tag) for tag in matching_version.tags.all()],
|
||||
}
|
||||
return clean_json_dictionary_from_optional_fields(data)
|
||||
result.append(clean_json_dictionary_from_optional_fields(data))
|
||||
return result
|
||||
|
||||
|
||||
class ExtensionsAPIView(APIView):
|
||||
@ -153,7 +157,10 @@ class ExtensionsAPIView(APIView):
|
||||
request=request,
|
||||
many=True,
|
||||
)
|
||||
data = [e for e in serializer.data if e is not None]
|
||||
data = []
|
||||
for entry in serializer.data:
|
||||
data.extend(entry)
|
||||
|
||||
return Response(
|
||||
{
|
||||
'blocklist': Extension.objects.blocklisted.values_list('extension_id', flat=True),
|
||||
|
Loading…
Reference in New Issue
Block a user