Beispiel #1
0
    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
Beispiel #3
0
    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'
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
    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')
Beispiel #7
0
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))
Beispiel #8
0
    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
Beispiel #9
0
    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