Update extension fields from manifest metadata #111 #121

Merged
Oleg-Komarov merged 4 commits from update-metadata-from-manifest into main 2024-05-10 15:13:33 +02:00
7 changed files with 74 additions and 1 deletions
Showing only changes of commit 1185b6c7fe - Show all commits

View File

@ -68,7 +68,16 @@ class VersionFactory(DjangoModelFactory):
download_count = factory.Faker('random_int') download_count = factory.Faker('random_int')
tagline = factory.Faker('bs') tagline = factory.Faker('bs')
file = factory.SubFactory('common.tests.factories.files.FileFactory') file = factory.SubFactory(
'common.tests.factories.files.FileFactory',
metadata=factory.Dict(
{
'name': factory.Faker('name'),
'support': factory.Faker('url'),
'website': factory.Faker('url'),
}
),
)
ratings = factory.RelatedFactoryList( ratings = factory.RelatedFactoryList(
RatingFactory, size=lambda: random.randint(1, 50), factory_related_name='version' RatingFactory, size=lambda: random.randint(1, 50), factory_related_name='version'
) )

View File

@ -25,3 +25,5 @@ class FileFactory(DjangoModelFactory):
source = factory.Faker('file_name', extension='zip') source = factory.Faker('file_name', extension='zip')
user = factory.SubFactory('common.tests.factories.users.UserFactory') user = factory.SubFactory('common.tests.factories.users.UserFactory')
metadata = factory.Dict({})

View File

@ -203,6 +203,24 @@ class Extension(CreatedModifiedMixin, RatingMixin, TrackChangesMixin, models.Mod
self.clean() self.clean()
return super().save(*args, **kwargs) return super().save(*args, **kwargs)
def update_metadata_from_version(self, version):
update_fields = set()
metadata = version.file.metadata
# check if we can also update name
# if we are uploading a new version, we have just validated and don't expect a clash,
# but if a version is being deleted, we want to rollback to a name from an older version,
# which may by clashing now, and we can't do anything about it
name = metadata.get('name')
if not self.__class__.objects.filter(name=name).exclude(pk=self.pk).exists():
update_fields.add('name')
for field in ['support', 'website']:
# if a field is missing from manifest, don't reset the corresponding extension field
if metadata.get(field):
update_fields.add(field)
for field in update_fields:
setattr(self, field, metadata.get(field))
self.save(update_fields=update_fields)
@transaction.atomic @transaction.atomic
def approve(self, reviewer=None): def approve(self, reviewer=None):
"""TODO: Approve an extension which is currently in review.""" """TODO: Approve an extension which is currently in review."""

View File

@ -189,3 +189,22 @@ def _create_approval_activity_for_new_version_if_listed(
extension=instance.extension, extension=instance.extension,
message=f'uploaded new version: {instance.version}', message=f'uploaded new version: {instance.version}',
).save() ).save()
@receiver(post_delete, sender=extensions.models.Version)
@receiver(post_save, sender=extensions.models.Version)
def _update_extension_metadata_from_latest_version(
sender: object,
instance: extensions.models.Version,
**kwargs: object,
):
# this code will also be triggered when an extension is deleted
# and it deletes all related versions
extension = instance.extension
latest_version = extension.latest_version
# should check in case we are deleting the latest version, then no need to update anything
if not latest_version:
return
extension.update_metadata_from_version(latest_version)

View File

@ -1,6 +1,7 @@
from django.test import TestCase from django.test import TestCase
from django.urls import reverse from django.urls import reverse
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
import factory
from common.tests.factories.extensions import create_approved_version from common.tests.factories.extensions import create_approved_version
from common.tests.factories.files import FileFactory from common.tests.factories.files import FileFactory
@ -63,6 +64,13 @@ class CreateFileTest(TestCase):
file=FileFactory( file=FileFactory(
type=File.TYPES.BPY, type=File.TYPES.BPY,
status=File.STATUSES.APPROVED, status=File.STATUSES.APPROVED,
metadata=factory.Dict(
{
'name': factory.Faker('name'),
'support': factory.Faker('url'),
'website': factory.Faker('url'),
}
),
), ),
) )
@ -240,6 +248,13 @@ class ValidateManifestTest(CreateFileTest):
file=FileFactory( file=FileFactory(
type=File.TYPES.BPY, type=File.TYPES.BPY,
status=File.STATUSES.APPROVED, status=File.STATUSES.APPROVED,
metadata=factory.Dict(
{
'name': factory.Faker('name'),
'support': factory.Faker('url'),
'website': factory.Faker('url'),
}
),
), ),
) )

View File

@ -22,6 +22,11 @@ class ExtensionTest(TestCase):
extension__name='Extension name', extension__name='Extension name',
extension__status=Extension.STATUSES.INCOMPLETE, extension__status=Extension.STATUSES.INCOMPLETE,
extension__support='https://example.com/', extension__support='https://example.com/',
file__metadata={
'name': 'Extension name',
'support': 'https://example.com/',
'website': 'https://example.com/',
},
).extension ).extension
self.assertEqual(entries_for(self.extension).count(), 0) self.assertEqual(entries_for(self.extension).count(), 0)
self.assertIsNone(self.extension.date_approved) self.assertIsNone(self.extension.date_approved)

View File

@ -19,6 +19,11 @@ def _create_extension():
extension__website='https://example.com/', extension__website='https://example.com/',
extension__status=Extension.STATUSES.INCOMPLETE, extension__status=Extension.STATUSES.INCOMPLETE,
extension__average_score=2.5, extension__average_score=2.5,
file__metadata={
'name': 'Test Add-on',
'support': 'https://example.com/issues/',
'website': 'https://example.com/',
},
).extension ).extension