Extract functions generate_edits_from_blocks() and write_edits().
[cvs2svn.git] / cvs2svn_lib / log.py
blob798350cb654a0dc44b49e48fe570f0185a5302b2
1 # (Be in -*- python -*- mode.)
3 # ====================================================================
4 # Copyright (c) 2000-2008 CollabNet. All rights reserved.
6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms
8 # are also available at http://subversion.tigris.org/license-1.html.
9 # If newer versions of this license are posted there, you may use a
10 # newer version instead, at your option.
12 # This software consists of voluntary contributions made by many
13 # individuals. For exact contribution history, see the revision
14 # history and logs, available at http://cvs2svn.tigris.org/.
15 # ====================================================================
17 """This module contains a simple logging facility for cvs2svn."""
20 import sys
21 import time
22 import threading
25 class Log:
26 """A Simple logging facility.
28 If self.log_level is DEBUG or higher, each line will be timestamped
29 with the number of wall-clock seconds since the time when this
30 module was first imported.
32 If self.use_timestamps is True, each line will be timestamped with a
33 human-readable clock time.
35 The public methods of this class are thread-safe.
37 This class is a Borg; see
38 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531."""
40 # These constants represent the log levels that this class supports.
41 # The increase_verbosity() and decrease_verbosity() methods rely on
42 # these constants being consecutive integers:
43 ERROR = -2
44 WARN = -1
45 QUIET = 0
46 NORMAL = 1
47 VERBOSE = 2
48 DEBUG = 3
50 start_time = time.time()
52 __shared_state = {}
54 def __init__(self):
55 self.__dict__ = self.__shared_state
56 if self.__dict__:
57 return
59 self.log_level = Log.NORMAL
61 # Set this to True if you want to see timestamps on each line output.
62 self.use_timestamps = False
64 # The output file to use for errors:
65 self._err = sys.stderr
67 # The output file to use for lower-priority messages:
68 self._out = sys.stdout
70 # Lock to serialize writes to the log:
71 self.lock = threading.Lock()
73 def increase_verbosity(self):
74 self.lock.acquire()
75 try:
76 self.log_level = min(self.log_level + 1, Log.DEBUG)
77 finally:
78 self.lock.release()
80 def decrease_verbosity(self):
81 self.lock.acquire()
82 try:
83 self.log_level = max(self.log_level - 1, Log.ERROR)
84 finally:
85 self.lock.release()
87 def is_on(self, level):
88 """Return True iff messages at the specified LEVEL are currently on.
90 LEVEL should be one of the constants Log.WARN, Log.QUIET, etc."""
92 return self.log_level >= level
94 def _timestamp(self):
95 """Return a timestamp if needed, as a string with a trailing space."""
97 retval = []
99 if self.log_level >= Log.DEBUG:
100 retval.append('%f: ' % (time.time() - self.start_time,))
102 if self.use_timestamps:
103 retval.append(time.strftime('[%Y-%m-%d %I:%M:%S %Z] - '))
105 return ''.join(retval)
107 def _write(self, out, *args):
108 """Write a message to OUT.
110 If there are multiple ARGS, they will be separated by spaces. If
111 there are multiple lines, they will be output one by one with the
112 same timestamp prefix."""
114 timestamp = self._timestamp()
115 s = ' '.join(map(str, args))
116 lines = s.split('\n')
117 if lines and not lines[-1]:
118 del lines[-1]
120 self.lock.acquire()
121 try:
122 for s in lines:
123 out.write('%s%s\n' % (timestamp, s,))
124 # Ensure that log output doesn't get out-of-order with respect to
125 # stderr output.
126 out.flush()
127 finally:
128 self.lock.release()
130 def write(self, *args):
131 """Write a message to SELF._out.
133 This is a public method to use for writing to the output log
134 unconditionally."""
136 self._write(self._out, *args)
138 def error(self, *args):
139 """Log a message at the ERROR level."""
141 if self.is_on(Log.ERROR):
142 self._write(self._err, *args)
144 def warn(self, *args):
145 """Log a message at the WARN level."""
147 if self.is_on(Log.WARN):
148 self._write(self._out, *args)
150 def quiet(self, *args):
151 """Log a message at the QUIET level."""
153 if self.is_on(Log.QUIET):
154 self._write(self._out, *args)
156 def normal(self, *args):
157 """Log a message at the NORMAL level."""
159 if self.is_on(Log.NORMAL):
160 self._write(self._out, *args)
162 def verbose(self, *args):
163 """Log a message at the VERBOSE level."""
165 if self.is_on(Log.VERBOSE):
166 self._write(self._out, *args)
168 def debug(self, *args):
169 """Log a message at the DEBUG level."""
171 if self.is_on(Log.DEBUG):
172 self._write(self._out, *args)