[02:20] *** eikenberry has joined #kamaelia
[04:01] *** wyleu has joined #kamaelia
[04:46] *** wyleu has joined #kamaelia
[07:21] *** tdobson has joined #kamaelia
[07:59] *** Uraeus has joined #kamaelia
[10:55] *** Uraeus has joined #kamaelia
[12:08] *** mhrd has joined #kamaelia
[12:29] *** VanL has joined #kamaelia
[12:44] *** VanL has parted #kamaelia
[17:52] *** vmlemon_ has joined #kamaelia
[17:52] < vmlemon_> Hi
[17:53] < Lawouach> hi
[18:04] *** VanL has joined #kamaelia
[18:06] < vmlemon_> Hi VanL
[18:06] < VanL> Hi
[18:06] < VanL> I am working on an IMAP server. Most times I need to buffer my input until I receive an entire line, but occasionally I need to buffer (size) bytes.
[18:06] < VanL> I wrote a BufferedReceiver (http://pastebin.com/m41eaf698) that changes its mode based on control messages
[18:07] < VanL> Any comments as to style? Is this the best way to do it? How would this be best wired up - just in a pipeline, and I can send signals to it from further down?
[18:12] *** MS- has joined #kamaelia
[18:12] < MS-> evening
[18:12] < vmlemon_> Hi MS-
[18:13] < VanL> Hi MS-
[18:13] < MS-> Hiya
[18:14] < VanL> MS-: I think I chatted with you a day or two ago about building an IMAP server in the style of the greylisting server. Is that right?
[18:14] *** MS- reading logs (& cleared pending messages on mailing list :) )
[18:14] *** MS- nods
[18:15] < VanL> oh, can you see the pastebin post above? (http://pastebin.com/m41eaf698). Either way, any comment?
[18:16] *** MS- taking a look :)
[18:16] < MS-> logs btw are here: http://www.kamaelia.org/logs/
[18:18] < MS-> Looking at it, there's somethings that I wouldn't do
[18:19] < MS-> this:
[18:19] < MS-> while self.dataReady('control'):
[18:19] < MS-> self.controlbuffer.append(self.recv('control'))
[18:19] < MS->
[18:19] < MS-> self.handle_control()
[18:19] < MS-> along with the code in handle_control()
[18:19] < MS-> is a little redundant
[18:19] < MS-> if you change:
[18:19] < MS-> for msg in self.controlbuffer:
[18:19] < MS-> to
[18:19] < MS-> for msg in self.Inbox("control"):
[18:20] < MS-> and get rid of:
[18:20] < MS-> while self.dataReady('control'):
[18:20] < MS-> self.controlbuffer.append(self.recv('control'))
[18:20] < MS->
[18:20] < MS-> Then that will perform the same way
[18:21] < MS-> Also, I'd probably write handle_data non recursively.
[18:21] < MS-> These are largely stylistic things I must admit :)
[18:22] < VanL> Thats fine, I think idiomatic code is important
[18:23] < VanL> would you keep the separate handle_control/handle_data/handle_shutdown? Or put in in main?
[18:24] < MS-> SInce you're using custom control messages (eg BufferUntil) I would keep handle_control
[18:25] < MS-> I'd do the handle_shutdown() outside the loop as well
[18:26] < MS-> Ah, it has two modes of operation as well
[18:27] < MS-> I think these days, I'd actually write that as two different components
[18:27] < MS-> one for size delimiting and one for line delimiting
[18:27] < MS-> and then have it work slightly differently, but that's something which isn't idiomatic at present
[18:28] < VanL> I have that. My concern was with extra data
[18:28] < MS-> (just something I'd do, to see if it looked better)
[18:28] < VanL> This was my second try.
[18:28] *** MS- nods
[18:29] < VanL> if we had data pending in the buffer but then needed to switch modes, I would have to send the extra data over as initial_data to the new component
[18:29] < VanL> possible, but seemed... less ideal.
[18:29] < MS-> I see
[18:31] < MS-> My personal approach was to create a "getline" generator instead here:
[18:31] < MS-> http://code.google.com/p/kamaelia/source/browse/trunk/Code/Python/Kamaelia/Kamaelia/Apps/Grey/MailHandler.py
[18:32] < MS-> The way that works is to use WaitComplete - which effectively tells the system "run this other function instead of main, and when it finishes come back here"
[18:33] < MS-> It's not as nice/composable as your component, but it can simplify code sometimes
[18:33] < VanL> My plan was actually to use it with WaitComplete
[18:33] < VanL> similarly to your code
[18:33] < MS-> That would be interesting to see
[18:34] < VanL> Updated here: http://pastebin.com/m7ff0223f
[18:36] < VanL> oops, actually http://pastebin.com/m421623f (moved handle_shutdown out of loop)
[18:38] < MS-> Ah the shutdown needs a little more as well
[18:39] < MS-> your component can shutdown and send "false" to the next component
[18:39] < VanL> I don't understand
[18:39] < MS-> Oh scratch that
[18:39] < MS-> sorry
[18:40] < MS-> missed the conditions for self.shutdown
[18:40] < MS-> if it's not set to an instance of either producerFinished, shutdownMicroprocess it doesn't get shutdown
[18:40] < MS-> which is fine
[18:41] < VanL> Are there any other shutdown conditions? Those were the only ones I saw when poking around various codebases
[18:41] < VanL> (any other standard shutdown conditions)
[18:41] < MS-> Those are the two most common
[18:41] < MS-> Over time it's become idiomatic for producerFInished() to mean
[18:42] < MS-> "I'm done, and I'm not going to send you any more data"
[18:42] < MS-> Which for many components means it's time for them to stop as well
[18:42] < VanL> That would make sense here
[18:42] < MS-> Whereas shutdownMicroprocess means "Shutdown ASAP"
[18:43] < VanL> Regarding WaitComplete - isn't an Axon component also a generator? The way IMAP works is that I receive a message crom the client saying "Expect X number of octets"; the server says, "ok to send X number of octets"; and then wait until I have received that many bytes.
[18:44] < VanL> My thought was that if I needed to do that, I could send the control message (BufferUntil(size)); and then WaitComplete on self.Inbox('inbox')
[18:46] < MS-> You could do that - I can see why you'd want to as well
[18:47] < MS-> An Axon component isn't just a generator really. The vast majority are implemented using generators, but I wouldn't say that an Axon component is also a generator
[18:50] < MS-> fwiw, it looks like the right sort of approach overall - especially given the fact you have to mode switch
[18:50] < MS-> The proof of the pudding is in the doing of course :)
[18:51] < VanL> Well, thats true. I appreciate your input and time.
[18:51] < VanL> Hmm, while I am at it, is there a good way to test these at the prompt?
[18:52] < VanL> I have been wiring up little echo servers
[18:53] < MS-> I tend to use a small pipeline or graphline and then either connect a file reader or a another component as a source (ala "cat" on unix)
[18:53] < MS-> and then dump the output through a ConsoleEchoer
[18:54] < MS-> eg http://www.kamaelia.org/Components/pydoc/Kamaelia.Util.DataSource.html
[18:54] < MS-> You can also use "Handle" from a python prompt, thinking about it
[18:55] < MS-> http://www.kamaelia.org/AxonHandle
[18:55] < MS-> doing:
[18:55] < MS-> from Axon.background import background
[18:55] < MS-> background().start()
[18:55] < MS-> starts a scheduler in the background
[18:56] < MS-> which means that works happily inside a python console
[20:14] *** mhrd-home has joined #kamaelia
[20:24] < VanL> MS-: FWIW, here is the little interact() snippet that I worked up based on Handle: http://pastebin.com/f1ecb5052
[20:25] < VanL> Thanks for the tip
[20:26] < mhrd-home> VanL: hi, reading scrollback :-)
[20:26] < mhrd-home> MS-: hi :-)
[20:28] < VanL> mhrd-home: Thanks for the help yesterday. Here is my final BufferedReceiver: http://pastebin.com/f16cb0117. Inspired by yours, but with the changes I needed for IMAP.
[20:29] < mhrd-home> hi VanL: it was a pleasure
[20:29] < mhrd-home> Stylistically, looks pretty good for a 1st/2nd attempt - has shutdown handling in it which always makes me happy :-)
[20:32] < mhrd-home> looking at what you're trying to do (switch chunking/splitting mode dynamically), and assuming I understand correctly ...
[20:33] < mhrd-home> the current design might suffer from a problem where you can't control the precise point at which it switches mode ...
[20:33] < mhrd-home> because the BufferedReceiver component could well be several lines/n-byte-chunks ahead of the next component in the pipeline which is parsing the messages and making the mode switching decisions?
[20:34] < VanL> I thought about that, but I wasn't sure I could fix it. I can receive stuff at any time.
[20:35] < VanL> Thats part of why I have the mode as a list
[20:35] < mhrd-home> aah, didn't spot that
[20:35] *** mhrd-home looks
[20:35] < VanL> so if I only want one message received the different way, I can send two successive BufferUntil messages
[20:35] *** vmlemon_ is really hating C++ right now
[20:36] < mhrd-home> the BufferUntil message gets sent to the "inbox" inbox?
[20:36] *** mhrd-home sympathises with vmlemon_
[20:36] < VanL> no, it gets sent to 'control'
[20:37] < vmlemon_> I've been trying to compile a stupid header file based on some code that I found, and there's a load of types that are used, but are undefined, and I have no idea what they're supposed to be
[20:37] *** VanL feels vmlemon_'s pain
[20:38] < mhrd-home> VanL: ah, ok, I see
[20:39] < VanL> see update_mode
[20:39] < mhrd-home> MS 's "getline generator" approach avoids the issue
[20:39] < mhrd-home> another option you can take is a similar kind of approach (albeit a bit less concise) whilst keeping it as a separate component ...
[20:41] < mhrd-home> eg. you can build a component with an additional inbox. whenever you want another chunk of data, you send a kind of "next-please" message to that additional inbox
[20:41] < mhrd-home> this component is a little like that: http://code.google.com/p/kamaelia/source/browse/trunk/Code/Python/Kamaelia/Kamaelia/Util/PromptedTurnstile.py
[20:42] < mhrd-home> so for your case you could have two kinds of "next-please" message - one is a number of bytes, the other is a delimiter
[20:43] < VanL> I see
[20:44] < VanL> I considered this sort of design as well - although this is better than what I was thinking. My concern was that normally, we didn't want to have to say "Next!" for every single command
[20:44] < mhrd-home> it is alot more verbose
[20:44] < VanL> Although in practice, it probably wouldn't be a big deal, just hidden in a function I guess
[20:45] < mhrd-home> you can use the WaitComplete approach to hide that "next-please, then wait for response" process
[20:46] < mhrd-home> I reckon the thing is to try it and see if your component does the job. if it does then there's no need to change anything
[20:49] < VanL> Yes, true.
[20:49] < VanL> Now, however, unfortunately back to less interesting billable work :(
[20:50] < VanL> bye everyone
[20:51] < mhrd-home> another component, I've just remembered, that contains something close to what you need is the WAV codec implementation I did a while ago ...
[20:51] < mhrd-home> http://code.google.com/p/kamaelia/source/browse/trunk/Code/Python/Kamaelia/Kamaelia/Codec/WAV.py
[20:52] < mhrd-home> it is done in a style similar to MS- 's getline() approach - with generators called readBytes() and readLine()
[20:52] < mhrd-home> however 1) it is more complicated that you need it to be, since I was experimenting with making it intelligently cope with outboxes which could overflow (due to a finite size limit being imposed onthem)
[20:53] < VanL> ooh, very nice
[20:53] < mhrd-home> 2) iirc WaitComplete() was broken at that time (at least that is my excuse!) so I used "for _ in self.readBytes(n): yield _"
[20:53] < mhrd-home> which kinda achieves the same effect
[20:54] < mhrd-home> hmm, I can't see why I left the readLine() generator in there - it doesn't appear to be used(!)
[20:54] < mhrd-home> ah well
[20:55] < VanL> still, this is worth knowing about, especially if my component doesn't work like I hope it will
[20:56] < VanL> ok, now really going. Thanks, mhrd-home
[20:56] *** VanL has parted #kamaelia
[20:57] < mhrd-home> np
[22:55] *** mhrd-home has parted #kamaelia