pvl.syslog.fifo: refactor open() and implement close()
authorTero Marttila <terom@paivola.fi>
Sun, 13 Jan 2013 12:59:05 +0200
changeset 138 e10e473902cb
parent 137 e312f27b807d
child 139 515b74c6b456
pvl.syslog.fifo: refactor open() and implement close()
pvl/syslog/fifo.py
--- a/pvl/syslog/fifo.py	Sun Jan 13 12:57:49 2013 +0200
+++ b/pvl/syslog/fifo.py	Sun Jan 13 12:59:05 2013 +0200
@@ -36,14 +36,43 @@
         return cls(fd)
 
     def __init__ (self, fd) :
+        """
+            May pass fd=None to open as closed.
+        """
+
         self._fd = fd
         self._buf = ''
         
         log.debug("pipe: %d", fd)
 
+    def open (self, fd) :
+        """
+            re-open closed pipe to use the given fd.
+
+            Raises ValueError if already open.
+        """
+
+        if self._fd is None :
+            self._fd = fd
+        else :
+            raise ValueError("%s: re-opening already open pipe: %s" % (self, fd))
+    
+    # XXX: good idea?
+    def __nonzero__ (self) :
+        """
+            Test if we are open.
+
+            XXX: signal EOF as well?
+        """
+
+        return self._fd is not None
+
     def fileno (self) :
         """
-            Fetch the internal fd, failing if we are not open..
+            Return the internal fd.
+
+            Raises ValueError if we are closed.
+            XXX: EOFError?
         """
 
         if self._fd is None :
@@ -57,7 +86,7 @@
             Read up to n bytes.
             
             Returns None if we would block.
-            Raises EOFError on EOF.
+            Raises EOFError on EOF, or closed.
         """
 
         try :
@@ -127,8 +156,26 @@
 
     __iter__ = readlines
 
+    def close (self) :
+        """
+            Close our fd, if open.
+
+            May be open()'d again. Meanwhile, all operatations will raise EOFError.
+
+            log.warn's if already closed.
+        """
+        
+        if self._fd is None :
+            log.warn("%s: already closed", self)
+
+        else :
+            log.debug("%s: %s", self, self._fd)
+
+            os.close(self._fd)
+            self._fd = None
+
     def __str__ (self) :
-        return "pipe:{self._fd}".format(self=self)
+        return "pipe({self._fd})".format(self=self)
 
 class Fifo (Pipe) :
     """
@@ -151,22 +198,18 @@
         log.debug("%s: open: %s", self, fd)
 
         return fd
-
-    def _close (self, fd) :
+   
+    def open (self) :
         """
-            Close.
+            Re-open the FIFO.
+            
+            Used when the writing end was closed, and read gave EOF. Opening the fifo again will clear the EOF condition,
+            and resume nonblocking mode.
+            
+            Raises ValueError() if already open. close() first.
         """
 
-        os.close(fd)
-    
-    def _reopen (self) :
-        """
-            Re-open the FIFO in case the writing end was closed, and read gave EOF.
-        """
-
-        self._close(self._fd)
-        self._fd = None
-        self._fd = self._open()
+        self.open(self._open())
 
     def readlines (self) :
         """
@@ -186,7 +229,8 @@
                 log.debug("%s: EOF: reopen", self)
 
                 # reopen and go back to waiting
-                self._reopen()
+                self.close()
+                self.open()
 
                 return
             
@@ -198,20 +242,15 @@
     
     __iter__ = readlines
 
-    def close (self) :
-        """
-            Close the fifo.
-        """
+    def __str__ (self) :
+        return self.path
 
-        self._close(self.fileno())
-        self._fd = None
-
+    # XXX: we need to figure out what references we have lying around, and clean those out!
     def __del__ (self) :
         """
             Cleanup
         """
 
         if self._fd is not None :
-            self._close(self._fd)
-            self._fd = None
-
+            self.close()
+