integrating inotify into a protocol
Jason Pepas <[email protected]>
| Newsgroups | gmane.comp.python.twisted.web |
|---|---|
| Message-ID | <[email protected]> |
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 _______________________________________________ Twisted-web mailing list [email protected] http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web
echo_inotify.py.txt
(text/plain, 1.6 KB)
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()
echo.py.txt
(text/plain, 851 B)
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()