* drop AppSupport model

* in language-tools api, application param only mandatory for appversion, and ignored otherwise

* Delete 0029_delete_appsupport.py
This commit is contained in:
Andrew Williamson 2021-01-19 16:07:59 +00:00 коммит произвёл GitHub
Родитель 2ba66a63b8
Коммит de374c4ceb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
24 изменённых файлов: 68 добавлений и 300 удалений

Просмотреть файл

@ -438,7 +438,7 @@ on AMO.
In addition, the results can be cached for up to 24 hours, based on the
full URL used in the request.
:query string app: Mandatory. Filter by :ref:`add-on application <addon-detail-application>` availability.
:query string app: Mandatory when ``appversion`` is present, ignored otherwise. Filter by :ref:`add-on application <addon-detail-application>` availability.
:query string appversion: Filter by application version compatibility. Pass the full version as a string, e.g. ``46.0``. Only valid when both the ``app`` and ``type`` parameters are also present, and only makes sense for Language Packs, since Dictionaries are always compatible with every application version.
:query string author: Filter by exact (listed) author username. Multiple author names can be specified, separated by comma(s), in which case add-ons with at least one matching author are returned.
:query string lang: Activate translations in the specific language for that query. (See :ref:`translated fields <api-overview-translations>`)

Просмотреть файл

@ -405,7 +405,7 @@ These are `v5` specific changes - `v4` changes apply also.
https://github.com/mozilla/addons-server/issues/16069
* 2021-01-07: changed API behavior with all fields that could be affected by ``wrap_outgoing_links``.
Now the url is an object containing both the original url and the wrapped url. See :ref:`Outgoing Links <api-overview-outgoing>`.
* 2021-01-21: in language-tools api, made ``application`` parameter only mandatory when ``appversion`` parameter is also present, and ignored otherwise. https://github.com/mozilla/addons-server/issues/12315
.. _`#11380`: https://github.com/mozilla/addons-server/issues/11380/
.. _`#11379`: https://github.com/mozilla/addons-server/issues/11379/

Просмотреть файл

@ -17,7 +17,6 @@ HOME=/tmp
15 * * * * %(django)s send_pending_rejection_last_warning_notifications
20 * * * * %(z_cron)s addon_last_updated
25 * * * * %(z_cron)s hide_disabled_files
45 * * * * %(z_cron)s update_addon_appsupport
55 * * * * %(z_cron)s unhide_disabled_files
# Four times per day

Просмотреть файл

@ -1,7 +1,6 @@
from datetime import date
from django.db.models import F, Q, Value, IntegerField
from celery import group
from django.db.models import Q, Value, IntegerField
import olympia.core.logger
@ -11,7 +10,6 @@ from olympia.addons.tasks import (
update_addon_average_daily_users as _update_addon_average_daily_users,
update_addon_hotness as _update_addon_hotness,
update_addon_weekly_downloads as _update_addon_weekly_downloads,
update_appsupport,
)
from olympia.amo.celery import create_chunked_tasks_signatures
from olympia.amo.decorators import use_primary_db
@ -92,27 +90,6 @@ def addon_last_updated():
_change_last_updated(dict(other))
def update_addon_appsupport():
# Find all the add-ons that need their app support details updated.
newish = Q(last_updated__gte=F('appsupport__created')) | Q(
appsupport__created__isnull=True
)
has_app_and_file = Q(
versions__apps__isnull=False,
versions__files__status__in=amo.VALID_FILE_STATUSES,
)
ids = (
Addon.objects.valid()
.distinct()
.filter(newish, has_app_and_file)
.values_list('id', flat=True)
)
task_log.info('Updating appsupport for %d new-ish addons.' % len(ids))
ts = [update_appsupport.subtask(args=[chunk]) for chunk in chunked(ids, 20)]
group(ts).apply_async()
def hide_disabled_files():
"""
Move files (on filesystem) belonging to disabled files (in database) to the

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 117445,
"model": "versions.version",
"fields": {
@ -104,16 +103,6 @@
"total_ratings": 0
}
},
{
"pk": 999999,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 228106,
"modified": "2010-10-02 07:22:41",
"created": "2010-10-02 07:22:41"
}
},
{
"pk": 5468632,
"model": "users.userprofile",
@ -147,4 +136,4 @@
"addon": 228106
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 1174945,
"model": "versions.version",
"fields": {
@ -116,16 +115,6 @@
"total_ratings": 0
}
},
{
"pk": 9999991,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 228107,
"modified": "2010-10-02 07:22:41",
"created": "2010-10-02 07:22:41"
}
},
{
"pk": 54686910,
"model": "users.userprofile",
@ -192,4 +181,4 @@
"addon": 228107
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 5,
"model": "versions.license",
"fields": {
@ -84,15 +83,5 @@
"version": 89774,
"min": 290
}
},
{
"pk": 1118,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 3723,
"modified": "2010-10-02 07:22:41",
"created": "2010-10-02 07:22:41"
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 1,
"model": "addons.addon",
"fields": {
@ -165,15 +164,5 @@
"datestatuschanged": null,
"size": 173056
}
},
{
"pk": 1186,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 1,
"modified": "2010-10-02 07:30:34",
"created": "2010-10-02 07:30:34"
}
}
]
]

Просмотреть файл

@ -2224,26 +2224,6 @@ models.signals.post_delete.connect(
)
class AppSupport(ModelBase):
"""Cache to tell us if an add-on's current version supports an app."""
id = PositiveAutoField(primary_key=True)
addon = models.ForeignKey(Addon, on_delete=models.CASCADE)
app = models.PositiveIntegerField(choices=amo.APPS_CHOICES, db_column='app_id')
min = models.BigIntegerField('Minimum app version', null=True)
max = models.BigIntegerField('Maximum app version', null=True)
class Meta:
db_table = 'appsupport'
indexes = [
models.Index(fields=('addon', 'app', 'min', 'max'), name='minmax_idx'),
models.Index(fields=('app',), name='app_id_refs_id_481ce338'),
]
constraints = [
models.UniqueConstraint(fields=('addon', 'app'), name='addon_id'),
]
class DeniedSlug(ModelBase):
name = models.CharField(max_length=255, unique=True, default='')

Просмотреть файл

@ -14,7 +14,6 @@ from olympia import amo
from olympia.addons.indexers import AddonIndexer
from olympia.addons.models import (
Addon,
AppSupport,
DeniedGuid,
Preview,
attach_tags,
@ -46,32 +45,6 @@ def version_changed(addon_id, **kw):
return
log.info('[1@None] Updating last updated for %s.' % addon.pk)
addon.update(last_updated=compute_last_updated(addon))
update_appsupport([addon.pk])
@task
@use_primary_db
def update_appsupport(ids, **kw):
log.info('[%s@None] Updating appsupport for %s.' % (len(ids), ids))
addons = Addon.objects.filter(id__in=ids).no_transforms()
support = []
for addon in addons:
for app, appver in addon.compatible_apps.items():
if appver is None:
# Fake support for all version ranges.
min_, max_ = 0, 999999999999999999
else:
min_, max_ = appver.min.version_int, appver.max.version_int
support.append(AppSupport(addon=addon, app=app.id, min=min_, max=max_))
if not support:
return
with transaction.atomic():
AppSupport.objects.filter(addon__id__in=ids).delete()
AppSupport.objects.bulk_create(support)
@task

Просмотреть файл

@ -13,7 +13,7 @@ from olympia.addons.tasks import (
update_addon_average_daily_users,
update_addon_weekly_downloads,
)
from olympia.addons.models import Addon, AppSupport, FrozenAddon
from olympia.addons.models import Addon, FrozenAddon
from olympia.amo.tests import addon_factory, file_factory, TestCase
from olympia.files.models import File
from olympia.versions.models import Version
@ -40,21 +40,6 @@ class TestLastUpdated(TestCase):
for addon in Addon.objects.filter(status=amo.STATUS_APPROVED):
assert addon.last_updated == addon.created
def test_appsupport(self):
ids = Addon.objects.values_list('id', flat=True)
cron.update_appsupport(ids)
assert AppSupport.objects.filter(app=amo.FIREFOX.id).count() == 2
# Run it again to test deletes.
cron.update_appsupport(ids)
assert AppSupport.objects.filter(app=amo.FIREFOX.id).count() == 2
def test_appsupport_listed(self):
AppSupport.objects.all().delete()
assert AppSupport.objects.filter(addon=3723).count() == 0
cron.update_addon_appsupport()
assert AppSupport.objects.filter(addon=3723, app=amo.FIREFOX.id).count() == 0
class TestHideDisabledFiles(TestCase):
msg = 'Moving disabled file: {source} => {destination}'

Просмотреть файл

@ -19,7 +19,6 @@ from olympia.addons.models import (
AddonRegionalRestrictions,
AddonReviewerFlags,
AddonUser,
AppSupport,
Category,
DeniedGuid,
DeniedSlug,
@ -2184,7 +2183,6 @@ class TestAddonDelete(TestCase):
addon=addon, category=Category.objects.create(type=amo.ADDON_EXTENSION)
)
AddonUser.objects.create(addon=addon, user=UserProfile.objects.create())
AppSupport.objects.create(addon=addon, app=1)
FrozenAddon.objects.create(addon=addon)
AddonLog.objects.create(

Просмотреть файл

@ -3,6 +3,7 @@ import json
from unittest import mock
from django.core.cache import cache
from django.test.utils import override_settings
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_encode, urlunquote
@ -2419,14 +2420,13 @@ class TestLanguageToolsView(TestCase):
super(TestLanguageToolsView, self).setUp()
self.url = reverse_ns('addon-language-tools')
def test_wrong_app_or_no_app(self):
response = self.client.get(self.url)
def test_wrong_app(self):
response = self.client.get(self.url, {'app': 'foo', 'appversion': '57.0'})
assert response.status_code == 400
assert response.data == {'detail': 'Invalid or missing app parameter.'}
response = self.client.get(self.url, {'app': 'foo'})
assert response.status_code == 400
assert response.data == {'detail': 'Invalid or missing app parameter.'}
assert response.data == {
'detail': 'Invalid or missing app parameter while appversion parameter '
'is set.'
}
def test_basic(self):
dictionary = addon_factory(type=amo.ADDON_DICT, target_locale='fr')
@ -2481,6 +2481,14 @@ class TestLanguageToolsView(TestCase):
'parameter is set.'
}
def test_with_appversion_but_no_application(self):
response = self.client.get(self.url, {'appversion': '57.0'})
assert response.status_code == 400
assert response.data == {
'detail': 'Invalid or missing app parameter while appversion parameter '
'is set.'
}
def test_with_invalid_appversion(self):
response = self.client.get(
self.url, {'app': 'firefox', 'type': 'language', 'appversion': 'foôbar'}
@ -2702,9 +2710,11 @@ class TestLanguageToolsView(TestCase):
assert expected_versions == returned_versions
def test_memoize(self):
cache.clear()
super_author = user_factory(username='super')
addon_factory(type=amo.ADDON_DICT, target_locale='fr', users=(super_author,))
addon_factory(type=amo.ADDON_DICT, target_locale='fr')
addon_factory(type=amo.ADDON_DICT, target_locale='fr')
addon_factory(type=amo.ADDON_LPAPP, target_locale='es')
addon_factory(type=amo.ADDON_LPAPP, target_locale='es', users=(super_author,))
with self.assertNumQueries(2):
response = self.client.get(self.url, {'app': 'firefox', 'lang': 'fr'})
@ -2718,13 +2728,14 @@ class TestLanguageToolsView(TestCase):
).content == (response.content)
with self.assertNumQueries(2):
assert (
self.client.get(self.url, {'app': 'android', 'lang': 'fr'}).content
!= response.content
)
assert self.client.get(
self.url, {'app': 'firefox', 'lang': 'fr', 'author': 'super'}
).content != (response.content)
# Same again, should be cached; no queries.
with self.assertNumQueries(0):
self.client.get(self.url, {'app': 'android', 'lang': 'fr'})
self.client.get(
self.url, {'app': 'firefox', 'lang': 'fr', 'author': 'super'}
)
# Change the lang, we should get queries again.
with self.assertNumQueries(2):
self.client.get(self.url, {'app': 'firefox', 'lang': 'de'})

Просмотреть файл

@ -576,7 +576,7 @@ class LanguageToolsView(ListAPIView):
def get_query_params(self):
"""
Parse query parameters that this API supports:
- app (mandatory)
- app (ignored unless appversion, then mandatory)
- type (optional)
- appversion (optional, makes type mandatory)
- author (optional)
@ -587,14 +587,16 @@ class LanguageToolsView(ListAPIView):
Returns a dict containing application (int), types (tuple or None),
appversions (dict or None) and author (string or None).
"""
# app parameter is mandatory when calling this API.
try:
application = AddonAppQueryParam(self.request.GET).get_value()
except ValueError:
raise exceptions.ParseError('Invalid or missing app parameter.')
# appversion parameter is optional.
if AddonAppVersionQueryParam.query_param in self.request.GET:
# app parameter is mandatory with appversion
try:
application = AddonAppQueryParam(self.request.GET).get_value()
except ValueError:
raise exceptions.ParseError(
'Invalid or missing app parameter while appversion parameter is '
'set.'
)
try:
value = AddonAppVersionQueryParam(self.request.GET).get_values()
appversions = {'min': value[1], 'max': value[2]}
@ -602,6 +604,7 @@ class LanguageToolsView(ListAPIView):
raise exceptions.ParseError('Invalid appversion parameter.')
else:
appversions = None
application = None
# type is optional, unless appversion is set. That's because the way
# dicts and language packs have their compatibility info set in the
@ -643,9 +646,7 @@ class LanguageToolsView(ListAPIView):
params['application'], params['appversions']
)
else:
# appversions filtering only makes sense for language packs only,
# so it's ignored here.
qs = self.get_queryset_base(params['application'], params['types'])
qs = self.get_queryset_base(params['types'])
if params['authors']:
qs = qs.filter(
@ -653,7 +654,7 @@ class LanguageToolsView(ListAPIView):
).distinct()
return qs
def get_queryset_base(self, application, addon_types):
def get_queryset_base(self, addon_types):
"""
Return base queryset to be used as the starting point in both
get_queryset() and get_language_packs_queryset_with_appversions().
@ -661,7 +662,6 @@ class LanguageToolsView(ListAPIView):
return (
Addon.objects.public()
.filter(
appsupport__app=application,
type__in=addon_types,
target_locale__isnull=False,
)
@ -687,7 +687,7 @@ class LanguageToolsView(ListAPIView):
and max keys pointing to application versions expressed as ints.
"""
# Base queryset.
qs = self.get_queryset_base(application, (amo.ADDON_LPAPP,))
qs = self.get_queryset_base((amo.ADDON_LPAPP,))
# Version queryset we'll prefetch once for all results. We need to
# find the ones compatible with the app+appversion requested, and we
# can avoid loading translations by removing transforms and then

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 426250,
"model": "translations.translation",
"fields": {
@ -149,15 +148,5 @@
"min": 233,
"max": 303
}
},
{
"pk": 3,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 1833,
"modified": "2010-10-04 13:01:45",
"created": "2010-10-04 13:01:45"
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 418039,
"model": "translations.translation",
"fields": {
@ -347,15 +346,5 @@
"category": 71,
"addon": 3615
}
},
{
"pk": 1028,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 3615,
"modified": "2010-10-01 21:37:07",
"created": "2010-10-01 21:37:07"
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 4283,
"model": "translations.translation",
"fields": {
@ -131,15 +130,5 @@
"min": 42,
"max": 123
}
},
{
"pk": 1208,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 40,
"modified": "2010-10-04 13:05:21",
"created": "2010-10-04 13:05:21"
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 4664,
"model": "translations.translation",
"fields": {
@ -280,15 +279,5 @@
},
"model": "addons.preview",
"pk": 20397
},
{
"pk": 1214,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 4664,
"modified": "2010-10-04 13:10:38",
"created": "2010-10-04 13:10:38"
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 90914,
"model": "translations.translation",
"fields": {
@ -171,15 +170,5 @@
"min": 1,
"max": 307
}
},
{
"pk": 1237,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 5299,
"modified": "2010-10-25 18:09:30",
"created": "2010-10-25 18:09:30"
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 93222,
"model": "translations.translation",
"fields": {
@ -135,15 +134,5 @@
"min": 233,
"max": 291
}
},
{
"pk": 1211,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 5369,
"modified": "2010-10-04 13:05:21",
"created": "2010-10-04 13:05:21"
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 476453,
"model": "translations.translation",
"fields": {
@ -145,15 +144,5 @@
"min": 82,
"max": 314
}
},
{
"pk": 1195,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 592,
"modified": "2010-10-02 07:44:05",
"created": "2010-10-02 07:44:05"
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 117839,
"model": "translations.translation",
"fields": {
@ -129,15 +128,5 @@
"min": 82,
"max": 291
}
},
{
"pk": 1216,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 6113,
"modified": "2010-10-04 13:10:38",
"created": "2010-10-04 13:10:38"
}
}
]
]

Просмотреть файл

@ -1,5 +1,4 @@
[
{
[{
"pk": 638212,
"model": "translations.translation",
"fields": {
@ -384,25 +383,5 @@
"datestatuschanged": "2009-05-08 05:26:20",
"size": 3072
}
},
{
"pk": 1042,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 7661,
"modified": "2010-10-01 22:09:39",
"created": "2010-10-01 22:09:39"
}
},
{
"pk": 1041,
"model": "addons.appsupport",
"fields": {
"app": 1,
"addon": 2464,
"modified": "2010-10-01 22:09:39",
"created": "2010-10-01 22:09:39"
}
}
]
]

Просмотреть файл

@ -1125,7 +1125,6 @@ CELERY_TASK_ROUTES = {
'olympia.addons.tasks.update_addon_average_daily_users': {'queue': 'cron'},
'olympia.addons.tasks.update_addon_hotness': {'queue': 'cron'},
'olympia.addons.tasks.update_addon_weekly_downloads': {'queue': 'cron'},
'olympia.addons.tasks.update_appsupport': {'queue': 'cron'},
# Bandwagon
'olympia.bandwagon.tasks.collection_meta': {'queue': 'bandwagon'},
# Reviewers
@ -1712,7 +1711,6 @@ CRON_JOBS = {
'update_addon_average_daily_users': 'olympia.addons.cron',
'update_addon_weekly_downloads': 'olympia.addons.cron',
'addon_last_updated': 'olympia.addons.cron',
'update_addon_appsupport': 'olympia.addons.cron',
'hide_disabled_files': 'olympia.addons.cron',
'unhide_disabled_files': 'olympia.addons.cron',
'update_addon_hotness': 'olympia.addons.cron',