def to_internal_value()

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