diff options
Diffstat (limited to 'Lib/logging')
-rw-r--r-- | Lib/logging/__init__.py | 35 | ||||
-rw-r--r-- | Lib/logging/handlers.py | 34 |
2 files changed, 61 insertions, 8 deletions
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 6455f39..b44a3b2 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -33,8 +33,9 @@ __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR', 'StreamHandler', 'WARN', 'WARNING', 'addLevelName', 'basicConfig', 'captureWarnings', 'critical', 'debug', 'disable', 'error', 'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass', - 'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning', - 'getLogRecordFactory', 'setLogRecordFactory', 'lastResort'] + 'info', 'log', 'makeLogRecord', 'setLoggerClass', 'shutdown', + 'warn', 'warning', 'getLogRecordFactory', 'setLogRecordFactory', + 'lastResort', 'raiseExceptions'] try: import threading @@ -107,6 +108,7 @@ _levelToName = { } _nameToLevel = { 'CRITICAL': CRITICAL, + 'FATAL': FATAL, 'ERROR': ERROR, 'WARN': WARNING, 'WARNING': WARNING, @@ -940,6 +942,10 @@ class Handler(Filterer): finally: del t, v, tb + def __repr__(self): + level = getLevelName(self.level) + return '<%s (%s)>' % (self.__class__.__name__, level) + class StreamHandler(Handler): """ A handler class which writes logging records, appropriately formatted, @@ -991,6 +997,14 @@ class StreamHandler(Handler): except Exception: self.handleError(record) + def __repr__(self): + level = getLevelName(self.level) + name = getattr(self.stream, 'name', '') + if name: + name += ' ' + return '<%s %s(%s)>' % (self.__class__.__name__, name, level) + + class FileHandler(StreamHandler): """ A handler class which writes formatted logging records to disk files. @@ -999,6 +1013,8 @@ class FileHandler(StreamHandler): """ Open the specified file and use it as the stream for logging. """ + # Issue #27493: add support for Path objects to be passed in + filename = os.fspath(filename) #keep the absolute path, otherwise derived classes which use this #may come a cropper when the current directory changes self.baseFilename = os.path.abspath(filename) @@ -1053,6 +1069,11 @@ class FileHandler(StreamHandler): self.stream = self._open() StreamHandler.emit(self, record) + def __repr__(self): + level = getLevelName(self.level) + return '<%s %s (%s)>' % (self.__class__.__name__, self.baseFilename, level) + + class _StderrHandler(StreamHandler): """ This class is like a StreamHandler using sys.stderr, but always uses @@ -1545,6 +1566,11 @@ class Logger(Filterer): suffix = '.'.join((self.name, suffix)) return self.manager.getLogger(suffix) + def __repr__(self): + level = getLevelName(self.getEffectiveLevel()) + return '<%s %s (%s)>' % (self.__class__.__name__, self.name, level) + + class RootLogger(Logger): """ A root logger is not that different to any other logger, except that @@ -1671,6 +1697,11 @@ class LoggerAdapter(object): """ return self.logger.hasHandlers() + def __repr__(self): + logger = self.logger + level = getLevelName(logger.getEffectiveLevel()) + return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level) + root = RootLogger(WARNING) Logger.root = root Logger.manager = Manager(Logger.root) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index c39a56f..7d77973 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -246,6 +246,9 @@ class TimedRotatingFileHandler(BaseRotatingHandler): self.extMatch = re.compile(self.extMatch, re.ASCII) self.interval = self.interval * interval # multiply by units requested + # The following line added because the filename passed in could be a + # path object (see Issue #27493), but self.baseFilename will be a string + filename = self.baseFilename if os.path.exists(filename): t = os.stat(filename)[ST_MTIME] else: @@ -440,11 +443,11 @@ class WatchedFileHandler(logging.FileHandler): sres = os.fstat(self.stream.fileno()) self.dev, self.ino = sres[ST_DEV], sres[ST_INO] - def emit(self, record): + def reopenIfNeeded(self): """ - Emit a record. + Reopen log file if needed. - First check if the underlying file has changed, and if it + Checks if the underlying file has changed, and if it has, close the old stream and reopen the file to get the current stream. """ @@ -467,6 +470,15 @@ class WatchedFileHandler(logging.FileHandler): # open a new file handle and get new stat info from that fd self.stream = self._open() self._statstream() + + def emit(self, record): + """ + Emit a record. + + If underlying file has changed, reopen the file before emitting the + record to it. + """ + self.reopenIfNeeded() logging.FileHandler.emit(self, record) @@ -1229,17 +1241,25 @@ class MemoryHandler(BufferingHandler): flushing them to a target handler. Flushing occurs whenever the buffer is full, or when an event of a certain severity or greater is seen. """ - def __init__(self, capacity, flushLevel=logging.ERROR, target=None): + def __init__(self, capacity, flushLevel=logging.ERROR, target=None, + flushOnClose=True): """ Initialize the handler with the buffer size, the level at which flushing should occur and an optional target. Note that without a target being set either here or via setTarget(), a MemoryHandler is no use to anyone! + + The ``flushOnClose`` argument is ``True`` for backward compatibility + reasons - the old behaviour is that when the handler is closed, the + buffer is flushed, even if the flush level hasn't been exceeded nor the + capacity exceeded. To prevent this, set ``flushOnClose`` to ``False``. """ BufferingHandler.__init__(self, capacity) self.flushLevel = flushLevel self.target = target + # See Issue #26559 for why this has been added + self.flushOnClose = flushOnClose def shouldFlush(self, record): """ @@ -1273,10 +1293,12 @@ class MemoryHandler(BufferingHandler): def close(self): """ - Flush, set the target to None and lose the buffer. + Flush, if appropriately configured, set the target to None and lose the + buffer. """ try: - self.flush() + if self.flushOnClose: + self.flush() finally: self.acquire() try: |