This file is indexed.

/usr/lib/python2.7/dist-packages/logbook/compat.py is in python-logbook 0.12.3-1.

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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# -*- coding: utf-8 -*-
"""
    logbook.compat
    ~~~~~~~~~~~~~~

    Backwards compatibility with stdlib's logging package and the
    warnings module.

    :copyright: (c) 2010 by Armin Ronacher, Georg Brandl.
    :license: BSD, see LICENSE for more details.
"""
import sys
import logging
import warnings
import logbook
from datetime import date, datetime

from logbook.helpers import u, string_types, iteritems

_epoch_ord = date(1970, 1, 1).toordinal()


def redirect_logging(set_root_logger_level=True):
    """Permanently redirects logging to the stdlib.  This also
    removes all otherwise registered handlers on root logger of
    the logging system but leaves the other loggers untouched.

    :param set_root_logger_level: controls of the default level of the legacy
       root logger is changed so that all legacy log messages get redirected
       to Logbook
    """
    del logging.root.handlers[:]
    logging.root.addHandler(RedirectLoggingHandler())
    if set_root_logger_level:
        logging.root.setLevel(logging.DEBUG)


class redirected_logging(object):
    """Temporarily redirects logging for all threads and reverts
    it later to the old handlers.  Mainly used by the internal
    unittests::

        from logbook.compat import redirected_logging
        with redirected_logging():
            ...
    """
    def __init__(self, set_root_logger_level=True):
        self.old_handlers = logging.root.handlers[:]
        self.old_level = logging.root.level
        self.set_root_logger_level = set_root_logger_level

    def start(self):
        redirect_logging(self.set_root_logger_level)

    def end(self, etype=None, evalue=None, tb=None):
        logging.root.handlers[:] = self.old_handlers
        logging.root.setLevel(self.old_level)

    __enter__ = start
    __exit__ = end


class LoggingCompatRecord(logbook.LogRecord):

    def _format_message(self, msg, *args, **kwargs):
        assert not kwargs
        return msg % tuple(args)


class RedirectLoggingHandler(logging.Handler):
    """A handler for the stdlib's logging system that redirects
    transparently to logbook.  This is used by the
    :func:`redirect_logging` and :func:`redirected_logging`
    functions.

    If you want to customize the redirecting you can subclass it.
    """

    def __init__(self):
        logging.Handler.__init__(self)

    def convert_level(self, level):
        """Converts a logging level into a logbook level."""
        if level >= logging.CRITICAL:
            return logbook.CRITICAL
        if level >= logging.ERROR:
            return logbook.ERROR
        if level >= logging.WARNING:
            return logbook.WARNING
        if level >= logging.INFO:
            return logbook.INFO
        return logbook.DEBUG

    def find_extra(self, old_record):
        """Tries to find custom data from the old logging record.  The
        return value is a dictionary that is merged with the log record
        extra dictionaries.
        """
        rv = vars(old_record).copy()
        for key in ('name', 'msg', 'args', 'levelname', 'levelno',
                    'pathname', 'filename', 'module', 'exc_info',
                    'exc_text', 'lineno', 'funcName', 'created',
                    'msecs', 'relativeCreated', 'thread', 'threadName',
                    'greenlet', 'processName', 'process'):
            rv.pop(key, None)
        return rv

    def find_caller(self, old_record):
        """Tries to find the caller that issued the call."""
        frm = sys._getframe(2)
        while frm is not None:
            if (frm.f_globals is globals() or
                    frm.f_globals is logbook.base.__dict__ or
                    frm.f_globals is logging.__dict__):
                frm = frm.f_back
            else:
                return frm

    def convert_time(self, timestamp):
        """Converts the UNIX timestamp of the old record into a
        datetime object as used by logbook.
        """
        return datetime.utcfromtimestamp(timestamp)

    def convert_record(self, old_record):
        """Converts an old logging record into a logbook log record."""
        record = LoggingCompatRecord(old_record.name,
                                     self.convert_level(old_record.levelno),
                                     old_record.msg, old_record.args,
                                     None, old_record.exc_info,
                                     self.find_extra(old_record),
                                     self.find_caller(old_record))
        record.time = self.convert_time(old_record.created)
        return record

    def emit(self, record):
        logbook.dispatch_record(self.convert_record(record))


class LoggingHandler(logbook.Handler):
    """Does the opposite of the :class:`RedirectLoggingHandler`, it sends
    messages from logbook to logging.  Because of that, it's a very bad
    idea to configure both.

    This handler is for logbook and will pass stuff over to a logger
    from the standard library.

    Example usage::

        from logbook.compat import LoggingHandler, warn
        with LoggingHandler():
            warn('This goes to logging')
    """

    def __init__(self, logger=None, level=logbook.NOTSET, filter=None,
                 bubble=False):
        logbook.Handler.__init__(self, level, filter, bubble)
        if logger is None:
            logger = logging.getLogger()
        elif isinstance(logger, string_types):
            logger = logging.getLogger(logger)
        self.logger = logger

    def get_logger(self, record):
        """Returns the logger to use for this record.  This implementation
        always return :attr:`logger`.
        """
        return self.logger

    def convert_level(self, level):
        """Converts a logbook level into a logging level."""
        if level >= logbook.CRITICAL:
            return logging.CRITICAL
        if level >= logbook.ERROR:
            return logging.ERROR
        if level >= logbook.WARNING:
            return logging.WARNING
        if level >= logbook.INFO:
            return logging.INFO
        return logging.DEBUG

    def convert_time(self, dt):
        """Converts a datetime object into a timestamp."""
        year, month, day, hour, minute, second = dt.utctimetuple()[:6]
        days = date(year, month, 1).toordinal() - _epoch_ord + day - 1
        hours = days * 24 + hour
        minutes = hours * 60 + minute
        seconds = minutes * 60 + second
        return seconds

    def convert_record(self, old_record):
        """Converts a record from logbook to logging."""
        if sys.version_info >= (2, 5):
            # make sure 2to3 does not screw this up
            optional_kwargs = {'func': getattr(old_record, 'func_name')}
        else:
            optional_kwargs = {}
        record = logging.LogRecord(old_record.channel,
                                   self.convert_level(old_record.level),
                                   old_record.filename,
                                   old_record.lineno,
                                   old_record.message,
                                   (), old_record.exc_info,
                                   **optional_kwargs)
        for key, value in iteritems(old_record.extra):
            record.__dict__.setdefault(key, value)
        record.created = self.convert_time(old_record.time)
        return record

    def emit(self, record):
        self.get_logger(record).handle(self.convert_record(record))


def redirect_warnings():
    """Like :func:`redirected_warnings` but will redirect all warnings
    to the shutdown of the interpreter:

    .. code-block:: python

        from logbook.compat import redirect_warnings
        redirect_warnings()
    """
    redirected_warnings().__enter__()


class redirected_warnings(object):
    """A context manager that copies and restores the warnings filter upon
    exiting the context, and logs warnings using the logbook system.

    The :attr:`~logbook.LogRecord.channel` attribute of the log record will be
    the import name of the warning.

    Example usage:

    .. code-block:: python

        from logbook.compat import redirected_warnings
        from warnings import warn

        with redirected_warnings():
            warn(DeprecationWarning('logging should be deprecated'))
    """

    def __init__(self):
        self._entered = False

    def message_to_unicode(self, message):
        try:
            return u(str(message))
        except UnicodeError:
            return str(message).decode('utf-8', 'replace')

    def make_record(self, message, exception, filename, lineno):
        category = exception.__name__
        if exception.__module__ not in ('exceptions', 'builtins'):
            category = exception.__module__ + '.' + category
        rv = logbook.LogRecord(category, logbook.WARNING, message)
        # we don't know the caller, but we get that information from the
        # warning system.  Just attach them.
        rv.filename = filename
        rv.lineno = lineno
        return rv

    def start(self):
        if self._entered:  # pragma: no cover
            raise RuntimeError("Cannot enter %r twice" % self)
        self._entered = True
        self._filters = warnings.filters
        warnings.filters = self._filters[:]
        self._showwarning = warnings.showwarning

        def showwarning(message, category, filename, lineno,
                        file=None, line=None):
            message = self.message_to_unicode(message)
            record = self.make_record(message, category, filename, lineno)
            logbook.dispatch_record(record)
        warnings.showwarning = showwarning

    def end(self, etype=None, evalue=None, tb=None):
        if not self._entered:  # pragma: no cover
            raise RuntimeError("Cannot exit %r without entering first" % self)
        warnings.filters = self._filters
        warnings.showwarning = self._showwarning

    __enter__ = start
    __exit__ = end