def fake_version_object(self, obj, data): if data: version = Version( addon=obj, id=data['id'], reviewed=self.handle_date(data['reviewed']), version=data['version']) version.all_files = [ File( id=file_['id'], created=self.handle_date(file_['created']), hash=file_['hash'], filename=file_['filename'], platform=file_['platform'], size=file_['size'], status=file_['status'], version=version) for file_ in data.get('files', []) ] # In ES we store integers for the appversion info, we need to # convert it back to strings. compatible_apps = {} for app_id, compat_dict in data.get('compatible_apps', {}).items(): app_name = APPS_ALL[int(app_id)] compatible_apps[app_name] = ApplicationsVersions( min=AppVersion(version=compat_dict.get('min_human', '')), max=AppVersion(version=compat_dict.get('max_human', ''))) version.compatible_apps = compatible_apps else: version = None return version
def test_mozilla_app(self): moz = amo.MOZILLA appver = AppVersion.objects.create(application=moz.id) v = Addon.objects.get(id=3615).current_version ApplicationsVersions(application=moz.id, version=v, min=appver, max=appver).save() fs = forms.CompatFormSet(None, queryset=v.apps.all()) apps = [f.app for f in fs.forms] assert moz in apps
def test_add_not(self): for id in [18, 52, 59, 60, 61]: av = AppVersion(application=id, version='1') av.save() ApplicationsVersions(application=id, min=av, max=av, version=self.version).save() res = self.client.get(self.url) doc = pq(res.content) assert not res.context['compat_form'].extra_forms assert doc('p.add-app')[0].attrib['class'] == 'add-app hide'
def fake_object(self, data): """Create a fake instance of Addon and related models from ES data.""" obj = Addon(id=data['id'], slug=data['slug'], is_listed=True) data_version = data.get('current_version') if data_version: obj._current_version = Version(addon=obj, id=data_version['id'], reviewed=self.handle_date( data_version['reviewed']), version=data_version['version']) data_files = data_version.get('files', []) obj._current_version.all_files = [ File(id=file_['id'], created=self.handle_date(file_['created']), hash=file_['hash'], filename=file_['filename'], platform=file_['platform'], size=file_['size'], status=file_['status'], version=obj._current_version) for file_ in data_files ] # In ES we store integers for the appversion info, we need to # convert it back to strings. compatible_apps = {} for app_id, compat_dict in data['appversion'].items(): app_name = APPS_ALL[int(app_id)] compatible_apps[app_name] = ApplicationsVersions( min=AppVersion(version=compat_dict.get('min_human', '')), max=AppVersion(version=compat_dict.get('max_human', ''))) obj._current_version.compatible_apps = compatible_apps # Attach base attributes that have the same name/format in ES and in # the model. self._attach_fields( obj, data, ('average_daily_users', 'bayesian_rating', 'created', 'default_locale', 'guid', 'hotness', 'is_listed', 'last_updated', 'public_stats', 'slug', 'status', 'type', 'weekly_downloads')) # Attach attributes that do not have the same name/format in ES. obj.tag_list = data['tags'] obj.disabled_by_user = data['is_disabled'] # Not accurate, but enough. # Attach translations (they require special treatment). self._attach_translations(obj, data, self.translated_fields) return obj
def fake_version_object(self, obj, data, channel): if data: version = Version( addon=obj, id=data['id'], reviewed=self.handle_date(data['reviewed']), version=data['version'], channel=channel, ) version.all_files = [ self.fake_file_object(version, file_data) for file_data in data.get('files', []) ] # In ES we store integers for the appversion info, we need to # convert it back to strings. compatible_apps = {} for app_id, compat_dict in data.get('compatible_apps', {}).items(): app_name = APPS_ALL[int(app_id)] compatible_apps[app_name] = ApplicationsVersions( min=AppVersion(version=compat_dict.get('min_human', '')), max=AppVersion(version=compat_dict.get('max_human', '')), ) version._compatible_apps = compatible_apps version_serializer = self.fields.get('current_version') or None if version_serializer: version_serializer._attach_translations( version, data, version_serializer.translated_fields ) if 'license' in data and version_serializer: license_serializer = version_serializer.fields['license'] version.license = License(id=data['license']['id']) license_serializer._attach_fields( version.license, data['license'], ('builtin', 'url') ) # Can't use license_serializer._attach_translations() directly # because 'name' is a SerializerMethodField, not an # ESTranslatedField. license_serializer.db_name.attach_translations( version.license, data['license'], 'name' ) else: version.license = None else: version = None return version
def to_internal_value(self, data): """Note: this returns unsaved and incomplete ApplicationsVersions objects that need to have version set, and may have missing min or max AppVersion instances for new Version instances. (As intended - we want to be able to partially specify min or max and have the manifest or defaults be instead used). """ try: if isinstance(data, list): # if it's a list of apps, normalize into a dict first data = {key: {} for key in data} if isinstance(data, dict): version = self.parent.instance existing = version.compatible_apps if version else {} qs = AppVersion.objects internal = {} for app_name, min_max in data.items(): app = amo.APPS[app_name] apps_versions = existing.get( app, ApplicationsVersions(application=app.id)) app_qs = qs.filter(application=app.id) if 'max' in min_max: apps_versions.max = app_qs.get(version=min_max['max']) elif version: apps_versions.max = app_qs.get( version=amo.DEFAULT_WEBEXT_MAX_VERSION) app_qs = app_qs.exclude(version='*') if 'min' in min_max: apps_versions.min = app_qs.get(version=min_max['min']) elif version: apps_versions.min = app_qs.get( version=amo.DEFAULT_WEBEXT_MIN_VERSIONS[app]) internal[app] = apps_versions return internal else: # if it's neither it's not a valid input raise exceptions.ValidationError('Invalid value') except KeyError: raise exceptions.ValidationError('Invalid app specified') except AppVersion.DoesNotExist: raise exceptions.ValidationError('Unknown app version specified')
class SimpleVersionSerializer(MinimalVersionSerializer): compatibility = VersionCompatabilityField( # default to just Desktop Firefox; most of the times developers don't develop # their WebExtensions for Android. See https://bit.ly/2QaMicU source='compatible_apps', default=serializers.CreateOnlyDefault({ amo.APPS['firefox']: ApplicationsVersions(application=amo.APPS['firefox'].id) }), ) edit_url = serializers.SerializerMethodField() is_strict_compatibility_enabled = serializers.BooleanField( source='file.strict_compatibility', read_only=True) license = CompactLicenseSerializer() release_notes = TranslationSerializerField(required=False) class Meta: model = Version fields = ( 'id', 'compatibility', 'edit_url', 'file', 'is_strict_compatibility_enabled', 'license', 'release_notes', 'reviewed', 'version', ) read_only_fields = fields def to_representation(self, instance): # Help the LicenseSerializer find the version we're currently serializing. if 'license' in self.fields and instance.license: instance.license.version_instance = instance return super().to_representation(instance) def get_edit_url(self, obj): return absolutify( obj.addon.get_dev_url('versions.edit', args=[obj.pk], prefix_only=True))
def fake_version_object(self, obj, data, channel): if data: version = Version( addon=obj, id=data['id'], reviewed=self.handle_date(data['reviewed']), version=data['version'], channel=channel) version.all_files = [ self.fake_file_object(version, file_data) for file_data in data.get('files', []) ] # In ES we store integers for the appversion info, we need to # convert it back to strings. compatible_apps = {} for app_id, compat_dict in data.get('compatible_apps', {}).items(): app_name = APPS_ALL[int(app_id)] compatible_apps[app_name] = ApplicationsVersions( min=AppVersion(version=compat_dict.get('min_human', '')), max=AppVersion(version=compat_dict.get('max_human', ''))) version._compatible_apps = compatible_apps else: version = None return version
def fake_object(self, data): """Create a fake instance of Addon and related models from ES data.""" obj = Addon(id=data['id'], slug=data['slug'], is_listed=True) # Attach base attributes that have the same name/format in ES and in # the model. self._attach_fields( obj, data, ('average_daily_users', 'bayesian_rating', 'created', 'default_locale', 'guid', 'hotness', 'icon_type', 'is_listed', 'last_updated', 'modified', 'public_stats', 'slug', 'status', 'type', 'weekly_downloads')) # Temporary hack to make sure all add-ons have a modified date when # serializing, to avoid errors when calling get_icon_url(). # Remove once all add-ons have been reindexed at least once since the # addition of `modified` in the mapping. if obj.modified is None: obj.modified = obj.created # Attach attributes that do not have the same name/format in ES. obj.tag_list = data['tags'] obj.disabled_by_user = data['is_disabled'] # Not accurate, but enough. # Categories are annoying, skip them for now. We probably need to start # declaring them in the code to properly handle translations etc if we # want to display them in search results. obj.all_categories = [] # Attach translations (they require special treatment). self._attach_translations(obj, data, self.translated_fields) # Attach related models (also faking them). data_version = data.get('current_version') if data_version: obj._current_version = Version(addon=obj, id=data_version['id'], reviewed=self.handle_date( data_version['reviewed']), version=data_version['version']) data_files = data_version.get('files', []) obj._current_version.all_files = [ File(id=file_['id'], created=self.handle_date(file_['created']), hash=file_['hash'], filename=file_['filename'], platform=file_['platform'], size=file_['size'], status=file_['status'], version=obj._current_version) for file_ in data_files ] # In ES we store integers for the appversion info, we need to # convert it back to strings. compatible_apps = {} for app_id, compat_dict in data['appversion'].items(): app_name = APPS_ALL[int(app_id)] compatible_apps[app_name] = ApplicationsVersions( min=AppVersion(version=compat_dict.get('min_human', '')), max=AppVersion(version=compat_dict.get('max_human', ''))) obj._current_version.compatible_apps = compatible_apps if data['type'] == amo.ADDON_PERSONA: persona_data = data.get('persona') if persona_data: obj.persona = Persona( addon=obj, accentcolor=persona_data['accentcolor'], display_username=persona_data['author'], header=persona_data['header'], footer=persona_data['footer'], persona_id=1 if persona_data['is_new'] else None, textcolor=persona_data['textcolor']) else: # Sadly, https://code.djangoproject.com/ticket/14368 prevents # us from setting obj.persona = None. This is fixed in # Django 1.9, but in the meantime, work around it by creating # a Persona instance with a custom attribute indicating that # it should not be used. obj.persona = Persona() obj.persona._broken = True return obj