[00:02:36] Howdy _jpl_, how's it going? [00:05:20] <_jpl_> Pretty good. Taking my first stab at using DMs today. [00:06:56] Ahh. cool. I haven't played w/ the DM stuff yet. I'm basically just still playing around w/ composing heirarchies of components. Its getting clearer in my head now. [00:10:20] <_jpl_> I'm still undecided on whether I want to use a RDBMS or ZODB, though. ZODB would give me the flexibility I need, but an RDBMS would be better for interoperability. [00:11:52] Ya-- I've weighed that one my self. I don't have much experience using ZODB. Is there a DM in PEAK that uses ZODB? [00:12:25] <_jpl_> I think Phillip said no to that somewhere recently. [00:14:28] I wonder if that's on the roadmap for PEAK. There is sqllite support, so that gives you an embedded db at least. [00:15:20] <_jpl_> Yes, I'm trying to put together some DMs that are compatible with both SQLite and Postgres. [00:18:37] cool. What's the main difficulty in creating DM's that are compatible w/ different backends? Is it mainly in the SQL statement parameter quoting? [00:21:39] <_jpl_> It's all the little differences, like creating new keys (which every RDBMS seems to do differently), data type variations, DDL syntax variations, etc. [00:25:16] Ah. right. That's one of the few areas (at least datatypes) where I find java to actually be easier to program in than python. Its too bad they weren't able to harden the python db api a bit more to remove some of the variences between vendor drivers [00:25:52] <_jpl_> It's not so much the problem with the Python DB API as it is with the underlying databases themselves. [00:26:24] ya-- they all deviate from ANSI SQL in their own "labor saving" ways... [00:29:15] <_jpl_> The standard isn't that great to begin with. For example, it's always been a pain in the ass to have to write a completely different command for doing inserts versus updates, when what you really want is something like SQLite's INSERT OR REPLACE functionality. [01:18:47] just finished reading pje's posting on peak.web to the list. Good stuff coming on that end. Did you see that jack-e got ZPT working with peak.web? Not complete of course, but pretty far along in a short time. [01:19:13] <_jpl_> Yeah, I tried it but didn't have success. [01:19:35] <_jpl_> I want to get it to work, though, so I can try putting together a basic web app. [01:20:47] ya-- that would be cool. I think I'm going to play w/ using twisted woven, with a twisted http protocol listener being a peak component like we did w/ the echo app. [01:21:17] Its pretty cool seeing all these great frameworks starting to work together! [01:21:59] <_jpl_> Thanks to Phillip and PEAK, I think. [01:22:53] Yeah. he's done a great job of pinpointing where these frameworks can interoperate, and creating the glue when necessary. [01:24:55] <_jpl_> And PEAK does a lot more of the groundwork for you than the other frameworks, so it seems like a great foundation for the others. The "framework of frameworks". [01:27:23] yeah, I'd like to see it become used by the other frameworks. [02:04:14] <_jpl_> Groovy, I've gotten my first DM to work with both SQLite and Postgres. [02:05:14] <_jpl_> If you're careful enough with your SQL, you can simply provide a different DB object to the DM and all will be well. [03:58:27] <_Maniac> _jpl_: i'm working on my first DM's as well :) [04:09:41] <_Maniac> twisted based jabber stuff: [04:09:42] <_Maniac> http://www.jabberstudio.org/cgi-bin/viewcvs.cgi/hemp/README?rev=1.2&content-type=text/vnd.viewcvs-markup [04:11:22] <_Maniac> (looks like client/component support only) [06:12:42] [Global Notice] Hi all. We're going to be doing some rehubbing this morning; we're losing a European hub due to the sponsor going over bandwidth limits. There'll probably be further detail on wallops (/mode yournick +w). Thanks. [06:19:58] --> _Maniac has joined #peak [06:23:10] --> _Maniac has joined #peak [06:23:10] --> jolby has joined #peak [06:23:10] --> __gotcha_ has joined #peak [06:23:10] --> _jpl_ has joined #peak [09:04:20] --> jack-e has joined #peak [11:17:08] --> yarcat has joined #peak [11:18:48] hi. anyone alive? [11:22:04] who could help me? we are trying to run ZConfig, from command line on WinNT, using absolute paths, but ZConfig assumes, drive letter is a scheme and doesn't wanna proceed our .zconf file [11:22:12] what is the way to solve the problem? [11:22:56] i'm alive .. but i've no idea how to help you out ;-) [11:23:19] are you using it with peak or without ?? [11:24:02] with [11:24:38] have you tried using a "file:C:\\some\\path\\url" ? [11:25:04] i'll try, thnx [11:31:13] yarcat: does it work ?? [11:31:29] no. but i've got another error. [11:31:46] what error you get know ?? [11:31:58] OSError 2 :) File not found '' [11:32:44] the thing is, when there is a ":" in the url, the part left of the first ":" is the URL-scheme .. [11:32:57] so you'll need to use file: [11:33:04] oups sorry - it was not OSError, it was IOError [11:33:36] you could try other path-styles .. i don't know what ZConfig expects as path .. [11:33:39] so file:c:\smth [11:33:44] must work or not? [11:33:46] e.g. file:c:/som/path/ [11:33:55] did not help :( [11:35:11] Unknown scheme C in body "/som/path" [11:35:19] in Base, sorry [11:36:11] you could try it from python-prompt: [11:36:18] from peak.api import * [11:36:25] ctx = config.makeRoot() [11:37:20] adr = naming.lookup(ctx, "file:") [11:37:41] fd = adapt(adr, naming.IStreamFactory) [11:38:08] if you get this working (get a File-like object for fd) then use this for your ZConfig url [11:38:45] and adr schould be an address-object with scheme file and body your path [12:03:16] it's working... the only question is how to make it working from command line? [12:03:32] what url do you use now ? [12:04:12] file:e:/... [12:04:54] but this does not work for you when supplying the same url at the command-prompt (i assume you [12:05:20] are using the peak-script ? [12:05:25] * yarcat nods in agreement [12:07:06] hmm .. [12:07:21] i'm writing smth like a: [12:07:37] E:\src\Test>E:\Python22\python.exe E:\Python22\Scripts\peak ZConfig E:\src\Test\app_config.xml E:\src\Test\testfiles\SocketServer.cfg [12:07:42] in command line [12:09:08] i think you'll need to prepend file: for every path that has ":" in it .. otherwhise peak will assume that you gave an url with some unkown scheme .. [12:09:32] what about E:\src\Test>E:\Python22\python.exe E:\Python22\Scripts\peak ZConfig file:E:\src\Test\app_config.xml file:E:\src\Test\testfiles\SocketServer.cfg [12:09:34] ? [12:11:59] this was the way i tried to execute my application. and that was the point i had got and error message like: "Unknown scheme E in Base(body='\\src\\Test\\testfiles\SocketServer.cfg', scheme='E')" [12:12:57] i also tried to substitute E:\src\Test\app_config.xml with "file:E:/src/Test/app_config.xml" and i've got the same error message [12:13:38] then something seems to be wrong with the peak-zconfig-command parts .. please post a full traceback and the full path's how you try to invoke you app to the mailinglist .. pje (phillip) will look into this [12:14:01] this works fine with linux-shell for me [12:14:31] yes, but you do not have a drive letter in linux. when i'm not using absolute paths i also have a nice result [12:16:17] yes .. that's the problem with peak guessing it'ld be an url ... [12:27:56] i've post the full traceback to the mailing list... [13:11:20] --> Maniac has joined #peak [13:11:34] good day all [13:17:01] * jack-e is gone (3:17PM): .. autoaway .. [13:43:59] hey maniac [13:45:00] jack-e is back [13:46:04] i tried your demo_jabber.py [13:46:23] did you get it working ? [13:47:17] no [13:47:18] :) [13:47:21] hmpf [13:47:27] from peak.api import * [13:47:28] from nll.app import makeRoot [13:47:28] rctx = makeRoot() [13:47:28] jab = naming.lookup(rctx, 'jabber.client://test:test@srv02.net-labs.dev/testing', creationParent=rctx) [13:47:28] jab.connection [13:47:37] of course using my login etc. [13:47:41] jab.connection [13:47:50] >>> jab.connection [13:47:50] Traceback (most recent call last): [13:47:50] File "", line 1, in ? [13:47:50] AttributeError: 'JabberClientURL' object has no attribute 'connection' [13:48:03] [13:48:06] yeah .. that's code that needs to be rewritten [13:48:07] aren't i a barrel of laughs [13:48:12] ah ok [13:48:23] you need to adaptTo=IJabberClientConnection [13:48:31] to get a JabberClientConnection object [13:48:55] same as for sql-url vs. conn [13:53:45] just checked in a corrected version of demo_jabber.py [13:56:48] heh, ok i was trying to do it myself :) [13:57:05] * Maniac notes he should be 'working' [13:57:24] ah ok [14:01:17] did you try the corrected version? [14:05:04] err . nope ;-) [14:05:13] what's the problem now ?? [14:05:22] says global name debug not found [14:05:27] er defined [14:05:47] i see [14:07:56] debug = binding.bindToProperty('nll.net.jabber.client.debug') [14:08:11] this is where it is defined... [14:15:15] .. i've mostly used the JabberComponentConnection .. [14:15:34] but now JabberClientConnection should work again (cvs up, install and try demo again) [14:15:45] s/mostly/only [14:15:59] bbiab [14:20:09] i would guess the components are with regards to JOAP? [14:32:24] anywho, demo didn't quite work. i did it this way: [14:32:42] >>> from peak.api import * [14:32:42] >>> from nll.app import makeRoot [14:32:42] >>> from nll.net.jabber.interfaces import IJabberClientConnection [14:32:42] >>> rctx = makeRoot() [14:33:17] jab=rctx.lookupComponent('jabber.client://aUser:aPasswd@hydra/testing',adaptTo=IJabberClientConnection) [14:33:22] jab.connection [14:33:45] [14:37:32] back [14:38:18] maniac: the demo still doesn't work ?? (i tried pasting the code to the prompt with success) [14:38:25] OK [14:40:05] yarcat: did pje's answer solve your problem ?? [14:40:46] sorry i must have made a typo, it worked [14:41:11] maniac: ok [14:41:19] btw. thanks for testing ;-) [14:41:42] np. i hope i'm not being annoying [14:42:42] no .. not at all .. you're the first one outside our company who tried to use nll .. so like i said earlier .. don't expect too much .. but we'll help/fix as far as our time let us ;-) [14:49:24] jack-e: it just so happened there were/are alot of things in there that look interesting and i figure why duplicate. especially when most of it is quite a bit more (ok alot) more advanced than i would come up wiht [14:51:14] maniac: that's the intention of nll, to collect usefull components that are worthy to reuse by others .. and probably integrate contributions in future, when basics have settled down a bit [15:13:36] i'm working (one of many started and maybe never finshed projects) on a jabber bot that monitors my email accounts and sends an IM when i get new mail [15:13:43] hence looking at nll.net.jabber :) [15:14:54] yay .. have a look at joap.py and nll.messaging.provider.jabberqueuemanager for (not finished) examples how to build stuff with it [15:15:36] it's basically just providing components that offer IJabberIqHandler, IJabberPresenceHandler and IJabberMessageHandler [15:16:15] if components exist, that provide these config-keys (interfaces) they'll be used for dispatching all incoming stuff [15:16:37] then you'll need a task (i did subclass from EventDriven which is not a good showcase) [15:16:53] that cares about processing all incoming messages [15:17:05] and sends out the messages to be sent [15:18:44] so in jabberqueuemanager the JabberQueueManager-Component should not subclass EventDriven, but be a simple AdaptiveTask or something that hooks in a Task into the TaskQueue of the EventLoop [15:19:07] the Tasks Job is what is now in the __call__ method of that component [15:19:38] i have a instance-attribute self.outbout (list) that queues all ougoing messages [15:19:47] they are processed in this task as well [15:21:28] how does one integrate a GUI event loop into the jabber event loop (as a question) [15:22:08] for example wxPython has a process(duration) method on the Main App-Instance [15:22:29] this one would be called from within a task to handle all GUI-Events [15:23:12] you can look at twisted.internet wxreactor(or something like this), they do it the same way [15:24:20] i should be able to just do jab.connection.connect() no? [15:24:22] you call process(0.01) regularly instead of run() once [15:24:41] talking about the instances from the demo ?? [15:24:45] yes [15:25:02] i mean it won't 'do' anything but shouldnt' it connect? [15:25:15] jab is an JabberClientURL instance .. it only carries the necessary information how to connect [15:25:37] there is an adapter from JabberClientURL -> JabberClientConnection that you need to use to get the connection object for it [15:26:10] you can call any method on the JabberClientConnection object, and the connection is made automatically on the first attempt on self.connection [15:26:29] you don't call .connect(..) as well. you just use it [15:27:21] ok,ok... /me needs to understand not just cut and paste [15:27:24] so for example: con.process(0.1) would automatically connect cause it delegates the process-call to connection [15:27:39] :) [15:30:30] ok [15:30:33] so if i do: [15:30:36] while (1): [15:30:42] con.process(5) [15:30:46] it will loop forever [15:31:26] jep, the param for process is the same as for select (if nothing to read, wait for XX seconds and then return) [15:32:30] but you'll probably want to include the process() in your EventLoop (like the twistedPeak examples showed basically (you don't need twisted to use the EventLoop) [15:36:07] i just don't follow why you built up a queue. [15:36:50] ok i guess you have to queu them up and then dispatch / process [15:37:11] you could probably send it out directly (this would just replace self.outbound.append(msg) with self.connection.send(msg) [15:37:45] the intention was, that a call must not cause any delay in the processing [15:37:50] yeah, most clients i've looked at (at least simple ones) just blow them out [15:38:10] but a queue is a good idear too i think [15:39:04] the downside is, that you loose data from the queue, if your app crashes before all messages are send [15:39:30] (unless you have a persistent-queue) which is what i'll be working on in a few weeks again [15:40:32] and you feel JabberQueueManager should not subclass EventDriven? [15:41:11] yes .. JQM was my first contact with peak.running and i must admit i didn't really understand what i was doing [15:41:49] so .. there should be your "client-component" that has some attribute that registers a task in an EventDriven appliction (use twistedpeak as example for that) [15:42:39] the "client-component" registers a Task at the ITaskQueue, that does the in/outbound processing of you client [15:46:38] this task reschedules itself again (.queue.callLater(0,.method) [15:48:32] s/queue/reactor [15:48:59] or if you use an AdaptivetTask, it should automatically reschedule [15:49:20] you just need to implement getWork and doWork (like FileCleaner) [15:59:45] * Maniac looks at twistedpeak [16:23:25] so are you saying i could use what you have with some changes? [16:25:34] depends on what you define with "some" ;-) [16:25:55] you would have 1-3 HandlerComponents (Iq, Presence, Message) [16:26:23] you would write a "client-Component" that registers a Task (subclassed from AdaptiveTask) at the TaskQueue [16:26:36] the Task takes care that data is received and sent [16:26:41] the Handlers care about received data [16:27:10] your client could generate messages e.g. when new mail arrived (checking for new mail would be another task) [16:27:40] after all you fire up the EventDriven (configured with a ZConfig schema/file) and run it [16:28:15] you need to assemble your components somehow in a tree, that the jabber-client-connection can lookup you handler, the client-component can reach the TaskQueue and so on [16:28:49] how to assemle and configure look at twistedpeak [16:29:09] for hints about jabber-components (mostly how to create the handlers) look at the jabberqueuemanager.py [16:29:26] that's where i'm lookin now [16:30:34] handler have a "handle" method that gets called from the jabber-module [16:30:47] you propose that this is a handler for example: [16:30:58] class SomeClient(binding.Component): [16:31:24] myIqHandler = binding.New(MyIqHandlerClass, offerAs=[IJabberIqHandler,]) [16:32:07] myConnection = binding.bindTo('jabber.client://test:test@host/resource', adaptTo=IJabberClientConnection) [16:32:29] indent myConnection [16:35:59] ok, i think i need to start with something simpler. [16:36:58] .. you could leave out peak.running at all and try with your wile(1): process(1) trick for now .. if assembling all this is too hard [16:37:33] it's not too hard. it's just too different for me to see the whole picture [16:38:08] :) .. i know [16:38:47] i have a gut feeling it would be better long term if i did it that way. but i need a very simple roadmap to get there :) [16:40:13] as you see, i didn't find the right way as well with my steps done so far .. e.g. subclassing EventDriven was just because of not having the bigpic ;-) [16:41:12] i need to start small and build from there. i first thought imap then jabber things were good starts [16:41:12] :) [16:41:25] i KNOW i can do it the old fashioned way :) [17:00:48] --> pje has joined #peak [17:01:11] Bonjour. [17:01:16] hello pje [17:01:22] Willkommen :) [17:01:38] I noticed some questions about peak.running..l. [17:01:48] er /..l./.../ [17:02:02] Thought I'd pop in and see if I could clarify anything. [17:02:03] jack-e is trying to explain basics to me, however, i appear to be too dense [17:02:47] Well, he's not certain he's giving you the correct guidance anyway, IIUC. [17:03:00] :) [17:03:03] IIUC ? [17:03:09] If I Understant Correctly. [17:03:13] er Understand. [17:03:21] I seem to be typo-ing a lot today. [17:03:46] My question is, does the thing you need to poll have a 'fileno()' available? [17:04:11] Because if so, you don't need a periodic task, you need to addReader() and/or addWriter() to the IReactor. [17:04:43] * pje is assuming you are *not* using Twisted [17:04:56] no, i'm trying to use jabber [17:05:04] there is no twisted.protocols.jabber yet (unless jolby already contributed this one ;-) [17:05:24] jabber uses the xmlstream library [17:05:29] of course if there were i could just build on the echo example i would guess [17:05:40] Right, you could indeed. [17:05:59] when using the python-jabber connection objects you con.process(timeout) usually [17:06:10] But, if you're not using Twisted, you effectively have to do some of your own versions of things that 'twisted.protocols' do. [17:06:38] But is there a way to get to the underlying socket/stream/whatever that con.process() uses? [17:06:40] only if you want to do async [17:07:02] communication .. which would require a rewrite of the jabber module [17:07:22] I'm talking about "half async", not full async like Twisted. [17:07:45] Let me ask you this: are you trying to build something that just listens to jabber, and does things when it "hears" things? [17:07:55] i haven't yet looked at the details of the implementation of the jabber-module yet .. we should ask jobly .. he's working on a jabber-server with twisted :) [17:08:09] Or are you just trying to use it to do a synchronous conversation? [17:08:20] the first i think [17:08:32] Right. Then you need it to process things in a loop, yes? [17:08:33] jabber is async by nature i think [17:08:37] pje yes [17:08:54] maniac: but the jabber-module is not ;-) [17:09:00] (yet) [17:09:02] jack-e: also correct [17:09:33] Jack: that's okay, the FastCGI module isn't async either, but PEAK hooks it to the reactor anyway. [17:09:58] peak.running.commands.FastCGIAcceptor is an example of a "half async" wrapper over a non-async library. [17:10:17] traditional client (with jabberpy) do this: [17:10:33] birth jabber.Client [17:10:41] define callbacks to protocol elements [17:10:49] loop over process() [17:10:59] pje: ok [17:11:19] Okay, the only question is, how do you get the fileno() that's probably being used in process() as a select() parameter. [17:11:35] If you can get that, then you can make a simple wrapper like FastCGIAcceptor. [17:11:48] The wrapper will have a fileno() method that returns the fileno... [17:12:07] And a doRead() method that calls process() on the underlying client. [17:12:38] def process(self,timeout): [17:12:38] reader=Node [17:12:38] if self._connection == TCP: [17:12:38] reader = self._sock [17:12:38] elif self._connection == TCP_SSL: [17:12:39] reader = self._sock [17:12:40] All you need to do is 'reactor.addReader(wrapper)' to hook it into your event loop. [17:12:46] elif self._connection == STDIO: [17:12:47] reader = sys.stdin [17:12:47] else: [17:12:47] pass [17:12:49] ready_for_read,ready_for_write,err = \ [17:12:51] select( [reader],[],[],timeout) [17:12:53] for s in ready_for_read: [17:12:55] if s == reader: [17:12:57] if not len(self.read()): # length of 0 means disconnect [17:12:59] ## raise error("network error") ? [17:13:01] self.disconnected() [17:13:03] return False [17:13:05] return True [17:13:07] return False [17:13:11] is the process-method [17:13:31] So con._sock.fileno() is the fileno you need. [17:14:36] Or you can duplicate the logic used to set up 'reader'. [17:15:31] Also, it looks like instead of calling process() from doRead(), you may simply want to do: [17:15:52] if not len(con.read()): con.disconnected() [17:16:17] And not bother calling process(), since in doRead() you already have established that it is ready to read. [17:17:35] That's all you need to make it part of your event loop, which means you can follow the twisted-peak example for how to use EventDriven to run this. [17:17:40] this could be done in the JabberClientConnection (which is a ManagedConnection). it would have a whenAssembled=True binding to add the Reader which is implemented within the component and does what you just described ? [17:18:19] Sure. You could put the doRead() and fileno() methods right on the ManagedConnection. [17:18:42] that would be the most convenient way i think [17:19:10] maniac: i'll look into this soon (probably not today) [17:19:22] * Maniac is just standing back and trying to learn [17:20:17] Depending on what you're doing, you might could use a property namespace or ZConfig schema to map out responses to the jabber events. [17:21:39] Hm. I'm not sure you really want the ManagedConnection to addReader() itself, since that would force the use of a reactor. [17:22:00] Unless this connection class is only ever used for half-async, and is never used for synchronous. [17:22:16] so provide another adapter for that eventually ?? [17:22:32] It makes sense to have the ManagedConnection be its own reader (doRead()/fileno())... [17:22:57] I just think that its *owner* should register it with the reactor, if it wants to. [17:23:03] ahh .. ok [17:23:09] makes sense .. right [17:23:34] So, lets say you have a "JabberListener" component that wants to do half-async, it should have a whenAssembled() method to 'self.reactor.addReader(self.conn)' [17:24:14] * jack-e will reread the irc-log and implement this stuff 2morrow probably :-) [17:24:18] Whereas a component that doesn't need the connection in an event loop, and just wants to poll it, can just have the connection object. [17:24:28] * Maniac hopes so, because it's over his head right now [17:25:35] Jack: what's the URL to browse the source of this? [17:25:50] mompl [17:26:07] Eh? [17:26:12] moment please [17:26:16] Ah. :) [17:26:43] I was thinking something like 'Message-Oriented Middleware Persistent Link'... :) [17:27:02] we're not that far with our messaging stuff yet ;-) [17:27:15] http://cvs.net-labs.de/cgi-bin/viewcvs.cgi/apps/nll/src/nll/net/jabber/connection.py?rev=1.6&content-type=text/vnd.viewcvs-markup [17:27:27] this is the connection module [17:27:30] pje: honestly the twisted peak example to me looks like a very straight forward twisted sample which became complicated when peak was injected (no insult intended) [17:27:54] that uses the jabber-py module for jabber.communication [17:28:26] or at least it injected some magic that i'm sure will help in the long run, but i still am trying to put it all together in my head [17:29:27] It depends on whether Twisted or PEAK are your primary runtime environment. [17:29:48] "It's not how the dancing bear dances, but that it dances at all." [17:29:56] @all .. i'll have to go .. cu all soon [17:30:06] Have a good one, Jack. [17:30:11] bye [17:30:45] PEAK is mainly intended to be "upward compatible" with PEAK where event-driven apps are concerned. [17:30:55] er, with Twisted, I mean. :) [17:31:24] But, to do simple event-driven apps (just periodic tasks and the occasional half-async I/O), it doesn't require Twisted. [17:33:10] You'll notice that these goals are not the same as, "make it easy to use Twisted stuff in the PEAK framework". :) [17:36:01] whew! -- just finished scrolling. Hi All. bummer, I just missed jack-e [17:36:56] Hi Maniac. I'm just finished reading about your trials w/ trying to make a PEAK+twisted+jabber client. [17:38:12] If you're using the echoserver example, I tried to make it a series of examples of ascending complexity. For instance, If you just call the EchoRunner directly, its not much more complicated than using bare twisted. [17:38:22] (run-tp, run-tp2 scripts) [17:38:54] Its the .ini, and ZConfig stuff that add to the complexity quite a bit. [17:40:43] Lunch has arrived... gotta run. [17:40:47] As I'm understanding how PEAK + twisted should work together, (and I could be wrong). It seems like PEAK will take over the job that a twisted Application object would do. [17:40:51] bye pje [17:40:58] BBL... [17:41:04] Au revoir. [17:41:25] Maniac: does that make any sense? [17:54:00] * Maniac just returned [17:55:40] jolby: i guess so. [17:55:57] jolby: i still don't really grok how to 'build' or assemble an application in PEAK twisted or otherwise [17:58:22] Yeah-- I'm still learning the "composing hierarchies of components in PEAK" part of PEAK as well. I made a simple example this weekend just to wrap my head around it, and I"m going to post it to the wiki. Hopefully it will help folks out until pje finishes the "composing hierarchies" chapter of the tutorial done [18:22:43] heh, from the mailing list archives that part has been a work in process since Janurary-ish [18:22:45] which is cool. [18:23:24] all my 'programming' consists of taking examples and manipulating into what i want [18:23:42] PEAK is short of examples so this is a bigger stretch than i'm used to [18:54:40] <_jpl_> Hi all, looks like I missed everyone. [18:54:49] <_jpl_> Well, Phillip and Ulrich anyway. :) [18:55:29] <_jpl_> Oops, and now I have a meeting to attend. [19:20:31] I've put a short example (with code) of composing hiearchies on the wiki: [19:20:43] http://peak.telecommunity.com/DevGuide/ComposingHierarchies [19:20:53] I'll post this link to the list as well [19:21:25] * Maniac goes to read [19:38:11] <_jpl_> Nice example, Joel. [19:39:50] <_jpl_> Though, rather than import from peak.interface, you can simply refer to protocols.Interface and protocols.Attribute (you get protocols with "from peak.api import *") [19:43:16] Ahh. ok. [19:43:29] I can change that. [19:45:01] <_jpl_> And in list literals you don't need the trailing commas for a single item as you do with tuples. [19:46:16] <_jpl_> i.e. in your protocols.advise calls... also there's an extra comma after the instancesProvice that could go. [19:46:22] <_jpl_> er, instancesProvide [19:47:46] ok. I made those changes. [20:23:02] see this peer review is cool [20:23:07] XP [20:37:49] hehe-- yeah. Wikis are good that way. [20:38:47] Maniac: So does that example help you grok how to build PEAK applications from different components a little better? [21:01:57] a little :) [22:59:26] <-- Maniac has quit #peak