[00:34:18] There, another chapter finished. [01:06:59] ** pje has joined us [01:07:14] Looks like the party's already over. [01:09:39] I just came by to thank R.D. again for the fine work on HelloWorld. [01:13:50] Well, guess I better get some sleep. Later, all. [01:13:57] ** pje has left us [04:24:38] ** hazmat has joined us [10:46:24] * Maniac just noticed helloworld chapter 2 [11:06:47] ** rdmurray has joined us [13:06:16] wee, i just noticed victor ng's posting that made it to the daily pythonURL [13:13:41] What's the daily python url? [13:16:13] http://www.pythonware.com/daily/ [13:16:27] you are not a pythonista until you read it.... daiy [13:16:29] daily [13:16:30] :) [13:16:39] (not that i do) [13:29:55] Hmm. That's weird. No rss feed. [13:36:15] it has one, i just can't find ti [13:36:16] it [13:36:31] Well, it isn't liked from the 'rss' link at the bottom of the page, that's for sure. [13:36:52] http://www.pythonware.com/daily/rss.xml [13:36:56] found it [13:50:06] Thanks. I just started using an rss reader, so I'm still collecting interesting feeds :) [13:54:21] no prob. [13:54:28] * Maniac is tired of working weekends [13:54:30] * Maniac is heading home [13:54:37] bye. [13:54:45] my irc client will still be around :) [13:54:51] :) [15:23:05] ** pje has joined us [15:23:12] Howdy. [15:23:29] Just popped in to say thanks yet again re: Hello World. [15:23:58] I hope you don't mind how much I've hacked on^H^H^H^H^H^H^Hrefactored it. :) [15:24:54] And I also hope I haven't slowed its pace down too much by the use of smaller steps for the first chapter. [15:32:57] No problem. I wouldn't judge anything I've seen so far as a dis-improvement, and learning the new stuff you've added is a good reward for having written it :) [15:34:52] Have you read the latest one, with all the help/usage stuff? [15:34:59] Looking at it now. [15:36:33] Mostly, all I did was break down concepts you presented into smaller pieces. [15:36:51] That's usually a good thing. [15:37:03] And used the system's own help messages to serve as prompts of what to do next, so that it seemed less like you just had to magically know things. :) [15:37:27] That way, I hope people will see, "oh, I can run things and look at them and figure out stuff from that." [15:37:39] Yeah, that sounds good. [15:37:51] Instead of thinking they have to already be initiated into the sacred mysteries of PEAK. :) [15:38:14] Of course, the first thing I did in that regard was type "peak help", and the response to that didn't lead me anywhere. [15:38:16] Usually it's a good thing, but not if it slows the pace down too much. [15:38:40] I mean, it's now a pretty huge page with two chapters just to say "Hello World". :) [15:39:02] So, somebody might use that to conclude that PEAK is ridiculously hard and complex, if it takes that much to do hello world! [15:39:15] And I've already got an outline for chapter 3 in my head :) [15:39:37] So I'm thinking maybe we should call it the "Grand Tour" or something. [15:39:42] Sure. [15:39:49] * pje grins [15:39:56] Or "HelloWorld Grows Up" :) [15:40:01] By the way, 'peak help' will become more helpful once I get around it. [15:40:05] k [15:40:06] Er, around to it. [15:40:28] I want it to do imports, so you can say e.g. 'peak help peak.util.fmtparse'. [15:40:38] I don't usually think of typing a command with no arguments to look for help information, because some commands *do* something if you don't give them any arguments. [15:40:43] And a way to get help on other kinds of objects would be nice too. [15:40:53] Hm, true. [15:41:03] They should really have -h/--help options. [15:41:41] But that should wait until we have the option parsing framework in place. [15:41:56] Otherwise, it won't be consistently available. [15:42:05] makes sense [15:44:03] I'd also like 'peak help' to be able to list some topics. [15:44:14] And maybe shortcuts, too. [15:44:37] But those are both a ways off. I think the first step is going to be to make sure that it says something helpful for anything that you might pick. :) [15:45:09] That's true for lots of things now, but there are also lots of gaps in the docstrings, or sometimes they only make sense in the context of the module they came from. [15:45:16] So that's a big job. [15:45:28] Anyway, I've got to run or I'm not going to make it to the fish market before it closes. [15:46:12] See y'all later. [15:46:36] see you [15:46:39] Bye. [15:46:41] ** pje has left us [18:20:25] Hmm. Why does AbstractCommand talk about "files"? Isn't it up to the concrete class to decide how to interpret the argument? [18:37:32] wow, that hello world is really turning into something fantastic. I really wish i had that when i discovered peak... [18:37:41] so what will chapter 3 bring? [18:37:54] subcommands and writing to a database. [18:38:22] aha! [18:38:29] You know, what's amazing is all the stuff I'm leaving out, that I only have a glimmering of myself. [18:38:32] rdmurray, are you a python progammer by trade? [18:38:48] I aspire to be. [18:39:13] I've been programming python for almost ten years now, but my day job up until recently was director of technology for an ISP. [18:39:23] googling rdmurray finds alot of zope references :) [18:39:30] Now I'm an independent consultant, and doing what I *want* to do :) [18:39:50] Yeah, I helped out a small amount on Z3 last year [18:40:00] i came across python 2 years ago (almost to the day) and am NOT a programmer [18:40:12] i have a totally non programming job, this is my hobby :) [18:40:15] I used zope for three years at my last job. [18:40:34] (so keep that in mind when i ask dumb questions :) ) [18:40:40] np [18:40:52] Python is great language to learn programming in. [18:41:13] It's much easier than trying to follow PJE's code would lead you to believe :) [18:41:50] peak is some of the more complicated python i've come across, that and twisted can be difficult to grasp [18:42:14] Yeah, its because both of them use deep concepts from program design theory. [18:42:18] as in, what the f*ck is a deferred [18:42:24] :) [18:42:50] but i have a *minimal* grasp of both now [18:42:58] and use peak for all my little projects. [18:43:18] peak.config and peak.binding are very usefull even in small sysadminish type scripts [18:43:36] Actually, one of the beauties of PEAK is how simple the individual bits of code are. It's how they all hang together that twists your brain :) [18:44:24] Yeah, one of the things I did for my old job was write scripts, and I sure wish I'd had PEAK then. [18:44:34] I'll probably never write another script without it :) [18:45:06] * Maniac has to get ready to go out [18:45:12] christmas party tonight (work) [18:45:23] l8tr [18:45:55] have fun [21:35:23] ** hazmat has joined us [21:36:46] I need a 're' regexp to match against xxx|yyyyyyy where this will be preceeded and followed by newlines. It seems to me r"^xxx\|(.*)$ should match, but it isn't. [21:36:51] I'm using re.M [21:39:05] Woops. I only thought I was using re.M. [21:39:08] * rdmurray blushes [21:42:01] Urm. [22:45:26] ** pje has joined us [22:45:30] re [22:45:46] 'lo [22:46:36] * pje is catching up on Groklaw [22:47:16] heh [22:47:56] "SCO vs the World: the most popular soap opera of all time". At least among geeks :) [22:48:09] Yep. [22:48:21] Nice to hear about the drubbing they took yesterday. [22:48:25] Finally! [22:51:01] The big show should be in 30 days, I hope. [22:51:22] Yes. [22:51:35] I still worry that they have something really really evil up their sleeves, though. [22:51:36] Too bad the judge couldn't pull it in a week or so and give it to us for a christmas present :) [22:52:03] I imagine she doesn't want to end up like the judge in the MS antritrust suit... overrruled due to an appearance of bias. [22:52:17] Hm, I think I had too many 'r's in there. [22:52:32] Anyway, that's what I worry about... "trickses, my precious". [22:53:19] That maybe they don't *need* to win in court, and don't care. [22:53:35] And what they have planned is worse than anything the court case could do. [22:53:44] But, I'm a paranoid kind of guy. :) [22:54:12] Well, they *are* out to get us, after all :) [22:55:09] Yeah, I guess you're right. :) [22:55:16] It is hard to imagine that a bunch of guys in their position could be so irrational, clueless, and ultimately loosers. But just because they've made money in the past doesn't mean they can't do something really stupid. Look at Enron, after all. [22:55:17] So, maybe I'm just *normal*. [22:55:22] * pje shudders. Scary thought. [22:55:33] I see your point. [22:55:48] :w [22:55:51] Never thought I'd be in the position of hoping some people are just incompetent. :) [22:55:53] woops, wrong window [22:55:58] heh [22:56:24] "Never blame on malice what can adequately be explained by incompetence". [22:56:33] Of course, in this case there is certainly malice. [22:58:06] Well, at the very least avarice. [22:58:42] So, was that regex question something for your next tutorial chapter? :) [22:58:48] yeah. [22:58:52] I figured it out. [22:58:59] * pje nods [22:59:11] Gotta wonder why you needed a regex for it though. [22:59:30] It seemed like split('|',1) would've sufficed for what you mentioned. [22:59:40] I was surprised that MessageDM['newkey'] = Message() didn't work, but I guess I understand why. [22:59:54] Ah. [23:00:03] Oh, I'm doing a little trickery with EditbleFile. [23:00:07] It's message = MessageDM.newItem(). [23:00:16] Yeah, I figured that out. [23:00:41] What's the protocol for xxx in someDM? [23:00:49] * pje almost hates to mention that the current DM interface may mutate horribly from this in alpha 4. [23:00:57] xxx in someDM? [23:01:00] Wha? [23:01:17] figuring out if a given oid currently exists in the database. [23:01:31] Seems to be necessary to avoid calilng _new with an existing key. [23:01:50] I think I must be looking at things wrong. [23:02:14] No, you're looking at a nasty limitation of the way things currently work. [23:02:20] ah. [23:02:32] Addressed in alpha4? :) [23:02:36] That is a part of why the interface (and especially implementation) are likely to change dramatically in a4. [23:02:41] Yep. [23:03:02] k, I won't spend much more time on it then. [23:03:12] If you want practical advice on what to do about it, I'd suggest you ask Ulrich, who at this point has done significantly more work with DM's than I have! [23:04:02] I'm just going to punt in the tutorial, and say this will be fixed in a later release. [23:04:22] In my own code it won't matter, since all my dbs are append-only. [23:04:27] * pje nods. [23:04:50] I imagine if you ask Ulrich, he'll probably say he just implements __contains__ or has_key if he really needs to check. [23:05:11] Certainly, nothing stops you from doing that. [23:05:14] That's what I was thinking. [23:05:28] It just seems sort of wrong that I should have to check :) [23:05:49] There's just no framework support for it, or any guarantee that a given DM supports it, unless you create your own subclass of the DM interface. [23:06:10] OTOH, extending the DM interface might be a good way to lead into protocols, and custom configuration keys. [23:06:29] e.g. "ExistenceCheckableDMFor(elementClass)" :) [23:06:52] On the *other* other hand, that's probably way too advanced for any part of this tutorial. :) [23:06:58] No sense scaring people away. :) [23:07:19] Heh. Yeah. [23:07:50] I keep being impressed by how much more there is than what I'm covering, given that what I'm covering is a fair bit of cool stuff. [23:07:51] I'm really surprised at how good this tutorial thing has been working out. [23:08:00] * pje laughs. [23:08:05] Ironically enough, I am too. [23:08:15] (impressed by how much we're leaving out) [23:08:41] heh [23:08:49] Anyway, I never in a million years would have thought of starting a PEAK-wide tutorial with the commands framework. [23:09:07] Followed by config, then binding, then over to model and storage and back... [23:09:22] But it works a lot better than *anything* I've tried to write before. [23:09:28] (about PEAK, I mean.) [23:09:28] Interesting. [23:09:31] * pje grins [23:10:02] I always want to explain things bottom-up. [23:10:19] Starting from the simple PEAK subatomic particles (like bindings) and working my way up from there. [23:10:35] On the theory that if you understand the parts, you will not have any errors in your thoughts about the whole. [23:10:37] I actually started learning it from Model, then to Storage, then to Commands. [23:11:16] The problem with my approach is that it takes way too long to learn anything really *useful*. [23:11:42] Well, I find that when I learn something, I learn pieces, but I don't *understand* anything until I have an overall framework to hang them on. Once I have a framework, learning speeds up tremendously. [23:11:44] Your top-down approach put *life* into the content. [23:12:11] Yeah, I can see that. [23:12:40] But I was never able to let go enough of my desire for precision and accuracy, to be happy writing generalizations. [23:13:09] However, with *you* writing the generalizations, I could feel free to step in and tune them a little so they never say anything that's false or misleading. [23:13:35] Yeah, that makes sense. Whereas I have no problem writing the generalizations, because I don't know any better :) [23:13:48] (And hopefully I'm not doing so much of that that I'm killing the original life of your work.) [23:14:13] Right. You're not clinging to a particular way of presenting things, based on your vision of what they are. [23:14:20] Whereas I *am*. [23:14:45] Well, I'm more worried about the usefulness of it than I am of how exciting a read it is :) [23:14:48] So I end up either talking more about the vision than the tools, or else I become hopelessly bogged down in trying to make people *understand*. [23:15:16] Usefulness is good, but it's not useful if people fall asleep, or give up because it seems like it's not going anywhere. [23:15:41] Still, I'm probably worrying too much, because each section is maybe only a page of content, and each contains large chunks of code. [23:16:12] I guess the only part I specifically am worried about is the digressions into PYTHONPATH, executable config files, and scripting. [23:16:37] Because it doesn't really "advance the plot" at that point. :) [23:16:57] But it's probably an interesting enough digression for Unix weenies. [23:17:09] Yeah. And that's most of the audience right now. [23:17:15] * pje chuckles [23:17:32] There's a substantial minority of Windows and Mac users on the mailing list. [23:17:50] Some who write code commercially that's deployed on Windows. [23:18:08] But I guess all the people I'm thinking of don't necessarily need this tutorial *now*, anyway. :) [23:18:33] Again, I am undone by my perfectionism, and desire to leave nothing undone. :) [23:19:34] I'm curious whether we can build this into something that gives a little taste of *all* the frameworks in PEAK. [23:19:51] For example, I was thinking about showing logging as a good place to go from the end of chapter 2. [23:20:57] I'm doing subcommands and writable DM in 3, and I was planning on doing SQL in 4. But Logging could fit in there anywhere, I'd say. [23:21:30] It also might be a good lead-in to naming. [23:21:31] (SQL giving an opportunity to talk about naming some more) [23:21:51] * pje nods [23:22:02] And 'n2' ties in to both naming and SQL. [23:22:14] n2? [23:22:25] Don't tell me you don't know about n2... [23:22:33] 'peak n2 name_or_url' [23:22:43] Nope, no clue. [23:22:52] You're in for a treat, then. [23:23:12] Try 'peak n2 --help' [23:23:37] Or, if you have an SQL DB, try 'peak n2 thedb:whatever' [23:23:52] Where 'thedb:whatever' is a PEAK SQL URL. [23:24:18] You'll be at a prompt where you can type SQL commands. [23:24:44] And if you have the GNU readline module for Python, you'll have history and even completion of table names. [23:24:52] It sounds cool, but I only have a glimmering of what it means :) [23:25:03] What what means? [23:25:21] It's an interactive shell for working with namespaces and SQL databases. [23:25:40] Or anything else you want to write an interaction adapter for, that can be accessed by name or URL. [23:26:20] For example, if you're working with a database, you can type \python and drop into the Python interpreter, with the connection object in the 'c' variable. [23:26:35] So you can then write some quick Python code to pull something out of the DB and do something with it. [23:27:02] Ah, that definately sounds cool. [23:28:04] One could probably write a whole manual just about that :) [23:28:15] Indeed. [23:28:24] That one's Ty's work. I didn't write any of it. [23:28:40] It also has a "namespace shell", where you can 'cd' and 'ls' in naming services. [23:29:13] If you have 'nis' services on your machine, try 'peak n2 nis:', and you'll be able to 'ls' services on your machine. [23:30:19] 'n2' actually is a pun on "namespace navigator", which is what I wanted to call it. [23:30:38] Ty wanted to call it something else, I forget what. Maybe "peek". [23:30:56] We compromised on "peak n2" a pun on "peek into" and "namespace navigator". :) [23:30:58] I have neither sql nor nis at the moment. [23:31:17] Ah. Alas, there's not much else you can do with it, unless you write another naming service. [23:31:31] Ulrich has written some naming services IIRC. [23:32:22] At work, Ty and I have other homegrown naming services, that were developed years ago as a quick fix for certain problems. [23:32:32] (enterprise app config problems) [23:32:35] This weird. I had my program failing nicely, and I made a small refactoring, and now insetad of throwing the error it is going off into never-never land somewhere. [23:33:02] So, n2 is much handier for us at work than anywhere else right now. That's where all our SQL and naming service usage is. [23:33:04] I must have created an recursive loop somehow. [23:33:10] Hmm. What seems to be the trouble? [23:34:39] Well, I made my _new method check to see if the key alredy exists and thow a KeyError if it does. That was working, then I refactored how the regex gets compiled, and now it hangs. [23:35:29] Well, if you're using bindings, it can't be recursive. [23:35:41] Oh, nevermind, I made another change that I forgot to back out. [23:35:43] I say that, because bindings have a recursion guard built into them. [23:36:00] Yeah, that did it. [23:36:07] * pje nods [23:36:14] It's always the little things. :) [23:36:24] It was doing the " key in DM " that went off into never never land. [23:36:31] Wonder why that didn't just throw an error. [23:38:02] Do you have a __contains__ method? [23:38:17] Nope. [23:38:36] Hm. I wonder if Python tries to use __getitem__ in that case? [23:38:49] I think it does. [23:39:10] Ooh. [23:39:12] Worse still... [23:39:17] It checks *numerically* [23:39:18] Not sure, though. [23:39:22] Oh, yeah. [23:39:23] I just did a test in the shell. [23:39:34] Try this... [23:39:49] >>> class test(object): [23:39:49] def __getitem__(self,key): [23:39:49] print "looking for",key [23:39:49] [23:39:50] >>> t=test() [23:39:52] >>> 123 in t [23:39:54] looking for 0 [23:39:56] looking for 1 [23:40:00] looking for 2 [23:40:02] looking for 3 [23:40:04] looking for 4 [23:40:05] I think there's some way to disable that by defining some magic method. [23:40:06] looking for 5 [23:40:08] looking for 6 [23:40:10] looking for 7 [23:40:12] looking for 8 [23:40:14] looking for 9 [23:40:16] looking for 10 [23:40:18] looking for 11 [23:40:20] looking for 12 [23:40:22] looking for 13 [23:40:24] looking for 14 [23:40:26] looking for 15 [23:40:30] looking for 16 [23:40:32] looking for 17 [23:40:34] looking for 18 [23:40:36] And it continues from there. :) [23:40:37] It does that until __getimte__ raise a SequenceError, or some such. [23:40:38] Yeah, __contains__! [23:40:40] Heh. [23:40:42] I guess maybe DM's should have a default __contains__ method. [23:40:44] IndexError. [23:40:49] right [23:41:24] So what's the DM doing when it gets called with, say, '1'? Just building ghosts? [23:41:38] Guess it would have to. [23:41:47] Yep. [23:42:05] Which means you could have _ghost raise a KeyError in that case. [23:43:07] In the case that the key didn't exist. Makes sense. [23:43:21] Or, maybe returning 'None' from _ghost should cause __getitem__ to raise the KeyError. [23:44:00] Seems like that would be handy. [23:44:46] The problem with it is that __getitem__ is really supposed to do a delayed load. [23:45:05] And having _ghost() check key validity, forces it to load immediately. [23:45:10] Right. So it should be up to the DM implementation to decide if checking keys is good. [23:45:17] Yep. [23:45:34] More than that, it highlights the interface flaw that I want to fix in 0.5a4. [23:45:35] There are certainly applications where you need to be able to check. [23:45:43] Specifically, DM's need *two* interfaces. [23:45:50] One for lazy loading, one for eager querying. [23:46:02] The lazy load interface is only needed for inter-object references. [23:46:17] Application code retrieving an item directly, wants and needs eager loading. [23:46:30] Make sense. [23:46:52] So, in the future, you'll use DM.get(someKey=someVal) to retrieve an item. [23:47:17] And __getitem__ will become some other method name, and be used only by other DM's to load ghosts for referenced objects. [23:47:37] And DM.find() will be a standard method to find multiple items, using kwargs to do filtering. [23:47:57] Why not keep the convenience of the [xxx] notation for the common case? [23:48:12] backward compatabiity? [23:48:22] More like incompatibility. :) [23:48:27] yeah :) [23:48:32] But the real reason is that it's *wrong*. [23:48:45] It implies that there is and can be only *one* "key" for an object. [23:48:52] And that's just not true in many domains. [23:49:20] Also, you might have noticed that there's invariably duplication between _p_oid, and one of an object's fields/attributes. [23:49:38] Right [23:49:50] OK, that makes sense. [23:49:52] If you don't have to have only one key, that problem goes away. [23:50:50] If you have a hidden key that doesn't show up in the model (like a DBMS object id or serial #), that might be exposed to the DM-to-DM interface, but not the public find/get. [23:51:04] (Because it's an implementation detail.) [23:51:37] Of course, this is all assuming that the future peak.storage will still use separate DM's for different classes! [23:52:04] Heh. [23:52:18] the alternative being? [23:52:23] There may simply be a "database" component, and a schema map. [23:52:27] Well, fixing the tutorial will be simpler if it doesn't. Just cut a lot of material :) [23:52:32] * pje laughs [23:52:55] What do I do if I want to have a 'secret' key like that now? [23:53:07] You'd ask the database something like db.find(Message, forname='fred') [23:53:15] Do I have to put it in the model, or can I just stuff an attribute onto the 'ob' that I'm passed? [23:53:24] You can use it as the oid. [23:53:33] In fact, you'd have to use it as the oid. [23:53:41] Hmm. [23:53:47] granted class dm's are more typing, but i find them more flexible for implementing additional domain logic [23:53:47] Which is really the problem with the current setup. It forces that "hidden" key into the open. [23:54:14] hazmat, you could put them on the database, or a subcomponent thereof. [23:54:27] But I'm curious what sort of domain logic you put there. [23:54:30] hazmat: why is your domain logic going into the DM? Shouldn't be in th emodel? [23:54:45] but i haven't really used peak, i'm here as an uninformed lurker, who shall probably go back to lurking mode [23:55:04] Yeah, that was what I was going to ask. I've been moving away from the old Specialist model of putting domain logic in Specialists. [23:55:29] Because there's usually a domain object that it can move to, although there's usually only one instance of that object. [23:55:52] Like say 'Store' in a point-of-sale system. [23:56:23] but say for example, i want to do additional work when storing/retrieving an object, where would that code go? [23:56:35] What additional work do you mean? [23:58:11] variable, messaging external systems, transformations of object, additional modifications to data model (like clickstream analysis for data objects) [23:58:26] i'm just tossing out things.. feel free to cry yagni on something ;-) [23:59:02] or translating yagni to there is a better way todo it. [23:59:32] * hazmat goes to look for a real example