コード例 #1
0
ファイル: test_models.py プロジェクト: kmaglione/zamboni
    def test_signature_parity(self):
        # Test flags -> signature -> flags works as expected.
        self._flag()
        signature = self.app.current_version.features.to_signature()
        eq_(signature.count('.'), 2, 'Unexpected signature format')

        af = AppFeatures(version=self.app.current_version)
        af.set_flags(signature)
        self._check(af)
コード例 #2
0
ファイル: test_models.py プロジェクト: at13/zamboni
    def test_signature_parity(self):
        # Test flags -> signature -> flags works as expected.
        self._flag()
        signature = self.app.current_version.features.to_signature()
        eq_(signature.count('.'), 2, 'Unexpected signature format')

        af = AppFeatures(version=self.app.current_version)
        af.set_flags(signature)
        self._check(af)
コード例 #3
0
    def get_changed_features(self):
        old_features = dict.fromkeys(self.initial_feature_keys, True)
        old_features = set(AppFeatures(**old_features).to_names())
        new_features = set(self.instance.to_names())

        added_features = new_features - old_features
        removed_features = old_features - new_features
        return added_features, removed_features
コード例 #4
0
ファイル: forms.py プロジェクト: miltonpereira/zamboni
    def _changed_features(self):
        old_features = defaultdict.fromkeys(self.initial_features, True)
        old_features = set(
            unicode(f) for f in AppFeatures(**old_features).to_list())
        new_features = set(unicode(f) for f in self.instance.to_list())

        added_features = new_features - old_features
        removed_features = old_features - new_features
        return added_features, removed_features
コード例 #5
0
ファイル: indexers.py プロジェクト: miltonpereira/zamboni
    def extract_document(cls, pk=None, obj=None):
        """Extracts the ElasticSearch index document for this instance."""
        from mkt.webapps.models import (AppFeatures, attach_devices,
                                        attach_prices, attach_tags,
                                        attach_translations, Geodata,
                                        Installed, RatingDescriptors,
                                        RatingInteractives)

        if obj is None:
            obj = cls.get_model().objects.no_cache().get(pk=pk)

        # Attach everything we need to index apps.
        for transform in (attach_devices, attach_prices, attach_tags,
                          attach_translations):
            transform([obj])

        latest_version = obj.latest_version
        version = obj.current_version
        geodata = obj.geodata
        features = (version.features.to_dict()
                    if version else AppFeatures().to_dict())

        try:
            status = latest_version.statuses[0][1] if latest_version else None
        except IndexError:
            status = None

        installed_ids = list(Installed.objects.filter(addon=obj)
                             .values_list('id', flat=True))

        attrs = ('app_slug', 'bayesian_rating', 'created', 'id', 'is_disabled',
                 'last_updated', 'modified', 'premium_type', 'status',
                 'uses_flash', 'weekly_downloads')
        d = dict(zip(attrs, attrgetter(*attrs)(obj)))

        d['boost'] = len(installed_ids) or 1
        d['app_type'] = obj.app_type_id
        d['author'] = obj.developer_name
        d['banner_regions'] = geodata.banner_regions_slugs()
        d['category'] = obj.categories if obj.categories else []
        if obj.is_published:
            d['collection'] = [{'id': cms.collection_id, 'order': cms.order}
                               for cms in obj.collectionmembership_set.all()]
        else:
            d['collection'] = []
        d['content_ratings'] = (obj.get_content_ratings_by_body(es=True) or
                                None)
        try:
            d['content_descriptors'] = obj.rating_descriptors.to_keys()
        except RatingDescriptors.DoesNotExist:
            d['content_descriptors'] = []
        d['current_version'] = version.version if version else None
        d['default_locale'] = obj.default_locale
        d['description'] = list(
            set(string for _, string in obj.translations[obj.description_id]))
        d['device'] = getattr(obj, 'device_ids', [])
        d['features'] = features
        d['has_public_stats'] = obj.public_stats
        d['icon_hash'] = obj.icon_hash
        try:
            d['interactive_elements'] = obj.rating_interactives.to_keys()
        except RatingInteractives.DoesNotExist:
            d['interactive_elements'] = []
        d['is_escalated'] = obj.escalationqueue_set.exists()
        d['is_offline'] = getattr(obj, 'is_offline', False)
        d['is_priority'] = obj.priority_review
        d['is_rereviewed'] = obj.rereviewqueue_set.exists()
        if latest_version:
            d['latest_version'] = {
                'status': status,
                'is_privileged': latest_version.is_privileged,
                'has_editor_comment': latest_version.has_editor_comment,
                'has_info_request': latest_version.has_info_request,
                'nomination_date': latest_version.nomination,
                'created_date': latest_version.created,
            }
        else:
            d['latest_version'] = {
                'status': None,
                'is_privileged': None,
                'has_editor_comment': None,
                'has_info_request': None,
                'nomination_date': None,
                'created_date': None,
            }
        d['manifest_url'] = obj.get_manifest_url()
        d['package_path'] = obj.get_package_path()
        d['name'] = list(
            set(string for _, string in obj.translations[obj.name_id]))
        d['name_sort'] = unicode(obj.name).lower()
        d['owners'] = [au.user.id for au in
                       obj.addonuser_set.filter(role=amo.AUTHOR_ROLE_OWNER)]
        d['popularity'] = len(installed_ids)
        d['previews'] = [{'filetype': p.filetype, 'modified': p.modified,
                          'id': p.id, 'sizes': p.sizes}
                         for p in obj.previews.all()]
        try:
            p = obj.addonpremium.price
            d['price_tier'] = p.name
        except AddonPremium.DoesNotExist:
            d['price_tier'] = None

        d['ratings'] = {
            'average': obj.average_rating,
            'count': obj.total_reviews,
        }
        d['region_exclusions'] = obj.get_excluded_region_ids()
        d['reviewed'] = obj.versions.filter(
            deleted=False).aggregate(Min('reviewed')).get('reviewed__min')
        if version:
            d['supported_locales'] = filter(
                None, version.supported_locales.split(','))
        else:
            d['supported_locales'] = []

        d['tags'] = getattr(obj, 'tag_list', [])
        if obj.upsell and obj.upsell.premium.is_published():
            upsell_obj = obj.upsell.premium
            d['upsell'] = {
                'id': upsell_obj.id,
                'app_slug': upsell_obj.app_slug,
                'icon_url': upsell_obj.get_icon_url(128),
                # TODO: Store all localizations of upsell.name.
                'name': unicode(upsell_obj.name),
                'region_exclusions': upsell_obj.get_excluded_region_ids()
            }

        d['versions'] = [dict(version=v.version,
                              resource_uri=reverse_version(v))
                         for v in obj.versions.all()]

        # Handle our localized fields.
        for field in ('description', 'homepage', 'name', 'support_email',
                      'support_url'):
            d['%s_translations' % field] = [
                {'lang': to_language(lang), 'string': string}
                for lang, string
                in obj.translations[getattr(obj, '%s_id' % field)]
                if string]
        if version:
            attach_trans_dict(Version, [version])
            d['release_notes_translations'] = [
                {'lang': to_language(lang), 'string': string}
                for lang, string
                in version.translations[version.releasenotes_id]]
        else:
            d['release_notes_translations'] = None
        attach_trans_dict(Geodata, [geodata])
        d['banner_message_translations'] = [
            {'lang': to_language(lang), 'string': string}
            for lang, string
            in geodata.translations[geodata.banner_message_id]]

        for region in mkt.regions.ALL_REGION_IDS:
            d['popularity_%s' % region] = d['popularity']

        # Bump the boost if the add-on is public.
        if obj.status == amo.STATUS_PUBLIC:
            d['boost'] = max(d['boost'], 1) * 4

        # If the app is compatible with Firefox OS, push suggestion data in the
        # index - This will be used by RocketbarView API, which is specific to
        # Firefox OS.
        if DEVICE_GAIA.id in d['device'] and obj.is_published():
            d['name_suggest'] = {
                'input': d['name'],
                'output': unicode(obj.id),  # We only care about the payload.
                'weight': d['boost'],
                'payload': {
                    'default_locale': d['default_locale'],
                    'icon_hash': d['icon_hash'],
                    'id': d['id'],
                    'manifest_url': d['manifest_url'],
                    'modified': d['modified'],
                    'name_translations': d['name_translations'],
                    'slug': d['app_slug'],
                }
            }

        # Indices for each language. languages is a list of locales we want to
        # index with analyzer if the string's locale matches.
        for analyzer, languages in amo.SEARCH_ANALYZER_MAP.iteritems():
            if (not settings.ES_USE_PLUGINS and
                analyzer in amo.SEARCH_ANALYZER_PLUGINS):
                continue

            d['name_' + analyzer] = list(
                set(string for locale, string in obj.translations[obj.name_id]
                    if locale.lower() in languages))
            d['description_' + analyzer] = list(
                set(string for locale, string
                    in obj.translations[obj.description_id]
                    if locale.lower() in languages))

        return d
コード例 #6
0
 def test_correct_fields(self):
     fields = self.form.fields
     f_values = fields.values()
     assert 'version' not in fields
     assert all(isinstance(f, BooleanField) for f in f_values)
     self.assertSetEqual(fields, AppFeatures()._fields())
コード例 #7
0
    def extract_document(cls, pk=None, obj=None):
        """Extracts the ElasticSearch index document for this instance."""
        from mkt.webapps.models import (AppFeatures, attach_devices,
                                        attach_prices, attach_translations,
                                        RatingDescriptors, RatingInteractives)

        if obj is None:
            obj = cls.get_model().objects.get(pk=pk)

        # Attach everything we need to index apps.
        for transform in (attach_devices, attach_prices, attach_tags,
                          attach_translations):
            transform([obj])

        latest_version = obj.latest_version
        version = obj.current_version
        features = (version.features.to_dict()
                    if version else AppFeatures().to_dict())

        try:
            status = latest_version.statuses[0][1] if latest_version else None
        except IndexError:
            status = None

        attrs = ('app_slug', 'bayesian_rating', 'created', 'default_locale',
                 'guid', 'hosted_url', 'icon_hash', 'id', 'is_disabled',
                 'is_offline', 'file_size', 'last_updated', 'modified',
                 'premium_type', 'promo_img_hash', 'status')
        d = dict(zip(attrs, attrgetter(*attrs)(obj)))

        d['app_type'] = obj.app_type_id
        d['author'] = obj.developer_name
        d['category'] = obj.categories if obj.categories else []
        d['content_ratings'] = (obj.get_content_ratings_by_body(es=True)
                                or None)
        try:
            d['content_descriptors'] = obj.rating_descriptors.to_keys()
        except RatingDescriptors.DoesNotExist:
            d['content_descriptors'] = []
        d['current_version'] = version.version if version else None
        d['device'] = getattr(obj, 'device_ids', [])
        d['features'] = features
        d['has_public_stats'] = obj.public_stats
        try:
            d['interactive_elements'] = obj.rating_interactives.to_keys()
        except RatingInteractives.DoesNotExist:
            d['interactive_elements'] = []
        d['installs_allowed_from'] = (version.manifest.get(
            'installs_allowed_from', ['*']) if version else ['*'])
        d['is_priority'] = obj.priority_review

        is_escalated = obj.escalationqueue_set.exists()
        d['is_escalated'] = is_escalated
        d['escalation_date'] = (obj.escalationqueue_set.get().created
                                if is_escalated else None)
        is_rereviewed = obj.rereviewqueue_set.exists()
        d['is_rereviewed'] = is_rereviewed
        d['rereview_date'] = (obj.rereviewqueue_set.get().created
                              if is_rereviewed else None)

        if latest_version:
            d['latest_version'] = {
                'status': status,
                'is_privileged': latest_version.is_privileged,
                'has_editor_comment': latest_version.has_editor_comment,
                'has_info_request': latest_version.has_info_request,
                'nomination_date': latest_version.nomination,
                'created_date': latest_version.created,
            }
        else:
            d['latest_version'] = {
                'status': None,
                'is_privileged': None,
                'has_editor_comment': None,
                'has_info_request': None,
                'nomination_date': None,
                'created_date': None,
            }
        d['manifest_url'] = obj.get_manifest_url()
        d['package_path'] = obj.get_package_path()
        d['name_sort'] = unicode(obj.name).lower()
        d['owners'] = [
            au.user.id
            for au in obj.addonuser_set.filter(role=mkt.AUTHOR_ROLE_OWNER)
        ]

        d['previews'] = [{
            'filetype': p.filetype,
            'modified': p.modified,
            'id': p.id,
            'sizes': p.sizes
        } for p in obj.previews.all()]
        try:
            p = obj.addonpremium.price
            d['price_tier'] = p.name
        except AddonPremium.DoesNotExist:
            d['price_tier'] = None

        d['ratings'] = {
            'average': obj.average_rating,
            'count': obj.total_reviews,
        }
        d['region_exclusions'] = obj.get_excluded_region_ids()
        d['reviewed'] = obj.versions.filter(deleted=False).aggregate(
            Min('reviewed')).get('reviewed__min')

        # The default locale of the app is considered "supported" by default.
        supported_locales = [obj.default_locale]
        other_locales = (filter(None, version.supported_locales.split(','))
                         if version else [])
        if other_locales:
            supported_locales.extend(other_locales)
        d['supported_locales'] = list(set(supported_locales))

        d['tags'] = getattr(obj, 'tags_list', [])
        d['tv_featured'] = obj.tags.filter(tag_text='featured-tv').exists()

        if obj.upsell and obj.upsell.premium.is_published():
            upsell_obj = obj.upsell.premium
            d['upsell'] = {
                'id': upsell_obj.id,
                'app_slug': upsell_obj.app_slug,
                'icon_url': upsell_obj.get_icon_url(128),
                # TODO: Store all localizations of upsell.name.
                'name': unicode(upsell_obj.name),
                'region_exclusions': upsell_obj.get_excluded_region_ids()
            }

        d['versions'] = [
            dict(version=v.version, resource_uri=reverse_version(v))
            for v in obj.versions.all()
        ]

        # Handle localized fields.
        # This adds both the field used for search and the one with
        # all translations for the API.
        for field in ('description', 'name'):
            d.update(
                cls.extract_field_translations(obj,
                                               field,
                                               include_field_for_search=True))
        # This adds only the field with all the translations for the API, we
        # don't need to search on those.
        for field in ('homepage', 'support_email', 'support_url'):
            d.update(cls.extract_field_translations(obj, field))

        if version:
            attach_trans_dict(version._meta.model, [version])
            d.update(
                cls.extract_field_translations(version,
                                               'release_notes',
                                               db_field='releasenotes_id'))
        else:
            d['release_notes_translations'] = None

        # Add boost, popularity, trending values.
        d.update(cls.extract_popularity_trending_boost(obj))

        # If the app is compatible with Firefox OS, push suggestion data in the
        # index - This will be used by RocketbarView API, which is specific to
        # Firefox OS.
        if DEVICE_GAIA.id in d['device'] and obj.is_published():
            d['name_suggest'] = {
                'input': d['name'],
                'output': unicode(obj.id),  # We only care about the payload.
                'weight': int(d['boost']),
                'payload': {
                    'default_locale': d['default_locale'],
                    'icon_hash': d['icon_hash'],
                    'id': d['id'],
                    'manifest_url': d['manifest_url'],
                    'modified': d['modified'],
                    'name_translations': d['name_translations'],
                    'slug': d['app_slug'],
                }
            }

        for field in ('name', 'description'):
            d.update(cls.extract_field_analyzed_translations(obj, field))

        return d
コード例 #8
0
ファイル: test_models.py プロジェクト: kmaglione/zamboni
 def test_bad_data(self):
     af = AppFeatures(version=self.app.current_version)
     af.set_flags('foo')
     af.set_flags('<script>')
コード例 #9
0
ファイル: test_tasks.py プロジェクト: at13/zamboni
 def test_validator(self):
     update_features(ids=(self.app.pk, ))
     assert self.mock_validator.called
     features = self.app.current_version.features.to_dict()
     eq_(AppFeatures().to_dict(), features)
コード例 #10
0
ファイル: test_models.py プロジェクト: at13/zamboni
 def test_bad_data(self):
     af = AppFeatures(version=self.app.current_version)
     af.set_flags('foo')
     af.set_flags('<script>')
コード例 #11
0
 def _flag(self):
     "Flag app with a handful of feature flags for testing."
     af = AppFeatures(version=self.app.current_version)
     for f in self.flags:
         setattr(af, 'has_%s' % f.lower(), True)
     af.save()