--- a/pvl/irk.py Sat Jan 12 23:22:23 2013 +0200
+++ b/pvl/irk.py Sun Jan 13 00:23:34 2013 +0200
@@ -7,7 +7,10 @@
import logging; log = logging.getLogger('pvl.irk')
# proto
-import socket, json
+import json
+
+# XXX: socket
+import socket, select
def parser (parser, connect='tcp://localhost/', target=None) :
"""
@@ -97,7 +100,7 @@
"""
if not url :
- return cls(sys.stdout)
+ return cls(sys.stdout, recv=False)
family, socktype = cls.SCHEME[url.scheme]
@@ -106,18 +109,32 @@
else :
# inet
sock = connect(url.hostname, url.port or cls.PORT, family=family, socktype=socktype)
-
- return cls(sock.makefile('w'))
- def __init__ (self, file) :
+ # XXX: just to make things a bit more exciting... and we really don't want to be blocking on our output..
+ sock.setblocking(False)
+
+ return cls(sock.makefile('w'), recv=sock)
+
+ def __init__ (self, file, recv=None) :
"""
- Use given file-like object for output.
+ Use given file-like object (write, flush, fileno) for output.
"""
self.file = file
+ # XXX
+ self.recv = recv
+ self._buf = ''
+
log.debug("%s", file)
+ def fileno (self) :
+ """
+ Return fd. Useful for detecting error conditions (connection lost).
+ """
+
+ return self.recv.fileno()
+
def send (self, **opts) :
"""
Raises IOError on write errors.
@@ -130,6 +147,62 @@
self.file.write('\n')
self.file.flush()
+ def read (self, size=512) :
+ """
+ Recieve data back from irkerd.
+
+ Raise EOFError.
+
+ XXX: this is seriously crazy on a buffered file-like object..?
+ """
+
+ # poll
+ read, _, _ = select.select((self.recv, ), (), (), 0.0)
+
+ if read :
+ read = self.recv.recv(size)
+
+ if read :
+ return read
+ else :
+ raise EOFError()
+ else :
+ return None # block
+
+ def readline (self) :
+ """
+ Yield line of input, or None.
+
+ Raise EOFError.
+ """
+
+ while '\n' not in self._buf :
+ read = self.read()
+
+ if not read :
+ return None # block
+
+ self._buf += read
+
+ line, self._buf = self._buf.split('\n')
+
+ return line
+
+ def readlines (self) :
+ """
+ Yield lines of input, until blocking.
+ """
+
+ while True :
+ line = self.readline()
+
+ if line :
+ yield line
+ else :
+ return
+
+ __iter__ = readlines
+
class IrkerTarget (object) :
"""
A channel on an Irk connection.