1###############################################################################
2# Copyright (c) 2013 INRIA
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License version 2 as
6# published by the Free Software Foundation;
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16#
17# Authors: Daniel Camara  <daniel.camara@inria.fr>
18#          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19###############################################################################
20'''
21 ModuleLogger.py
22
23 This file stores the logger implementation. The logger is responsible for
24 logging the messages and control the level of information showed to the
25 user.
26'''
27
28import sys
29import os
30from bake.Exceptions import NotImplemented
31
32class ModuleLogger:
33    """ The logger class. The logger is responsible for logging the messages
34    and control the level of information showed to the user.
35    """
36    sendToFile=None
37
38    def __init__(self):
39        """ Initializes the used variables."""
40
41        self._verbose = None
42        self._command_file = open(os.devnull, 'w')
43        self._std_file = None
44        self._dump_file = None
45
46    def _update_file(self, f):
47        """ Opens/changes the output devices accordingly to the verbose level."""
48
49        if self._verbose == 0:
50            self._command_file = open(os.devnull, 'w')
51            self._std_file = open(os.devnull, 'w')
52        elif self._verbose == 1:
53            self._command_file = f
54            self._std_file = open(os.devnull, 'w')
55        elif self._verbose == 2:
56            self._command_file = f
57            self._std_file = f
58
59        if self.sendToFile :
60            self._dump_file = open(self.sendToFile, 'w')
61
62    def set_verbose(self, verbose):
63        """ Sets verbosity level."""
64
65        self._verbose = verbose if verbose <= 2 else 2
66
67    # empty implementations, to be re-implemented by the descendants
68    def set_current_module(self, name):
69        raise NotImplemented()
70    def clear_current_module(self):
71        raise NotImplemented()
72
73    @property
74    def stdout(self):
75        """ Returns the in use standard out put."""
76
77        return self._std_file
78    @property
79    def stderr(self):
80        """ Returns the in use  error out put."""
81
82        return self._std_file
83    @property
84    def commands(self):
85        return self._command_file
86
87
88class StdoutModuleLogger(ModuleLogger):
89    """ The Standard output logger, where all the outputs go to the stdout."""
90
91    def __init__(self):
92        """ Initializes the used variables."""
93
94        ModuleLogger.__init__(self)
95        self._file=sys.__stdout__
96        self._update_file(self._file)
97
98    def set_current_module(self, name):
99        """ Sets stdout as the output as the output for the module."""
100
101        self._update_file(sys.__stdout__)
102
103    def clear_current_module(self):
104        """ Not implemented, as the output is always the same, one does
105        not need to reset it.
106        """
107        pass
108
109class LogfileModuleLogger(ModuleLogger):
110    """ The file output logger, all the outputs go to the same log file."""
111
112    def __init__(self, filename):
113        """ Initializes the used variables."""
114
115        ModuleLogger.__init__(self)
116        self._file = open(filename, 'w')
117
118    def set_current_module(self, name):
119        """ Sets the file the output as the output for the module."""
120
121        self._update_file(self._file)
122
123    def clear_current_module(self):
124        """ Not implemented, as the output is always the same, one does
125        not need to reset it.
126        """
127        pass
128
129class LogdirModuleLogger(ModuleLogger):
130    """ Logs the output for a repository,  i.e. one log file per module."""
131
132    def __init__(self, dirname):
133        """ Initializes the used variables."""
134
135        if not os.path.isdir(dirname):
136            os.mkdir(dirname)
137        self._dirname = dirname
138        self._file = None
139
140    def set_current_module(self, name):
141        """ Sets the output file in accordance to the module in use, so that
142        the log outputs will be separated by module.
143        """
144
145        # XXX: we should be checking for other reserved characters
146        import re
147        filename = re.sub('/', '_', name)
148        assert self._file is None
149        self._file = open(os.path.join(self._dirname, filename + '.log'), 'w')
150        self._update_file(self._file)
151
152    def clear_current_module(self):
153        """ Cleans the output for the next module."""
154
155        self._file.close()
156        self._file = None
157
158