Forráskód Böngészése

Implementation + additional test

 * descriptor to for management of class variable

 * additional test to confirm proper behavior on reopen
Whit Morriss 13 éve
szülő
commit
d2bc68561f
2 módosított fájl, 38 hozzáadás és 10 törlés
  1. 31 3
      supervisor/loggers.py
  2. 7 7
      supervisor/tests/test_loggers.py

+ 31 - 3
supervisor/loggers.py

@@ -44,7 +44,7 @@ def getLevelNumByDescription(description):
     num = getattr(LevelsByDescription, description, None)
     return num
 
-class Handler:
+class Handler(object):
     fmt = '%(message)s'
     level = LevelsByName.INFO
     def setFormat(self, fmt):
@@ -87,7 +87,6 @@ class Handler:
 class FileHandler(Handler):
     """File handler which supports reopening of logs.
     """
-
     def __init__(self, filename, mode="a"):
         self.stream = open(filename, mode)
         self.baseFilename = filename
@@ -139,6 +138,9 @@ class BoundIO:
         self.buf = ''
             
 class RotatingFileHandler(FileHandler):
+
+    open_streams = {}
+
     def __init__(self, filename, mode='a', maxBytes=512*1024*1024,
                  backupCount=10):
         """
@@ -163,12 +165,38 @@ class RotatingFileHandler(FileHandler):
         """
         if maxBytes > 0:
             mode = 'a' # doesn't make sense otherwise!
-        FileHandler.__init__(self, filename, mode)
+        self.mode = mode
+        self.baseFilename = filename
+        self.stream = self.stream or open(filename, mode)
+
         self.maxBytes = maxBytes
         self.backupCount = backupCount
         self.counter = 0
         self.every = 10
 
+    class _stream(object):
+        """
+        Descriptor for managing open filehandles so that only one
+        filehandle per file path ever receives logging.
+        """
+        def __get__(self, obj, objtype):
+            """
+            Return open filehandle or None
+            """
+            return objtype.open_streams.get(obj.baseFilename)
+
+        def __set__(self, obj, stream):
+            """
+            Set open filehandle for filename defined on the
+            RotatingFileHandler
+            """
+            obj.open_streams[obj.baseFilename] = stream        
+
+    stream = _stream()
+
+    def close(self):
+        if self.stream: self.stream.close()
+
     def emit(self, record):
         """
         Emit a record.

+ 7 - 7
supervisor/tests/test_loggers.py

@@ -162,13 +162,13 @@ class RotatingFileHandlerTests(FileHandlerTests):
         handler2.emit(new_record)
         self.assertTrue(open(self.filename).read().endswith(""))
 
-##     def test_reopen_raises(self):
-##         handler = self._makeOne(self.filename)
-##         stream = DummyStream()
-##         handler.baseFilename = os.path.join(self.basedir, 'notthere', 'a.log')
-##         handler.open_streams[handler.baseFilename] = stream
-##         self.assertRaises(IOError, handler.reopen)
-##         self.assertEqual(stream.closed, True)
+    def test_reopen_raises(self):
+        handler = self._makeOne(self.filename)
+        stream = DummyStream()
+        handler.baseFilename = os.path.join(self.basedir, 'notthere', 'a.log')
+        handler.open_streams[handler.baseFilename] = stream
+        self.assertRaises(IOError, handler.reopen)
+        self.assertEqual(stream.closed, True)
 
     def test_emit_does_rollover(self):
         handler = self._makeOne(self.filename, maxBytes=10, backupCount=2)