[Twisted-Python] Re: Where is best place to put my custom code?

Andrew Bennetts andrew-twisted at puzzling.org
Thu Jan 1 21:52:08 EST 2004


On Thu, Jan 01, 2004 at 11:25:37AM -0800, JD wrote:
> On Dec 31, 2003, at 7:43 PM, Eric Mangold wrote:
> >
> >Since this is IRC you shouldn't go issuing commands until your signed
> >on, thus the signedOn method of your protocol would be the right place.
> 
> Ok,   good point....   but how do I issue commands?   let's say I have
> a IRCClient class called "testIRC".
> 
> do I use:    testIRC.sendLine('signedOn')  to send the command to the 
> IRC server
> to signon?

No.  IRCClient is a LineReceiver subclass, because that's how the low-level
protocol works.  However, you're not using the low-level protocol, you're
using an abstraction on top of it -- IRCClient.  Don't break the abstraction
(by calling LineReceiver's sendLine method) unless you have a good reason to
and you know the protocol spec well enough to know what you're doing (which
would be RFC 2812 in this case, I think).

As far as I'm aware, sending a line saying 'signedOn' to the server doesn't
make any sense in the IRC protocol, so this definitely wouldn't achieve
anything useful, except causing an error from the server that the IRCClient
instance probably won't expect (because you broke the abstraction and snuck
behind its back to do it).

> or do I:   testIRC.register('mynick', 'myhost', 'irc.debian.com')

That looks much saner.  And noticeably more full of information than
testIRC.sendLine('signedOn')...

> then,   when I want to do the "who" command,  would I do:   
> testIRC.sendLine('who')

Well, I believe the WHO command requires an argument, so it would be more
like testIRC.sendLine('WHO ' + name)... but see my next answer.

> then,   i would expect to call me back,   so I would override the 
> "action" method,
> like so:
> 
> def action(self, user, channel, msg):
> 	< extract the info I want from msg and store it somewhere,  probably 
> in an instance variable in testIRC object >
>          reactor.stop()    ---  to exit the client and disconnect,   or 
> would I have to put the reactor.stop() in the
>          factory's "clientConnectionFailed" method,  which I would 
> override of course.

That's not what the action method is for.  As the docstring for action says:
"Called when I see a user perform an ACTION on a channel."  An ACTION is a
specific thing in IRC, not a catch-all for every type of message from
server to client.  See the RFC if you're not familar with the terms.

The right way to do this is implemented in sandbox/exarkun/irc2.py -- see
the AdvancedClient.who method.  I'd follow JP's earlier suggestion and use
it.

> It's things like this that throw me totally for a loop.   Where to put 
> things....  what gets the call back...

It depends on the protocol implementation.  There's no single generic answer
for the whole of Twisted.

> >No. An ACTION in IRC terms is a user doing an /me.
> 
> Ok,  if "action" isn't the callback which I override to get the output 
> of the who command,
> then what is?
> 
> myInfo?   luserClient?
> 
> luserChannels - Called with the number of channels existant on the 
> server (ALMOST what I want)
> luserOp - Called with the number of ops logged on to the server 
> (GETTING CLOSER - NOT QUITE)
> luserMe - Called with information about the server connected to. 
> (CLOSEST YET - but no IP address info)

The answer is of course none of those.  You should've already noticed that
IRCClient doesn't implement a who() method, so it's hardly surprising it
hasn't implemented a command to deal with its response.  irc2.py does,
though (and uses Deferreds for dealing with the response, which is cleaner
anyway).

> Ok,   so how do these get called?   As far as I can tell,    
> "handleCommand" calls
> 
> method = getattr(self, "irc_%s" % command, None)
> 
> which it then somehow then calls back to:
> 
>     def irc_RPL_LUSERME(self, prefix, params):
>         self.luserMe(params[1])
> 
> I really want:   RPL_WHOISSERVER,  but (sigh) it's not there.   Nobody 
> bothered to finish this
> module.

I thought you wanted to use the WHO command not WHOIS?  Please try to be
precise.

Anyway, irc2.py also implements WHOIS.

> Could I add this to my IRCClient's subclass?
> 
> IE:
> 
>     def irc_RPL_WHOISSERVER(self, prefix, params):
>         self.whois(params[1])

If you look at irc2.py, you'll see it does override this method.  Note that
'whois' is a bad name for the response handler -- the existing convention in
IRCClient is that 'join', 'nick', etc, are the methods that *issue* the
command, not that handle the response.

> Is this all I have to do....   but then would 'getattr' as you see 
> above,   know how to get the method name?
> Or would I have to add this somehow to another dictionary?

Yes, it would.  Please see the docs for getattr in the Python standard
library reference.

> Anyway,   other then being totally confused,   is there any hope?   I 
> think I'm just missing a few
> critical steps.    Or do I have them all?

No idea.  You tell me :)

I think the biggest critical step you're missing is that you're busily
trying to reinvent a wheel that's already been made in
sandbox/exarkun/irc2.py, though.

-Andrew.





More information about the Twisted-Python mailing list