def to_string()

in src/olympia/activity/models.py [0:0]


    def to_string(self, type_=None):
        log_type = constants.activity.LOG_BY_ID[self.action]
        if type_ and hasattr(log_type, '%s_format' % type_):
            format = getattr(log_type, '%s_format' % type_)
        else:
            format = log_type.format
        absolute_url_method = (
            'get_admin_absolute_url' if type_ == 'admin' else 'get_absolute_url'
        )

        def get_absolute_url(obj):
            return getattr(obj, absolute_url_method)() if obj is not None else ''

        # We need to copy arguments so we can remove elements from it
        # while we loop over self.arguments.
        arguments = copy(self.arguments)
        addon = None
        addon_name = None
        addon_pk = None
        rating = None
        version = None
        collection = None
        tag = None
        group = None
        file_ = None
        status = None
        user = None
        channel = None
        _versions = []

        for arg in self.arguments:
            if isinstance(arg, Addon) and not addon:
                addon_pk = arg.pk
                addon_name = arg.name
                # _current_version_id as an approximation to see if the add-on
                # has listed versions without doing extra queries.
                if type_ == 'admin' or arg._current_version_id:
                    addon = format_html(
                        '<a href="{0}">{1}</a>', get_absolute_url(arg), addon_name
                    )
                else:
                    addon = format_html('{0}', arg.name)
                arguments.remove(arg)
            if isinstance(arg, Rating) and not rating:
                rating = format_html(
                    '<a href="{0}">{1}</a>', get_absolute_url(arg), gettext('Review')
                )
                arguments.remove(arg)
            if isinstance(arg, Version):
                # Versions can appear multiple time. Append to an intermediary
                # _versions list, and use that later to build the final
                # 'version' argument used for formatting.
                channel = arg.channel
                if type_ == 'admin' or (
                    type_ != 'reviewlog' and arg.channel == amo.CHANNEL_LISTED
                ):
                    _versions.append(
                        format_html(
                            '<a href="{0}">{1}</a>',
                            get_absolute_url(arg),
                            arg.version,
                        )
                    )
                else:
                    _versions.append(arg.version)
                arguments.remove(arg)
            if isinstance(arg, Collection) and not collection:
                collection = format_html(
                    '<a href="{0}">{1}</a>', get_absolute_url(arg), arg.name
                )
                arguments.remove(arg)
            if isinstance(arg, Tag) and not tag:
                if arg.can_reverse():
                    tag = format_html(
                        '<a href="{0}">{1}</a>', get_absolute_url(arg), arg.tag_text
                    )
                else:
                    tag = format_html('{0}', arg.tag_text)
            if isinstance(arg, Group) and not group:
                group = arg.name
                arguments.remove(arg)
            if isinstance(arg, File) and not file_:
                validation = 'passed'
                if self.action in (
                    amo.LOG.UNLISTED_SIGNED.id,
                    amo.LOG.UNLISTED_SIGNED_VALIDATION_FAILED.id,
                ):
                    validation = 'ignored'

                file_ = format_html(
                    '<a href="{0}">{1}</a> (validation {2})',
                    get_absolute_url(arg),
                    arg.pretty_filename,
                    validation,
                )
                arguments.remove(arg)
            if isinstance(arg, UserProfile) and not user:
                user = format_html(
                    '<a href="{0}">{1}</a>', get_absolute_url(arg), arg.name
                )
                arguments.remove(arg)
            if self.action == amo.LOG.CHANGE_STATUS.id and not isinstance(arg, Addon):
                # Unfortunately, this action has been abused in the past and
                # the non-addon argument could be a string or an int. If it's
                # an int, we want to retrieve the string and translate it.
                if isinstance(arg, int) and arg in amo.STATUS_CHOICES_ADDON:
                    status = gettext(amo.STATUS_CHOICES_ADDON[arg])
                else:
                    # It's not an int or not one of the choices, so assume it's
                    # a string or an unknown int we want to display as-is.
                    status = arg
                arguments.remove(arg)

        user_responsible = format_html(
            '<a href="{0}">{1}</a>', get_absolute_url(self.user), self.user.name
        )

        if _versions:
            # Now that all arguments have been processed we can build a string
            # for all the versions and build a string for addon that is
            # specific to the reviewlog, with the correct channel for the
            # review page link.
            version = format_html(
                ngettext('Version {0}', 'Versions {0}', len(_versions)),
                # We're only joining already escaped/safe content.
                mark_safe(', '.join(_versions)),
            )

        if channel is None and self.details and 'channel' in self.details:
            channel = self.details['channel']

        if type_ == 'reviewlog' and addon and addon_pk and addon_name:
            reverse_args = [addon_pk]
            if self.action in (amo.LOG.REJECT_CONTENT.id, amo.LOG.APPROVE_CONTENT.id):
                reverse_args.insert(0, 'content')
            elif channel and channel == amo.CHANNEL_UNLISTED:
                reverse_args.insert(0, 'unlisted')
            addon = format_html(
                '<a href="{0}">{1}</a>',
                reverse('reviewers.review', args=reverse_args),
                addon_name,
            )

        try:
            kw = {
                'addon': addon,
                'rating': rating,
                'version': version,
                'collection': collection,
                'tag': tag,
                'user': user,
                'user_responsible': user_responsible,
                'group': group,
                'file': file_,
                'status': status,
            }
            return format_html(str(format), *arguments, **kw)
        except (AttributeError, KeyError, IndexError):
            log.warning('%d contains garbage data' % (self.id or 0))
            return 'Something magical happened.'