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()
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.