def clean_changed_version_ids()

in src/olympia/blocklist/forms.py [0:0]


    def clean_changed_version_ids(self):
        data = self.cleaned_data.get('changed_version_ids', [])
        errors = []

        # First, check we're not creating empty blocks
        # we're checking new blocks for add/change; and all blocks for other actions
        for block in (bl for bl in self.blocks if not bl.id or not self.is_add_change):
            version_ids = [v.id for v in block.addon_versions]
            changed_ids = (v_id for v_id in data if v_id in version_ids)
            blocked_ids = (v.id for v in block.addon_versions if v.is_blocked)
            # for add/change we raise if there are no changed ids for this addon
            # for other actions, only if there is also at least one existing blocked
            # version
            if (self.is_add_change or any(blocked_ids)) and not any(changed_ids):
                errors.append(ValidationError(f'{block.guid} has no changed versions'))

        # Second, check for duplicate version strings in reused guids.
        error_string = (
            '{}:{} exists more than once. All {} versions must be selected together.'
        )
        for block in self.blocks:
            version_strs = defaultdict(set)  # collect version strings together
            for version in block.addon_versions:
                if version.id in self.changed_version_ids_choices:
                    version_strs[version.version].add(version.id)
            for version_str, ids in version_strs.items():
                # i.e. dupe version string & some ids, but not all, are being changed.
                if len(ids) > 1 and not ids.isdisjoint(data) and not ids.issubset(data):
                    errors.append(
                        ValidationError(
                            error_string.format(block.guid, version_str, version_str)
                        )
                    )

        if errors:
            raise ValidationError(errors)
        return data