Merge lp:~mterry/duplicity/levelName into lp:duplicity/0.6

Proposed by Michael Terry
Status: Merged
Approved by: Kenneth Loafman
Approved revision: 725
Merged at revision: 734
Proposed branch: lp:~mterry/duplicity/levelName
Merge into: lp:duplicity/0.6
Diff against target: 82 lines (+17/-20)
1 file modified
duplicity/log.py (+17/-20)
To merge this branch: bzr merge lp:~mterry/duplicity/levelName
Reviewer Review Type Date Requested Status
duplicity-team Pending
Review via email: mp+62226@code.launchpad.net

Description of the change

I found this while messing with the Ubuntu One backend, because apparently one of the ubuntuone modules sets a log level using logging.addLevelName (as duplicity does).

While that's probably not something the ubuntuone module should be doing, reading the documentation for the logging module (http://docs.python.org/library/logging.html), I realized that any old piece of code anywhere could add level names, overriding ours (as ubuntuone did).

That's not wise, so I adjusted the logging code to be more careful of that and use our own mapping always.

To post a comment you must log in.
lp:~mterry/duplicity/levelName updated
725. By Michael Terry

fix MachineFilter logic to match new level name code

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'duplicity/log.py'
--- duplicity/log.py 2011-03-06 15:12:33 +0000
+++ duplicity/log.py 2011-05-31 18:07:33 +0000
@@ -3,6 +3,7 @@
3# Copyright 2002 Ben Escoto <ben@emerose.org>3# Copyright 2002 Ben Escoto <ben@emerose.org>
4# Copyright 2007 Kenneth Loafman <kenneth@loafman.com>4# Copyright 2007 Kenneth Loafman <kenneth@loafman.com>
5# Copyright 2008 Michael Terry <mike@mterry.name>5# Copyright 2008 Michael Terry <mike@mterry.name>
6# Copyright 2011 Canonical Ltd
6#7#
7# This file is part of duplicity.8# This file is part of duplicity.
8#9#
@@ -46,6 +47,14 @@
46 more severe"""47 more severe"""
47 return DupToLoggerLevel(verb)48 return DupToLoggerLevel(verb)
4849
50def LevelName(level):
51 level = LoggerToDupLevel(level)
52 if level >= 9: return "DEBUG"
53 elif level >= 5: return "INFO"
54 elif level >= 3: return "NOTICE"
55 elif level >= 1: return "WARNING"
56 else: return "ERROR"
57
49def Log(s, verb_level, code=1, extra=None, force_print=False):58def Log(s, verb_level, code=1, extra=None, force_print=False):
50 """Write s to stderr if verbosity level low enough"""59 """Write s to stderr if verbosity level low enough"""
51 global _logger60 global _logger
@@ -201,6 +210,7 @@
201 global _logger210 global _logger
202 logging.LogRecord.__init__(self, *args, **kwargs)211 logging.LogRecord.__init__(self, *args, **kwargs)
203 self.controlLine = controlLine212 self.controlLine = controlLine
213 self.levelName = LevelName(self.levelno)
204214
205class DupLogger(logging.Logger):215class DupLogger(logging.Logger):
206 """Custom logger that creates special code-bearing records"""216 """Custom logger that creates special code-bearing records"""
@@ -229,18 +239,6 @@
229 logging.setLoggerClass(DupLogger)239 logging.setLoggerClass(DupLogger)
230 _logger = logging.getLogger("duplicity")240 _logger = logging.getLogger("duplicity")
231241
232 # Set up our special level names
233 logging.addLevelName(DupToLoggerLevel(0), "ERROR")
234 logging.addLevelName(DupToLoggerLevel(1), "WARNING")
235 logging.addLevelName(DupToLoggerLevel(2), "WARNING")
236 logging.addLevelName(DupToLoggerLevel(3), "NOTICE")
237 logging.addLevelName(DupToLoggerLevel(4), "NOTICE")
238 logging.addLevelName(DupToLoggerLevel(5), "INFO")
239 logging.addLevelName(DupToLoggerLevel(6), "INFO")
240 logging.addLevelName(DupToLoggerLevel(7), "INFO")
241 logging.addLevelName(DupToLoggerLevel(8), "INFO")
242 logging.addLevelName(DupToLoggerLevel(9), "DEBUG")
243
244 # Default verbosity allows notices and above242 # Default verbosity allows notices and above
245 setverbosity(NOTICE)243 setverbosity(NOTICE)
246244
@@ -258,7 +256,11 @@
258 processes."""256 processes."""
259 def __init__(self):257 def __init__(self):
260 # 'message' will be appended by format()258 # 'message' will be appended by format()
261 logging.Formatter.__init__(self, "%(levelname)s %(controlLine)s")259 # Note that we use our own, custom-created 'levelName' instead of the
260 # standard 'levelname'. This is because the standard 'levelname' can
261 # be adjusted by any library anywhere in our stack without us knowing.
262 # But we control 'levelName'.
263 logging.Formatter.__init__(self, "%(levelName)s %(controlLine)s")
262264
263 def format(self, record):265 def format(self, record):
264 s = logging.Formatter.format(self, record)266 s = logging.Formatter.format(self, record)
@@ -274,13 +276,8 @@
274class MachineFilter(logging.Filter):276class MachineFilter(logging.Filter):
275 """Filter that only allows levels that are consumable by other processes."""277 """Filter that only allows levels that are consumable by other processes."""
276 def filter(self, record):278 def filter(self, record):
277 # We only want to allow records that have level names. If the level279 # We only want to allow records that have our custom level names
278 # does not have an associated name, there will be a space as the280 return hasattr(record, 'levelName')
279 # logging module expands levelname to "Level %d". This will confuse
280 # consumers. Even if we dropped the space, random levels may not
281 # mean anything to consumers.
282 s = logging.getLevelName(record.levelno)
283 return s.find(' ') == -1
284281
285def add_fd(fd):282def add_fd(fd):
286 """Add stream to which to write machine-readable logging"""283 """Add stream to which to write machine-readable logging"""

Subscribers

People subscribed via source and target branches

to all changes: