[Twisted-web] integrating inotify into a protocol
Jason Pepas
cell at phunware.com
Tue Mar 29 21:21:03 EDT 2011
hey guys,
I'm new to twisted, and I'm trying to figure out how to integrate the
inotify support into a client protocol.
let's say I have a client protocol which connects to a server and
stays connected, like the "Echo" example here:
http://twistedmatrix.com/documents/10.2.0/core/howto/clients.html#auto3
I've taken that example a tweaked it so that it echos back to the
server, rather than to stdout (see echo.py, attached), and takes its
port number as sys.argv[1].
now, I can start the "server":
$ cat | socat - tcp4-listen:1234
and start the client:
$ python echo.py 1234
Started to connect.
Connected.
and if I type something into the server, it gets printed on client's
stdout, and then echoed back to the server:
$ cat | socat - tcp4-listen:1234
blah
blah
$ python foo.py 1234
Started to connect.
Connected.
blah
life is good.
now, let's say I want to integrate inotify support into my persistent
client. let's say that whenever a new file appears in /tmp, I want to
client to announce this file to the server, over its persistent
connection. accordingly, I've added 'def announceNewFile()' to the
Echo() protocol class (see echo_inotify, attached).
but herein lies the rub: the inotify notifier just takes a list of
callback functions, not a list of objects. so how can I get the
notifier to call a method on my Echo protocol object?
another way to say this is that the protocol/client/factory side of
things is all object-oriented, but the inotify side of things is just
procedural. n'ere the twain shall meet?
specifically, the notifier expects the callback to accept 3 args:
_Watch object, path, and mask. so, when you try to pass in a class
method as one of its callbacks, you get something like this:
exceptions.TypeError: unbound method announceNewFile() must be
called with Echo instance as first argument (got _Watch instance
instead)
halp?
-jason
-------------- next part --------------
from twisted.internet.protocol import Protocol, ClientFactory
from sys import stdout
class Echo(Protocol):
def dataReceived(self, data):
stdout.write(data)
self.transport.write(data)
def announceNewFile(self, watch_obj, path, mask):
# problem!!! the inotify callback sends three args (watch_obj, path, mask)
# but we require a reference to self. halp?
self.transport.write(msg)
class EchoClientFactory(ClientFactory):
def startedConnecting(self, connector):
print 'Started to connect.'
def buildProtocol(self, addr):
print 'Connected.'
return Echo()
def clientConnectionLost(self, connector, reason):
print 'Lost connection. Reason:', reason
def clientConnectionFailed(self, connector, reason):
print 'Connection failed. Reason:', reason
if __name__ == "__main__":
from twisted.internet import reactor, inotify
from twisted.python import filepath
import sys
reactor.connectTCP("localhost", int(sys.argv[1]), EchoClientFactory())
notifier = inotify.INotify()
notifier.startReading()
watch_mask = inotify.IN_CREATE
notifier.watch(filepath.FilePath("/tmp"), mask=watch_mask, callbacks=[Echo.announceNewFile])
# again, there is no way for notifier to actually call the announceNewFile
# method on an Echo() object, because it doesn't have an Echo() object. lolwut?
# speaking generally, the protocol/client/factory situation is all object-oriented,
# but the inotify stuff if procedure (ie, just a callback function). how does one
# reconcile these two realms?
reactor.run()
-------------- next part --------------
from twisted.internet.protocol import Protocol, ClientFactory
from sys import stdout
class Echo(Protocol):
def dataReceived(self, data):
stdout.write(data)
self.transport.write(data)
class EchoClientFactory(ClientFactory):
def startedConnecting(self, connector):
print 'Started to connect.'
def buildProtocol(self, addr):
print 'Connected.'
return Echo()
def clientConnectionLost(self, connector, reason):
print 'Lost connection. Reason:', reason
def clientConnectionFailed(self, connector, reason):
print 'Connection failed. Reason:', reason
if __name__ == "__main__":
from twisted.internet import reactor, inotify
from twisted.python import filepath
import sys
reactor.connectTCP("localhost", int(sys.argv[1]), EchoClientFactory())
reactor.run()
More information about the Twisted-web
mailing list