[04:02:29] [connected at Sat May 14 04:02:29 2005] [04:02:29] <> *** Looking up your hostname... [04:02:29] <> *** Checking ident [04:02:29] <> *** Found your hostname [04:03:00] <> *** No identd (auth) response [04:03:00] <> *** Your host is niven.freenode.net[niven.freenode.osuosl.org/6667], running version dancer-ircd-1.0.35 [04:03:00] [I have joined #peak] [04:03:00] ** niven.freenode.net set the topic to http://dirtsimple.org/2005/04/generic-functions-reloaded.html [12:14:46] ** s1x has joined us [12:14:48] lo all [12:14:57] how do I load a config file? [12:16:38] i tried: root = config.makeRoot(); obj = binding.Configurable(root); config.loadConfigFile (obj, "/some/file.ini") [12:16:44] but it didn't work [13:16:37] ** s1x has left us [13:35:54] ** pje has joined us [13:37:04] ** s1x has joined us [13:37:09] hi pje :) [13:37:22] Hi. Could you go ahead and define "didn't work"? [13:37:33] the example I pasted here didn't work because it could't find the configuration filed [13:37:38] Just FYI, config.loadConfigFile and loadConfigFiles do not generate errors when given non-existent files [13:37:56] This is so that you can e.g. supply a list of standard locations for optional configuration files [13:38:05] that's what i guessed, becaue i tried issuing a bogus value [13:38:13] ah [13:38:20] well i solved my problem using: root = config.makeRoot(iniFiles= [("peak","peak.ini"), ("__main__", "app.ini")]) [13:39:09] but i donb't know if that's the correct way to do it [13:39:42] If you use 'config.getStreamFactory(ctx,filename).exists()', you can check for its existence [13:40:11] what is the context? the root component? [13:40:13] I've been thinking about adding an option to loadCongfigFile() though, to have it raise an error for a missing file. [13:40:20] Any component will do. [13:40:28] As long as it *has* a config root. [13:40:42] I see [13:40:52] and as I've done it, is it correct? [13:41:01] see 'peak help config.getStreamFactory' for more on that [13:41:09] Oh, the way you've done it is fine [13:41:16] kk :) [13:41:30] thx for the interest in providing an answer :P [13:41:39] you're ever so helpful! [13:41:53] Although you could also do config.packageFile('__main__', 'app.ini') [13:42:11] ** debugger has joined us [13:42:22] And that would be the preferred way, as I'd like to phase out the special case for tuples in IniLoader [13:42:34] i see [13:42:51] what does it return? [13:43:02] PEAK itself no longer uses ('peak','peak.ini'); it uses config.packageFile('peak','peak.ini') [13:43:08] It returns a stream source [13:43:11] hellos [13:43:16] hi debugger [13:43:19] A naming.IStreamFactory, to be precise [13:43:27] See 'peak help config.packageFile' for details [13:43:30] what is that for? [13:43:45] A stream factory is like a virtual filename [13:43:59] It has methods for 'open()', 'exists()', and stuff like that [13:44:20] what i don't understand is how do I couple the object returned with my component [13:44:39] Oh, sorry; I was saying use it in the 'iniFiles' list instead of a tuple. [13:45:10] root = config.makeRoot(iniFiles= [config.packageFile("peak","peak.ini"), config.packageFile("__main__", "app.ini")]) [13:45:12] In other words. [13:45:16] ok [13:45:16] :) [13:45:18] cool [13:45:50] A few months back I refactored most everything in PEAK to use stream factories instead of filenames or URLs. [13:46:03] ah, ok [13:46:09] :) then that's why [13:46:12] And to use config.getStreamSource() to convert filenames into stream factories [13:46:44] But getStreamSource() will return a factory unchanged if you pass one in, so basically the lingua franca is stream factories. [13:46:56] And everything uses getStreamSource just to make sure that strings get converted. [13:47:09] ehe [13:47:10] Of course, if a string is a valid URL, then it's interpreted as a URL by getStreamSource [13:47:22] by adaptation [13:47:24] Which is what it needs the 'context' argument for [13:47:34] Actually it's a generic function. [13:47:45] But the GF is powered by adaptation under the hood. :) [13:47:49] are generic functiuons replacing adaptation? [13:47:54] ah [13:48:01] For lots of things, yes, they are. [13:48:18] thay're really nice, i've started using them already [13:48:31] i've read in an email you sent that DM's are "legacy" [13:48:34] getStreamSource is a single-dispatch generic, though, not a full predicate dispatch. [13:48:50] s1x, yes, but they're a legacy that hasn't actually been replaced by anything yet. :) [13:48:56] lol [13:49:05] but what's ur ideat to replace it for? [13:49:33] Short explanation - sets as databases. [13:49:49] just using sets? [13:49:54] You'll have a "session" or "connection" or "workspace" object that is just a set of all objects in a DB [13:50:08] And sets will have querying methods, and event notifications about changes to them. [13:50:19] the peak.schema? [13:50:27] By "set" I mean a set interface, not the builtin set type [13:50:37] yes [13:50:49] The whole concept is peak.schema, yes, as far as how the object schemas will be defined. [13:51:09] I've been working on something similar for OSAF, which is nice but then it means I don't have time to work on the one for PEAK [13:51:25] :) [13:51:39] indeed. and what about peak.web? My first iteration with it was not that successfull ;) [13:51:56] Well, there's a demo sitemap for the bulletins example now [13:52:01] however I intend to test the new changes you put in cvs [13:53:33] A big difference between working for Verio and working for OSAF is that 1. web stuff isn't nearly as relevant and 2. most of the problems PEAK tackles are bigger in scope than the problems being tackled by OSAF. [13:53:56] Also, OSAF is making a client app and PEAK is a little biased towards server apps ATM. [13:54:05] indeed [13:54:27] So, there's not anywhere near as much overlap between PEAK and my day job anymore, and by the time I get done with my OSAF work day I often don't even want to look at the computer. :) [13:54:28] but the component based desing rocks for every GUI app, IMO [13:54:43] lol [13:54:58] Yeah, but Chandler already has its own UI framework, designed around persistent UI objects. [13:55:09] i see [13:55:20] i.e., the UI is designed to be able to be modified by a user, directly in the DB... sort of like Zope but a GUI instead of web. [13:55:38] And unlike Zope the initial population of the DB is from a file. :) [13:55:46] eheh [13:55:51] strange :) [13:56:00] And of course they have their own ZODB-like DB. [13:56:39] Which my current work involves putting a peak.schema-like interface over top of it, so that people don't have to write XML files to define their object schema. [13:56:53] Instead you just do stuff like... [13:56:57] class Person(schema.Item): [13:57:06] fullname = schema.One(String) [13:57:17] parents = schema.Many() [13:57:18] kind of like model [13:57:24] children = schema.Many(inverse=parents) [13:57:36] Yes, but much more compact. [13:57:45] No nested classes. [13:57:54] is it better? [13:57:56] Bidirectional relationships only linked on one side. [13:58:07] why did u choose classes? [13:58:09] Well, it's not better than peak.schema will be. :) [13:58:13] ehhehe [13:58:17] But it's better than peak.model, yes. :) [13:58:31] It also supports Sequence and Mapping cardinalities. [13:58:41] And Many is actually a set (unordered collection) [13:58:59] peak.model doesn't do sets or mappings, only singles and sequences. [13:59:37] is there any way to override certain methods of the sequences, for example? [13:59:46] No. [13:59:51] for example, peak.Model enables me to generate the html forms for managing my DB, the introspection is very nice [14:00:06] I should say, no in what I'm doing for Chandler. [14:00:09] Yes in peak.schema. [14:00:22] As you can see, I'm mostly thinking about the one for Chandler lately. :) [14:00:32] :) [14:00:43] In peak.schema, there will be generic functions used to do that kind of configuration. [14:00:56] So, it isn't necessary to use nested classes and embed methods and all that. [14:01:14] I also plan to drop the "method exporting" feature of peak.model; I just haven't seen it being all that useful. [14:01:24] what is that? [14:01:41] You know, where it generates methods like 'addParent' and 'addChild' for you? [14:01:42] there are lots of great things I don't know about peak :( [14:02:07] i haven't used/seen that [14:02:16] Try peak help model.MethodExporter [14:02:21] kk [14:02:44] Or perhaps don't, since I don't plan to keep that feature in peak.schema. :) [14:02:57] lol [14:03:02] The reason I created it was so that you could do special behavior in response to changes in the data [14:03:23] But, if you can hook that stuff with generic functions, there's no reason to have more than one way to do the same thing. [14:03:49] And in order to generate decent methods you had to specify singular and plural forms and a bunch of junk like that. [14:03:50] generic functions are so yummy [14:04:15] So, I'm moving in the direction of making things just seem like normal Python objects as much as possible. [14:04:29] i see [14:04:49] And minimizing the amount of stuff you have to specify to define the schema. [14:05:09] For example, you might notice that in my Person example above, the parents and children don't actually specify their type. [14:05:22] That's done automatically by the fact that they are linked and on the same type. [14:05:39] Whereas peak.model forces you to use strings to forward-specify types [14:05:55] yes, i've felt that [14:06:03] My new approach never has to use strings, because you only have to set the type on one side of a link. [14:06:18] ah [14:06:28] right, i underand [14:06:35] *understand [14:06:51] The downside is that you can only link two types that way; [14:07:03] peak.model lets you link with anything that has the right attribute name. [14:07:30] Actually, that's not entirely true. You can share the same attribute descriptor between multiple types, and give it a different name in each one, if you like. [14:07:53] (this is peak.schema I'm talking about here, though, which doesn't exist, or the Spike prototype for Chandler, which does exist but won't be used in Chandler...) [14:08:05] Confused yet? :) [14:08:12] I know I am. :) [14:08:13] lol [14:08:14] a bit [14:08:29] Which is why I mostly think about the one I'm doing for actual use in Chandler. [14:08:51] Spike is pretty and elegant and cool, but it doesn't mesh with the existing Chandler persistence system very well. [14:09:07] i see [14:09:08] But it demos some of the cooler features that will only be available in peak.schema. [14:09:43] (Because Chandler either can't support them with its persistence backend, or because Chandler doesn't need them and PEAK does.) [14:11:15] At the moment though, peak.schema is on the back burner until after Python Eggs. I really want that sucker done. [14:11:48] Chandler really needs Eggs too, in fact I designed them with Chandler very much in mind, but the features they support aren't really on Chandler's roadmap for a while yet. [14:11:56] So it's hard to get official hours to spend on them. [14:12:11] ehehe [14:12:20] python eggs seem very cool [14:12:57] Well, at least they're there and they work. It's the automatic dependency resolution part that's cool, but not yet done. [14:13:22] to generate the egg? [14:16:45] ** _pje has joined us [14:18:30] when I declare a DM i usually define some extra methods. Should I implement an Interface for that or not. I don't understand how to keep things general with the aid of configuration files [14:22:27] <_pje> Not to generate the egg; to let you find eggs at runtime [14:22:39] ah ok [14:22:39] <_pje> As for the interface, that's up to you. [14:22:59] <_pje> Interfaces are for documentation and adaptation. [14:23:13] <_pje> If you need one or the other, then by all means use an interface. [14:23:36] aren't they for enforcing an Interface? [14:23:49] <_pje> Enforcing? How and for whom? [14:24:15] <_pje> Zope interfaces have functions to check if a class defines all the stuff declared in an interface, but PyProtocols' interfaces don't. [14:24:23] that the DM defined in my configuration files abides for a certain interface [14:24:28] <_pje> Just because you have all the methods doesn't mean you implemented 'em right. :) [14:24:35] indeed [14:24:53] *abides _to_ a [14:25:33] <_pje> If you're looking 'em up in config files, aren't you using storage.DMFor? [14:25:42] <_pje> That uses a stock interface and a target class. [14:26:44] <_pje> See 'bulletins.ini' and 'model.py' in 'examples/bulletins/src/bulletins' for examples [14:26:49] for example [14:26:55] in the storage.py [14:27:40] you have getAll, which isn't part of the DM interface [14:28:00] however when u use a DM you expect it to have that method [14:28:08] <_pje> Yeah, but I didn't need documentation or adaptation. [14:28:24] but if you change ur storage backend it will be broken [14:28:27] <_pje> It's not like there's ever going to be some other object I'll adapt to be a DM with that ability. [14:28:40] <_pje> Yeah, it'd be broken even if I had an interface. :) [14:29:01] <_pje> If it's not for documentation or adaptation, it's really not going to help you any. [14:29:03] but doesn't the interface document a set of rules [14:29:13] <_pje> Key word: document [14:29:19] <_pje> If you want documentation, there you go. [14:29:25] lol [14:29:44] so in this case I _should_ use an interface [14:29:59] <_pje> Yeah, if you want to document it. [14:30:07] <_pje> That's what I've been saying. [14:30:20] i know :P [14:30:27] <_pje> e.g. security.ISecurityContext is an example of a pure documentation interface in PEAK. [14:30:44] <_pje> I never adapt to it or anything, it just explains what a security context has to do. [14:31:08] <_pje> When you're writing a framework, interfaces are important for documentation to explain what other people need to do. [14:31:22] <_pje> When you're writing an application, especially as an individual, you may not care. [14:31:32] I care :D [14:31:50] i care so that I can understand how to make things right [14:33:24] in here: http://cvs.eby-sarna.com/PEAK/examples/bulletins/src/bulletins/storage.py?rev=1.6&content-type=text/vnd.viewcvs-markup [14:33:47] why do u return a dict(Item(...)) instead of just a dict(..)? [14:34:30] <_pje> Because dict(**kw) wasn't available until Python 2.3 [14:34:39] ah [14:34:41] <_pje> And PEAK was mostly written for Python 2.2 [14:34:45] didn't know :D [14:34:56] <_pje> Items(**kw) returns kw.items() [14:34:57] so I can use plain dict() [14:35:01] <_pje> Yes. [14:35:07] <_pje> And the example could now, too. [14:35:16] <_pje> Because PEAK now requires 2.3 [14:35:22] :) [14:36:40] thanks alot for all your answers. bbs [14:37:09] ** pje has left IRC (Read error: 113 (No route to host)) [14:38:01] <_pje> bbs? [14:38:04] _pje is now known as pje [14:40:46] be back soon ;) [14:45:22] ** _pje has joined us [15:01:40] ** pje has left IRC (Read error: 113 (No route to host)) [15:19:10] ** pje has joined us [15:28:41] ** _pje has left IRC (Read error: 113 (No route to host)) [15:59:43] ** _pje has joined us [16:17:58] ** pje has left IRC (Read error: 110 (Connection timed out)) [16:33:06] ** pje has joined us [16:48:21] ** _pje has left IRC (Read error: 113 (No route to host)) [17:29:31] ** _pje has joined us [17:42:29] ** pje has left IRC (Read error: 110 (Connection timed out)) [17:46:23] ** _pje has left IRC ("Client exiting") [17:57:33] ** s1x has left us [20:38:24] ** debugger has left IRC ()