This file is indexed.

/usr/lib/python2.7/dist-packages/oops_amqp/publisher.py is in python-oops-amqp 0.0.7-0ubuntu2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
# Copyright (c) 2011, Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, version 3 only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# GNU Lesser General Public License version 3 (see the file LICENSE).

"""Publish OOPS reports over amqp."""

__metaclass__ = type

from hashlib import md5
from threading import local

from amqplib import client_0_8 as amqp
from anybson import dumps

from utils import (
    amqplib_error_types,
    is_amqplib_connection_error,
    )

__all__ = [
    'Publisher',
    ]

class Publisher:
    """Publish OOPS reports over AMQP.
    
    Messages are published as bson dicts via durable messages sent to a
    supplied exchange + routing key.
    """

    def __init__(self, connection_factory, exchange_name, routing_key,
            inherit_id=False):
        """Create a publisher.

        :param connection_factory: A callable which creates an amqplib
            Connection when called. This is used to create connections - one
            per thread which OOPS publishing happens in. This is because
            amqplib is not threadsafe and recommends not sharing connections
            across threads.
        :param exchange_name: The name of the exchange to publish to.
        :param routing_key: The routing key for messages.
        :param inherit_id: If True any 'True' 'id' in an OOPS report is
            preserved. Handy if an id that has already been shown to a user is
            being published (but uniqueness cannot be guaranteed).
        """
        self.connection_factory = connection_factory
        self.exchange_name = exchange_name
        self.routing_key = routing_key
        self.channels = local()
        self.inherit_id = inherit_id

    def get_channel(self):
        if getattr(self.channels, 'channel', None) is None:
            try:
                self.channels.channel = self.connection_factory().channel()
            except amqplib_error_types, e:
                if is_amqplib_connection_error(e):
                    # Could not connect
                    return None
                # Unknown error mode : don't hide it.
                raise
        return self.channels.channel

    def __call__(self, report):
        # Don't mess with the passed in report.
        report = dict(report)
        if not self.inherit_id or not report.get('id'):
            # Discard any existing id.
            original_id = report.pop('id', None)
            # Hash it, to make an ID
            oops_id = "OOPS-%s" % md5(dumps(report)).hexdigest()
            # Store the id in what we send on the wire, so that the recipient
            # has it.
            report['id'] = oops_id
        message = amqp.Message(dumps(report))
        # We don't want to drop OOPS on the floor if rabbit is restarted.
        message.properties["delivery_mode"] = 2
        channel = self.get_channel()
        if channel is None:
            return []
        try:
            channel.basic_publish(
                message, self.exchange_name, routing_key=self.routing_key)
        except amqplib_error_types, e:
            self.channels.channel = None
            if is_amqplib_connection_error(e):
                # Could not connect / interrupted connection
                return []
            # Unknown error mode : don't hide it.
            raise
        return [report['id']]