Make sure to close CVS repository files after parsing them.
[cvs2svn.git] / cvs2svn_lib / log.py
blobea694a63da8ae2892f89a27bba219a5a21d7216c
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 The public methods of this class are thread-safe."""
34 # These constants represent the log levels that this class supports.
35 # The increase_verbosity() and decrease_verbosity() methods rely on
36 # these constants being consecutive integers:
37 ERROR = -2
38 WARN = -1
39 QUIET = 0
40 NORMAL = 1
41 VERBOSE = 2
42 DEBUG = 3
44 start_time = time.time()
46 def __init__(self):
47 self.log_level = _Log.NORMAL
49 # The output file to use for errors:
50 self._err = sys.stderr
52 # The output file to use for lower-priority messages. We also
53 # write these to stderr so that other output (e.g., dumpfiles) can
54 # be written to stdout without being contaminated with progress
55 # messages:
56 self._out = sys.stderr
58 # Lock to serialize writes to the log:
59 self.lock = threading.Lock()
61 def increase_verbosity(self):
62 self.lock.acquire()
63 try:
64 self.log_level = min(self.log_level + 1, _Log.DEBUG)
65 finally:
66 self.lock.release()
68 def decrease_verbosity(self):
69 self.lock.acquire()
70 try:
71 self.log_level = max(self.log_level - 1, _Log.ERROR)
72 finally:
73 self.lock.release()
75 def is_on(self, level):
76 """Return True iff messages at the specified LEVEL are currently on.
78 LEVEL should be one of the constants _Log.WARN, _Log.QUIET, etc."""
80 return self.log_level >= level
82 def _timestamp(self):
83 """Return a timestamp if needed, as a string with a trailing space."""
85 retval = []
87 if self.log_level >= _Log.DEBUG:
88 retval.append('%f: ' % (time.time() - self.start_time,))
90 return ''.join(retval)
92 def _write(self, out, *args):
93 """Write a message to OUT.
95 If there are multiple ARGS, they will be separated by spaces. If
96 there are multiple lines, they will be output one by one with the
97 same timestamp prefix."""
99 timestamp = self._timestamp()
100 s = ' '.join(map(str, args))
101 lines = s.split('\n')
102 if lines and not lines[-1]:
103 del lines[-1]
105 self.lock.acquire()
106 try:
107 for s in lines:
108 out.write('%s%s\n' % (timestamp, s,))
109 # Ensure that log output doesn't get out-of-order with respect to
110 # stderr output.
111 out.flush()
112 finally:
113 self.lock.release()
115 def write(self, *args):
116 """Write a message to SELF._out.
118 This is a public method to use for writing to the output log
119 unconditionally."""
121 self._write(self._out, *args)
123 def error(self, *args):
124 """Log a message at the ERROR level."""
126 if self.is_on(_Log.ERROR):
127 self._write(self._err, *args)
129 def warn(self, *args):
130 """Log a message at the WARN level."""
132 if self.is_on(_Log.WARN):
133 self._write(self._out, *args)
135 def quiet(self, *args):
136 """Log a message at the QUIET level."""
138 if self.is_on(_Log.QUIET):
139 self._write(self._out, *args)
141 def normal(self, *args):
142 """Log a message at the NORMAL level."""
144 if self.is_on(_Log.NORMAL):
145 self._write(self._out, *args)
147 def verbose(self, *args):
148 """Log a message at the VERBOSE level."""
150 if self.is_on(_Log.VERBOSE):
151 self._write(self._out, *args)
153 def debug(self, *args):
154 """Log a message at the DEBUG level."""
156 if self.is_on(_Log.DEBUG):
157 self._write(self._out, *args)
160 # Create an instance that everybody can use:
161 logger = _Log()