in src/olympia/addons/fields.py [0: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).
"""
if isinstance(data, list):
# if it's a list of apps, normalize into a dict first
data = {key: {} for key in data}
if not isinstance(data, dict) or data == {}:
# if it's neither it's not a valid input
raise exceptions.ValidationError(gettext('Invalid value'))
version = self.parent.instance
existing = version.compatible_apps if version else {}
internal = {}
for app_name, min_max in data.items():
try:
app = amo.APPS[app_name]
except KeyError as exc:
raise exceptions.ValidationError(
gettext('Invalid app specified')
) from exc
existing_app = existing.get(app)
# we need to copy() to avoid changing the instance before save
apps_versions = copy.copy(existing_app) or ApplicationsVersions(
application=app.id, version=version
)
app_version_qs = AppVersion.objects.filter(application=app.id)
try:
if 'max' in min_max:
apps_versions.max = app_version_qs.get(version=min_max['max'])
apps_versions.min_or_max_explicitly_set = True
elif version:
apps_versions.max = apps_versions.get_default_maximum_appversion()
except AppVersion.DoesNotExist as exc:
raise exceptions.ValidationError(
gettext('Unknown max app version specified')
) from exc
try:
app_version_qs = app_version_qs.filter(~Q(version__contains='*'))
if 'min' in min_max:
apps_versions.min = app_version_qs.get(version=min_max['min'])
apps_versions.min_or_max_explicitly_set = True
elif version:
apps_versions.min = apps_versions.get_default_minimum_appversion()
except AppVersion.DoesNotExist as exc:
raise exceptions.ValidationError(
gettext('Unknown min app version specified')
) from exc
if existing_app and existing_app.locked_from_manifest:
if (
existing_app.min != apps_versions.min
or existing_app.max != apps_versions.max
):
raise exceptions.ValidationError(
gettext(
'Can not override compatibility information set in the '
'manifest for this application (%s)'
)
% app.pretty
)
else:
apps_versions.originated_from = (
amo.APPVERSIONS_ORIGINATED_FROM_DEVELOPER
)
internal[app] = apps_versions
# Also make sure no ApplicationsVersions that existed already and were
# locked because manifest is the source of truth are gone.
for app, apps_versions in existing.items():
if apps_versions.locked_from_manifest and app not in internal:
raise exceptions.ValidationError(
gettext(
'Can not override compatibility information set in the '
'manifest for this application (%s)'
)
% app.pretty
)
return internal