summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/util/leap_log_handler.py
blob: 1ab62331a3ffd62c770526bc22e027f9381ed723 (plain)
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
# -*- coding: utf-8 -*-
# leap_log_handler.py
# Copyright (C) 2013 LEAP
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
Custom handler for the logger window.
"""
import logging

from PySide import QtCore


class LogHandler(logging.Handler):
    """
    This is the custom handler that implements our desired formatting
    and also keeps a history of all the logged events.
    """

    MESSAGE_KEY = 'message'
    RECORD_KEY = 'record'

    def __init__(self, qtsignal):
        """
        LogHander initialization.
        Calls parent method and keeps a reference to the qtsignal
        that will be used to fire the gui update.
        """
        # TODO This is going to eat lots of memory after some time.
        # Should be pruned at some moment.
        self._log_history = []

        logging.Handler.__init__(self)
        self._qtsignal = qtsignal

    def _get_format(self, logging_level):
        """
        Sets the log format depending on the parameter.
        It uses html and css to set the colors for the logs.

        :param logging_level: the debug level to define the color.
        :type logging_level: str.
        """
        log_format = ('%(asctime)s - %(name)s:%(funcName)s:L#%(lineno)s '
                      '- %(levelname)s - %(message)s')
        formatter = logging.Formatter(log_format)

        return formatter

    def emit(self, logRecord):
        """
        This method is fired every time that a record is logged by the
        logging module.
        This method reimplements logging.Handler.emit that is fired
        in every logged message.

        :param logRecord: the record emitted by the logging module.
        :type logRecord: logging.LogRecord.
        """
        self.setFormatter(self._get_format(logRecord.levelname))
        log = self.format(logRecord)
        log_item = {self.RECORD_KEY: logRecord, self.MESSAGE_KEY: log}
        self._log_history.append(log_item)
        self._qtsignal(log_item)


class HandlerAdapter(object):
    """
    New style class that accesses all attributes from the LogHandler.

    Used as a workaround for a problem with multiple inheritance with Pyside
    that surfaced under OSX with pyside 1.1.0.
    """
    MESSAGE_KEY = 'message'
    RECORD_KEY = 'record'

    def __init__(self, qtsignal):
        self._handler = LogHandler(qtsignal=qtsignal)

    def setLevel(self, *args, **kwargs):
        return self._handler.setLevel(*args, **kwargs)

    def addFilter(self, *args, **kwargs):
        return self._handler.addFilter(*args, **kwargs)

    def handle(self, *args, **kwargs):
        return self._handler.handle(*args, **kwargs)

    @property
    def level(self):
        return self._handler.level


class LeapLogHandler(QtCore.QObject, HandlerAdapter):
    """
    Custom logging handler. It emits Qt signals so it can be plugged to a gui.

    Its inner handler also stores an history of logs that can be fetched after
    having been connected to a gui.
    """
    # All dicts returned are of the form
    # {'record': LogRecord, 'message': str}
    new_log = QtCore.Signal(dict)

    def __init__(self):
        """
        LeapLogHandler initialization.
        Initializes parent classes.
        """
        QtCore.QObject.__init__(self)
        HandlerAdapter.__init__(self, qtsignal=self.qtsignal)

    def qtsignal(self, log_item):
        # WARNING: the new-style connection does NOT work because PySide
        # translates the emit method to self.emit, and that collides with
        # the emit method for logging.Handler
        # self.new_log.emit(log_item)
        QtCore.QObject.emit(
            self,
            QtCore.SIGNAL('new_log(PyObject)'), log_item)

    @property
    def log_history(self):
        """
        Returns the history of the logged messages.
        """
        return self._handler._log_history