[03:11:01] ** gbay has joined us [04:02:24] [connected at Thu Oct 7 04:02:24 2004] [04:02:24] <> *** Looking up your hostname... [04:02:24] <> *** Checking ident [04:02:24] <> *** Found your hostname [04:02:58] <> *** No identd (auth) response [04:02:58] <> *** Your host is sendak.freenode.net[sendak.freenode.net/6667], running version dancer-ircd-1.0.35 [04:02:58] [I have joined #peak] [04:02:58] ** sendak.freenode.net set the topic to http://peak.telecommunity.com is back on line [04:35:17] ** gbay has left IRC ("It's not like I'm leaving or anything...") [04:45:15] ** apoirier has joined us [05:15:18] ** gbay has joined us [08:27:10] ** apoirier has left IRC ("Using KVIrc 3.0.1") [09:53:48] ** apoirier has joined us [09:55:51] ** __lm___ has joined us [11:52:54] <__lm___> anybody can answer a quick question on pyprotocols? [11:58:27] ** pje has joined us [11:58:30] * pje waves [11:58:35] Sure. What's the question? [12:05:44] <__lm___> hi pje, sorry was on the phone... [12:06:36] <__lm___> I have some problems trapping the protocols.adapters.AdaptationFailure exception [12:07:00] Why not just use a default return value? [12:07:15] ** asrenzo has joined us [12:07:37] <__lm___> my pyprotocols installation uses the speedups, and the only way I can catch AdaptationFailure is if I directly import it from protocols._speedups [12:07:54] <__lm___> what do you mean? [12:08:15] I mean, why trap AdaptationFailure when you can just use a default return value? [12:08:27] Instead of IFoo(ob), use IFoo(ob,default) [12:08:27] <__lm___> ohhh ok, right [12:08:33] Or adapt(ob,IFoo,default) [12:08:58] I never bother catching adaptation failure, even when I don't use a default value, though. [12:09:16] Because basically adpatation failure is a programmer error, so the program *should* crash so the programmer knows they've done something wrong. :) [12:09:26] <__lm___> but is this supposed to happen anyway, that protocols._speedups.AdaptationFailure is not protocols.adapters.AdaptationFailure? [12:09:48] <__lm___> right.... [12:10:15] <__lm___> I'm a real newbie with pyprotocols, but they're great [12:10:26] No, it isn't supposed to happen. In the source tree that I'm looking at right now (the 1.0a0 trunk), _speedups imports it from adapters. [12:10:57] There's also another way to prevent AdaptationFailure... define an adapter from type 'object' to your target interface. [12:11:00] <__lm___> ok, I will use a default return value anyway [12:11:26] This works if you have a default behavior you want to use for any object that doesn't have a more specific adapter. [12:11:47] <__lm___> not my situation, but I'll keep it in mynd [12:11:51] <__lm___> mind, sorry [12:13:20] I can't see why _speedups would have a different AdaptationFailure... What version exactly do you have? [12:13:39] <__lm___> a real newbie question: how do you test if an object implements an interface, eg in unit tests? by adapting it to the interface, or do you have something more specific like Zope? [12:14:02] I just adapt it. [12:14:30] I usually do (in unit tests) self.failUnless(IFoo(ob,None) is ob) [12:14:41] (if I want to prove the object implements it directly) [12:14:57] <__lm___> uhm, the latest stable, I nstalled it last week [12:15:15] But I try never do that in non-test code, because it usually means that something is wrong with the design. [12:15:17] <__lm___> ok, that's what I'm doing [12:15:49] Source or binary? [12:16:23] <__lm___> no, that's ok, I am migrating a small project from zope.interfaces to pyprotocols and I test for interface implementation in unit tests only [12:16:26] <__lm___> source [12:16:33] <__lm___> in fact they're the same: [12:16:58] <__lm___> >>> protocols._speedups.AdaptationFailure is protocols.adapters.AdaptationFailure [12:16:58] <__lm___> True [12:16:58] <__lm___> >>> [12:17:39] Ah. Whew. I was worried there was another problem with the source distro. [12:17:40] <__lm___> but when I imported AdaptationFailure from protocols._speedups my tests passed.... [12:17:58] <__lm___> pretty strange [12:18:14] Hi, I'm trying to use genPkg() function from peak.model.mof2py but I always get : [12:18:19] You should just use protocols.AdaptationFailure. [12:18:20] peak.exceptions.NameNotFound: [12:18:37] Pretty much all of the protocols API is in the top-level package. [12:18:55] Do you have any idea of what's happeneing ??? [12:19:01] asrenzo, what arguments are you calling it with? [12:19:18] <__lm___> thanks a lot pje [12:19:49] ** __lm___ has left IRC ("leaving") [12:20:57] hi pje. I'am trying to understand your mail about the peak.web package configuration [12:21:15] Okay. [12:21:27] pje, genPkg('UML 1.3','project.xmi','peak.metamodels.UML13.model.', './src', '') [12:21:52] asrenzo, are you using CVS PEAK or PEAK 0.5a3? [12:22:14] pje, PEAK 0.5a3 [12:22:39] asrenzo, /msg me the full traceback [12:23:45] Also, quick question... is 'project.xmi' a MOF model or a UML model? [12:23:54] Because if it's a UML model, that's totally not going to work. [12:24:23] ** asrenzo has left IRC (Excess Flood) [12:24:31] ** asrenzo has joined us [12:24:36] apoirier, what's your question? [12:24:43] asrenzo, msg it in parts. [12:25:12] basic question: and are the way to map a Web space (URL) onto a components graph, right ? [12:25:38] pje, send it once agai and complete [12:25:42] Pretty much, although you'll note I tossed out the 'site' tag by the end of the email [12:26:28] yes, seen [12:26:51] asrenzo, is the xmi file a MOF model? [12:27:15] pje, It's an umbrello generated file [12:27:41] apoirier, the idea is that the elements will become components in a traversal hierarchy, yes. [12:27:50] asrenzo, that's a UML modeller, not a MOF modeller. [12:28:16] mof2py generates Python from MOF models, not UML models. [12:28:30] but seen very too much static [12:28:52] how, for example, add a new section in my site ? [12:28:54] apoirier, the tag extends the location with dynamic lookup capability [12:29:13] Also note that it's for applications, not "sites" [12:29:33] ok, seen the [12:29:35] If you have an application with dyanmic sections, you might have: [12:29:39] [12:29:54] [12:30:02] pje, Oooops, sounds like I misunderstood what mof2py could do. Sorry. [12:30:02] Oops, left off a close quote on the first line. [12:30:41] asrenzo, you would have to write your own code generator for UML; search the mailing list archives and I think you'll see that somebody else was possibly working on one. [12:30:59] You might contact him or see if you can join forces. [12:31:46] PEAK should be able to *read* your UML file, just not generate anything from it. [12:32:07] You should be able to script whatever generation you want. [12:32:33] apoirier, so anyway, you extend static locations with to have dynamic lookups [12:32:53] ...and you use to describe how views will be added to the objects that are dynamically looked up. [12:34:42] ok [12:35:00] pje, I'll try to use UML2MOF or something similar. [12:35:25] And then the other four kinds of elements are basically to control security, define views, manage imports, and provide ways to link up locations. [12:35:33] Er, five kinds of elements. [12:35:48] (Chief amongst the kinds of elements... sorry, Monty Python joke.) [12:35:59] yes, a bit like Zope 3 [12:36:57] Right, the difference is that ZCML doesn't have static locations (last I looked, anyway), because they put that stuff in ZODB. [12:37:41] And I'm trying to keep our configuration language small. It'll probably grow more elements and special attributes before too long, but to start I'd like it to be a lot simpler than ZCML. [12:38:19] a good thing IMHO [12:38:54] asrenzo, let me know how it turns out. Keep in mind you need a MOF 1.3 model. If in doubt, look at the *.xml files in the peak.metamodels package to see what they should look like. [12:39:11] apoirier, the static layout, or the simplicity? [12:39:21] the simplicity [12:39:54] the static layout stay a interrogation for me : [12:39:58] Yeah, I really wish I had this back when Ty and I created ZPatterns [12:40:15] Of course, I also wish I had it now. :) [12:40:21] I still have to write it. :) [12:40:26] in nearly all the applications we did/do, there is a lot of dynamism [12:41:07] But even the dynamic items surely must be found under *some* static location? Even if it's the site root! [12:41:31] If your entire application was dynamic, you could just define your whole site as: [12:41:33] [12:41:44] [12:41:52] [12:41:54] [12:42:34] hehe, yes, that's just I'am thinking of. [12:42:40] Indeed, if your objects already define their own UI directly, you don't need the definitions either, and you could use what's in CVS today. [12:43:13] for exemple a CMS like site where all the sections and content are dynamics can nearly only have only a static root [12:43:15] Just implement IWebTraversable and define security directly on the objects. [12:43:59] Zope 3 will have an edge on peak.web for CMS-ish applications, because it has lots of features specific to that. [12:45:03] peak.web is targeted at developers who need to create more "data-driven" applications, which are usually organized as containers according to object types. [12:45:35] Like [12:45:54] [12:45:55] etc. [12:46:14] So that you go to /products/527 /customers/Jones, etc. to do things with them. [12:46:31] In fact Zope2 and 3 directly publish an URL, following the components relationship [12:46:37] But, you probably also have some pages within the locations, so you can go to /products/add.html or /products/search.html, etc. [12:46:50] couldn't be possible in peak, following the bindings ? [12:47:09] apoirier, yes, and by default that's what will happen, as long as you have declared the security. [12:47:53] However, I've discovered over time that the best component layout for an application is not necessarily the same as its ideal URL layout. [12:48:05] completly agree [12:48:09] And, sometimes you want to reuse the same components as part of a web application with a different layout. [12:48:19] completly agree too :) [12:48:22] Or, give it a different UI. [12:48:38] So, the elements let you define the UI for a domain model class, specific to *that* web application. [12:48:55] You can make multiple XML files, each "skinning" the UI differently. [12:49:17] Technically, they're not skins, but actually different apps. [12:49:28] here we dissociate contents objects from layout objects. Layout objects using proxies on the contents ones [12:49:42] (Skins in peak.web are just the physical templates and icons and other static files.) [12:49:51] Pretty much... [12:50:06] Only elements aren't proxies, and neither are elements. [12:50:33] peak.web has Context objects that track the traversal, and do lookups of views like elements. [12:50:40] So, they are the thing that's proxy-like. [12:50:59] Except of course that they don't really proxy as such, they just wrap the objects being traversed. [12:51:18] ok [12:51:52] Look at the web.ITraversalContext interface; it has all the attributes and methods you can do, like traverse to a subobject, get a view on the object, etc. [12:52:07] require a permission on the current object... [12:52:50] ok [12:52:54] other question: [12:53:10] are the views only adapters ? [12:53:37] No. They use adaptation for their registry, but they aren't really adapters. [12:54:30] What's actually being adapted to is an INamespaceHandler: a function that returns a new traversal context. [12:54:49] the function receives the old context, the view name, and some other data [12:55:03] And then it can return a new context pointing to an arbitrary object. [12:55:45] So for example will register a function that calls the input context's 'getResource()' method to get an object to put in the return context. [12:56:26] And so on for each of the three ways you can define a page view. [12:56:43] For example, let's say I want to define a date format... I could do: [12:56:55] [12:57:59] [12:58:03] [12:58:37] Then, in a page template, I can do something like date goes here [12:59:07] I guess technically that isn't a page. :) [12:59:32] Maybe I should call it 'view' so it reads well in both uses. [13:00:57] yeah, to me it's not a 'page', but it's a 'view' [13:01:14] A lot of the time, they will be pages, e.g. [13:01:47] hmm, I hope no [13:01:57] [13:02:09] it's a big problem I have with the actual 'page' in Zope 3 [13:02:27] So, wherever you go to /someworkorder/editform.html you get the edit template. [13:02:34] to me component must have views, not pages [13:03:01] Because you see a page as something static? [13:03:24] no, I mean, for HTML, each view of components must be HTML fragments, and not a complete page with ... [13:04:11] Ah, yes. But I suppose you saw my notes on that for the new PWT, yes? You'll be able to make such fragments and use them either as a fragment within another template, [13:04:21] or else use them as a standalone page, wrapped with a layout. [13:04:51] In any case I'm leaning towards making it instead of just because there are plenty of views that aren't pages. [13:05:16] no, I didn't see the PWT. What is it ? URL ? [13:05:59] http://www.eby-sarna.com/pipermail/peak/2004-August/001713.html [13:06:15] That's the design rant for the new PWT. [13:06:50] Think "extensible ZPT that can use slabs of XML as parameters passed to other templates" [13:07:05] Sort of like METAL, but more dynamic. [13:07:25] Such that even basic operations like lists are implemented in terms of parameter elements. [13:07:36] great. I didn't see it [13:08:16] For example: [13:08:17]
    [13:08:18]
  • Text will go here
  • [13:08:18]
[13:08:22] renders to: [13:08:28]
    [13:08:29]
  • foo
  • [13:08:29]
  • bar
  • [13:08:29]
[13:09:06] Where content:list is a component written in Python that accepts a 'listItem' parameter. [13:09:21] So, it's like METAL, but macros can be written in Python to have dynamic behavior. [13:09:53] And all of the language's dynamic behavior comes from such components; there is no "built in" behavior. [13:10:21] Just the ability to invoke components, and to pass them blocks of XML/XHTML as (functional) parameters. [13:11:17] Like the site config,however, it doesn't actually exist yet. We have an existing PWT language that does the same basic idea, but its syntax is uglier. [13:12:04] it would use e.g.
    instead of
      [13:12:29] and
    • , etc. [13:13:04] It also lacks the ability to distinguish between 'this' (the entire element) and 'content' (the contents of the element), except by hardcoding it in the Python DOMlet that provides the dynamic behavior. [13:13:30] Those are really the only significant differences at this point between "old PWT" and "new PWT". [13:14:59] ok, I will read about it [13:15:48] other question: [13:16:29] how to do if I have 2 edit views, for example, one in HTML and one in WML/cHTML/XML ? [13:16:53] is it possible to select a view based on the User Agent for example ? [13:17:15] Sure. Remember, everything maps to a INamespaceHandler function that's passed a traversal context. [13:17:32] That context includes a request 'environ' mapping with e.g. HTTP_USER_AGENT et al. [13:17:43] ok so I need to code a new traversal ? [13:18:02] In the site config language, you'd have to say something like [13:18:26] And then 'myfunc' just has to return a new traversal context. [13:19:09] Although, it might be better to add a different attribute, such that you use [13:19:28] And then myfunc would just have to implement the INamespaceHandler signature. [13:20:09] i.e., myfunc(ctx, ob, ns, name, qname, default=NOT_GIVEN). It's a rather scary signature, but you rarely need all the parameters. [13:20:41] Most of the time you'll only use ctx (traversal context), ob (the current object), and qname (the URL path segment being traversed). [13:21:22] ns and name will usually be 'view' and the unprefixed part of qname. (You'll see I stole @@viewname and ++view++viewname from Zope 3). [13:22:25] Anyway... there are also several other ways to address your use case, such as creating a DOMlet that switches between templates... [13:22:59] Adding your own element (or some such) to the configuration language (hopefully that won't be too difficult) [13:23:10] hmm, so is it possible to do something as adding a presentation service and register it like for _all_ components ? [13:23:25] (it's what we did in out framework on Zope 2) [13:23:29] Heh. [13:23:32] out=our [13:24:04] [13:24:31] fine :) [13:24:31] Whoops, that won't work. [13:24:36] :( [13:24:46] You have to register it for every *name* you want to look up. [13:25:01] not so fun [13:25:16] It would be better to define an adapter to IWebTraversable from whatever your base classes are. [13:25:53] In other words, override the default adapter to IWebTraversable; then you can have it do whatever you want, as long as you're not trying to bypass the ++whatever++ namespace mechanism. [13:26:24] (To bypass that also, you'd need to register a '*' namespace handler, that then reroutes things the way you want 'em.) [13:26:35] Of course, at that point you've pretty much bypassed all of peak.web... ;) [13:26:40] ok, I understand [13:28:05] yeah but it's the problem with Zope 3 I have (and perhaps with peak.web also ;) [13:28:27] I think a presentation service is a mandatory mecanism [13:28:42] for example to do pages caching [13:29:31] Well, I don't pretend to know what you mean by "presentation service", but it seems better to me to decouple responsibilities from one another. [13:30:29] For example, the way *I* would probably tackle your WML/cHTML/XML view issue might be to use peak.web's skins facility, and just make different versions of the same resources. [13:30:32] ** [asrenzo] has joined us [13:31:08] Or, maybe I'd just create different config files to lay them out as different applications, but with a top-level location whose automatically ensured that they went to the right sub-site... [13:31:29] I doubt I'd try to create some whole new service. But I could be wrong. [13:31:50] As for caching, I think I'd be more likely to implement that as a functional service invoked by the templates... [13:32:12] Some sort of 'this:cache="stuffthatvaries"' or something. [13:32:19] basically, the presentation service is the dispatcher that selects the views of the components and aggregate them [13:32:30] Or, as an annotation on the view definitions, like: [13:32:46] [13:33:15] * pje shrugs. [13:34:11] I try to avoid such "active" or "managerial" components operating on "passive" objects, because they're harder to get correct and maintain than orthogonal services controlled by "active objects" [13:34:14] yes but specifically, for a cache mecanisme you need to keep a association between the HTML page and all the views on the components that made it [13:34:31] ** asrenzo has left IRC (Remote closed the connection) [13:34:46] to be able to invalidate it when on the components changes [13:35:30] So use peak.events to have subscribable events on the components that reflect changes. [13:35:52] And when a view invokes the caching service, it says, "here's the components I depend on", so it can subscribe to the events. [13:37:10] In my view, that's easier to deal with because the responsibility is separated into smaller pieces. [13:37:12] exactly. But to me it's not the role of a view to directly invoke a caching service. That why we have a presentation service here [13:37:35] But only the view knows what it depends on. [13:37:50] Therefore, that seems to me the *only* place you can put it. :) [13:38:21] hehe, true. 1 point to you [13:38:59] here we invalidate all the views of a component when it changes [13:38:59] Also, from an architectural standpoint, I'm probably not going to cache everything, just things that are slow and commonly used, so I want to be able to work on it in a localized fashion. [13:39:40] However, I probably don't really want it in the template, from a use point of view. Where I probably really want the control is to be in the site config, near or on the view definition. [13:39:42] hehe yes. But ... python is slow :) [13:40:09] Not on today's machines it isn't. :) [13:40:43] but not with millions/hits per day :o) [13:41:21] But it's cheap to add more boxes, if your bottleneck is rendering. [13:41:49] And you can always write a page template-to-C translator. ;) [13:42:14] perhaps with peak but not with the ZODB in ZEO configuration [13:42:31] And are you sure that all that tracking of dependencies and invalidating objects doesn't take just as much time as the rendering? [13:42:46] (ok pt2c this week-end ;) [13:43:17] no, not at all. It's several order of magnitude [13:43:40] So you're heavier on reads than writes. [13:43:45] for example a portal homepage here can invoke > 50 component's views [13:44:08] Heck, you must be if you're using ZODB; ZODB dies a horrible death for sites where writes are in the same order of magnitude as reads. [13:44:08] and the pages are cached by Apache [13:44:40] Ah a portal. [13:44:55] paris.wanadoo.fr for example [13:45:06] (all the biggest French cities) [13:45:10] So these 50 views are all portlets or pagelets or some such. [13:45:45] I don't like portlets or pagelets terms. They are only components views [13:46:07] (but our presentation service knows how to add decorations on them) [13:46:16] * pje laughs [13:46:37] Why not just have them be pagelets and know how to add their own decorations? ;) [13:47:08] perhaps because we are not doing some plone sites ;) [13:47:51] Sorry, I just have architectural trouble with the "God object" approach. [13:48:14] I shudder at the thought of trying to write and maintain such an omniscient and omnipotent object. :) [13:48:17] yes, me too [13:48:34] but I didn't find a better way [13:48:54] except to put lots of mandatory calls into the views [13:49:01] which is worst to me [13:49:33] What kind of calls do you mean? [13:50:12] calls to the cache manager, calls to the change listener, calls to the decoration views ... [13:50:35] But doesn't your God object make those calls now? [13:50:47] right [13:51:15] So what is it you object to? [13:51:20] but all these tasks are located in one point [13:51:36] Wouldn't they be in one point if you put them in a base class for your views? [13:52:03] And then used e.g. attributes to list the metadata to activate them in subclasses or instances? [13:52:05] and, also, take into consideration that the presentation service is implemented by developpers and the views by designers. 2 differente population [13:52:41] right, first version of the presentation service was in fact a view base classe [13:53:08] but we then needed differentes behaviours of the presentation service, for different projects [13:53:27] do we ended with a presentation services made of registred plugins [13:53:30] do=so [13:54:28] Architecturally, it sounds almost like a job for a generic function. [13:54:59] = "multidispatcher method" ? [13:55:00] Although plugins can do almost the same thing. [13:55:18] Yes, but I was specifically thinking of *predicate* dispatch, with method combining. [13:55:37] predicate dispatch allows you to test arbitrary conditions as part of the dispatch, like "is this in cache?" [13:55:53] yes, I read you mail (paper ;) about it. And it make me think a lot [13:55:58] There's a prototype implementation in the PyProtocols trunk, but it's not quite finished yet. [13:57:15] But anyway. If you've distributed the logic into plugins that is at least an improvement over a monolithic God object. [13:58:07] Hm. Do these views each depend on only one component, or do they depend on multiple components? [14:11:37] ** [nicknam] has joined us [14:12:15] <[nicknam]> pje ? [14:12:25] [nicknam] is now known as apoirier2 [14:12:25] Yes? [14:12:33] sorry IRC problem [14:13:03] I see into the IRC log : [14:13:06] [13:58:07] Hm. Do these views each depend on only one component, or do they depend on multiple components? [14:13:23] Yes. [14:13:34] we mandate that views depend on only one component directly [14:14:00] but a view can call other components views, thru the presentation service [14:14:16] Ah. [14:14:31] so, for example, we have specialised layout components [14:15:45] ** apoirier has left IRC (Read error: 110 (Connection timed out)) [14:15:48] ** [asrenzo] has left IRC (Read error: 110 (Connection timed out)) [14:17:22] in fact, more I read and more I see our presentation service as a '@@' namespace "on steroids" [14:17:31] So, I'm thinking that I would probably just define the view lookup mechanism to handle that, if I were trying to do something like that in peak.web [14:17:44] :) [14:17:46] IOW, I'd register an alternative 'view' namespace (which @@ maps to). [14:18:15] And I'd track the components accessed in the traversal context 'environ' (which is global to that web hit). [14:18:37] So that when the hit was finished, I'd have a list to attach to that rendering in the cache. [14:18:56] In order to be able to validate it when it gets looked up on another hit. [14:19:22] yeah, agree [14:19:29] At least, if I was caching at the page level anyhow. [14:19:57] And it wouldn't require any callbacks, although I might include a TTL mechansim just to keep stuff from cluttering up the cache that was never going to be used again. [14:20:43] couldn't you just put expire headers on the pages and use something like squid? [14:21:07] Hi Bob. We're talking about intra-page caching, like for portals. [14:21:11] ah [14:21:36] yes. In fact, here the caching is made by a specialized Apache module : apache caches the HTML page and the module keeps the association page -> [views] [14:22:01] zope send this association and the invalidation to the Apache module thru HTTP headers [14:22:23] Also, apoirier wants to invalidate the cache when objects change, not just TTL. [14:22:44] IOW, I assume one of the design requirements is that a user never see information that is no longer valid. [14:22:56] right [14:23:13] in fact we have cache policy (made with plugin) [14:23:56] we can declare some page not cacheage, cacheble with TTL or completly driven by the invalidations [14:24:34] TTL policy is to brutal for highly dynamic sites [14:24:52] It does seem to me, though, as though I could do this in peak.web by changing the PWT "Document" class to interact with a cache manager. [14:25:20] I.e., to say, "I'm view template such-and-such, here's my target object, do you have a cache result for me?" [14:25:47] And then if not, to say to the cache manager, "okay, I'm starting my rendering, so track all your cache requests from here" [14:26:00] And finally, "Okay, I'm done rendering, so now you know all the views I depend on." [14:27:11] Yeah... and then all I'd need to do is define that .pwt files use my cached subclass. [14:27:50] Although, other caching rules like noncacheable, TTL, etc. are best defined in the site config rather than as part of the template system. [14:28:28] Hm. I'm almost tempted to actually add that to peak.web, even though I don't currently need it. [14:29:09] exactly. Here each presentation service plugins has StartPageRendering / StartViewRendering / EndViewRendering / EndPageRendering hooks [14:29:45] and the cache policy are not into the views but in a config [14:30:15] The cache manager could live on the interaction policy object in peak.web's case. [14:30:43] what is the "interaction policy object" ? [14:31:15] It's the thing that allows access to the various web-related services. [14:31:35] For example, it determines what happens when an uncaught error occurs, allows skin lookups, etc. [14:31:50] It's just a consolidator of other (orthogonal) services. [14:32:17] (services that are global to a given web application) [14:32:34] So, it's the natural place for a cache manager to be accessed from. [14:32:46] A "Service services" ? [14:33:04] Yeah. It's an attribute of the traversal context. [14:33:18] And it controls the top-level invocation, transaction scope, etc. [14:33:36] You configure what services it actually provides via an .ini, or you can specify a custom policy class. [14:34:31] I think I'd actually invert the control of a cache manager, such that you call something like "renderMe(self,target,self.renderingMethod)" [14:34:41] (we have something like that : we call it '-services-'. It's a container that manage the other services. Found by acquisition. Forward services search to an ascendant '-services-' if service not found) [14:35:07] Then the cache calls renderingMethod if it doesn't have anything cached. That way, there's no extra calls for the "start/stop" events. [14:35:09] BTW: the render hooks are very usefull, not only for the cache [14:35:40] for example to insert comment as '' into the HTML, for debug [14:36:15] Right, but you can also do that with the inverted control approach. [14:36:43] hmm, interesting ... [14:37:07] InteractionPolicy isn't a generic services service; you can always use normal PEAK service lookups against it, though. [14:37:55] It *consolidates* commonly used services. For example, IAuthenticationService has a 'getUser' method. Policy has a 'getUser' method that is delegated to the configured authentication service. [14:38:29] So, IInteractionPolicy actually inherits from a bunch of other web-related services. The idea is to minimze the amount of "look up this to do that" code that would otherwise have to be written. [14:38:57] kind of facade pattern ? [14:38:58] er, that should be, "inherits from a bunch of other web-related service *interfaces*" [14:39:15] Yes. [14:39:40] Except it's just consolidation, not really "unifying" those services; just straight delegation. [14:40:04] ok, more like a hub [14:40:30] Normally in PEAK, one uses bindings to automatically attach services to yourself as your own attributes. [14:41:04] But, in a web application, you are dynamically creating lots of components as you go. [14:41:27] So, you don't get to take advantage of caching these dynamic lookups, unless you have an object to hold the shortcuts. [14:42:04] The purpose of the policy object is to hold all these configured services across all web hits, not just the current one. [14:42:30] yes. Someone talked to you on the mailing list about how the bindings are dynamics [14:43:01] you answered they are pretty statics [14:43:14] I find that restricted too [14:43:22] Right, that's the point of them, to "build" things. [14:43:40] because you have then to ressort to service search, acquisition ... [14:43:41] There is significant static architecture to any comprehensible application. ;) [14:44:37] We have to distinguish between "dynamic" as in "determined at runtime" and "changes at runtime". [14:44:46] PEAK does the first with bindings, the latter with events. [14:44:56] (or model objects) [14:46:41] BTW : did you look at some of the new java framework as picocontainers, spring ... based on IoC and adaptation ? [14:47:09] I'm familiar with them, but PEAK was actually developed first. [14:47:15] :)) [14:47:22] And is considerably more flexible, I might add. :) [14:48:39] one is using contructor injecter and the components to inject are registred into the container. I find this interesting [14:49:14] The PEAK approach is to use binding.Obtain on attributes, which then become constructor arguments. [14:49:44] ??? [14:49:47] Since Python doesn't have typed arguments, you pretty much have to do it that way. [14:50:12] apoirier2, suppose I have an object that wants to use, say, a 'cache'. I might do: [14:50:18] class Thing(binding.Component): [14:50:28] cache = binding.Obtain(ICache) [14:50:51] Now, I can say Thing(cache=someCache), or just Thing(someOtherThing) [14:51:12] In the former case, cache is explicitly supplied, in the latter, it will be looked up using the service context 'someOtherThing'. [14:51:28] In turn, the new Thing is suitable for use as a service context by other components. [14:51:40] Thus, PEAK doesn't need an explicit "container" object: all components are containers. [14:51:54] Ah, ok. I understand [14:52:29] Of course, a given component may not offer any real services for lookup. The "root component" is usually loaded with an .ini file to configure services. [14:52:32] For example: [14:52:35] [Component Factories] [14:52:47] somepackage.ICache = otherpackage.CacheImplementation [14:53:33] This says, "if somebody wants an ICache, instantiate this class in the nearest ServiceArea if one isn't already there". [14:53:49] ServiceArea is more or less like the idea of a Container in those Java frameworks. [14:54:06] It's a place for holding things that are Singleton-ish. [14:55:10] ok [14:55:26] Of course, component factories can also create non-singletons... [14:55:51] If my Thing class had said 'cache = binding.Make(ICache)', then each Thing instance will get its own CacheImplementation instance at runtime. [14:56:05] instead of sharing one with any other Thing in that ServiceArea. [14:56:46] How do you to that. It's exactly the problem a collegue has now with peak ? [14:57:04] How do you to that? [14:57:11] I don't understand. [14:58:47] By binding.Obtain(), each instance always receive the same object [14:59:18] *within a common component subtree*, yes. [14:59:55] IOW, "each instance that shares the ancestor component that provides that service, and doesn't have a closer provider" [15:00:31] It's like acquisition, in other words, but it's not name-based; it uses explicitly declared "configuration keys" to do lookups. [15:00:49] Interfaces are keys, property names are keys, classes are keys, and you can create your own keys by implementing config.IConfigurationKey. [15:01:31] Components have a 'registerProvider' method that associates a key with a function for returning a result. [15:02:19] So the looked-up values can change at runtime, but if you use a binding, the lookup is cached. You just can't mix caching and dynamism, because bindings don't offer an "invalidation" facility. [15:03:46] Is this feature into the TODO list or do you think it's not important ? [15:04:22] I had it on TODO at one time, but I really don't think it's that important. [15:04:53] ok [15:04:55] I think that most of the use cases for it, are better served by just re-instantiating an entire component subtree. [15:05:31] but then you lose all the states [15:05:32] IOW, the "if one leaf dies, buy a new tree" strategy. [15:05:48] States? Components aren't supposed to be stateful, unless they die at the end of their states. [15:06:00] Components in PEAK-speak are part of the solution domain, not the problem domain. [15:06:17] If they're stateful, they're probably model.Elements, not binding.Components. [15:07:04] binding.Components are supposed to provide services. Typically, components are only stateful while you're building them, or building something. [15:07:57] I've been using the term "component" pretty broadly in our web-app discussion, but wrt "Component" with a capital C, in PEAK they're your application, not the things your application works *on*. [15:09:13] oops, I think I need to well integrate this distinction [15:09:35] It makes a lot of difference to implementation, yes. [15:10:46] Anyway, peak.model has a crude mechanism for implementing observation of problem domain objects, and later on it'll be better integrated with peak.events. [15:11:00] But none of that is nearly as well-developed or stable as the Component side of things. [15:11:40] Anyway, there are plenty enough extension points available for an interested person to add invalidation. [15:12:21] It's just impractical to use it as the general case for bindings, because it would use lots of memory and be slow for the 90% of components whose bindings would never change at runtime. [15:15:41] so the model.Elements objects manage the states ? [15:16:30] Yep. Like a Customer class would subclass model.Element. [15:16:52] However, physical storage of that state is handled by a DM (DataManager) in the current peak.storage system. [15:17:06] However, you can still use model objects without storing them. [15:17:47] Model objects just control domain-model behaviors and invariant maintenance. [15:18:07] but, for example, the views are not direcly applicables on a Customer object ? [15:18:12] Separating storage means you can have different physical back-ends, like save-to-XML or store in a database. [15:18:23] No, the customer object doesn't know anything about views. [15:18:47] It just knows about its WorkOrders or Invoices or whatever. [15:19:52] You'd define the views in /content> blocks. [15:20:12] And they'd apply only to the application that used them. [15:20:37] Further, if they're resource views, then they're "skinnable" (e.g. for translation/localization, different browsers, etc.) [15:20:59] But the Customer object knows not a darned thing about any of that, or about how it's stored in a database or XML file either. [15:21:25] Which means if there's ever a peak.gui to go with peak.web, and it defines GUI views, then those will also be independent. [15:21:40] * pje likes keeping things orthogonal [15:24:20] How do you represent the bindings between Customer, WorkOrders, Invoices ? [15:24:32] those are model.Features. [15:24:56] Customer might have a 'work_orders' feature, linked to the 'customer' feature of WorkOrder: [15:25:02] class Customer(model.Element): [15:25:09] class work_orders(model.Collection): [15:25:16] referencedType = WorkOrder [15:25:40] referencedEnd='customer' [15:25:57] Oops, one too many spaces on that last line. [15:26:15] Collection is a subclass of Feature, used for multi-item attributes. [15:26:44] Anyway, the above code creates a Customer class with an 'add_work_orders()' method, remove_work_orders(), etc., as well as a 'work_orders' attribute. [15:27:12] and a DM can automatically translate this relation in SQL/tables ? [15:27:28] For better naming, I could add 'singularName = "work_order"', so that the methods would be called e.g. 'add_work_order', which makes more sense. [15:27:37] Some people have written DM's that do that, yes. [15:28:08] I haven't put one in PEAK because I want PEAK to support mapping from arbitrary (e.g. legacy) schemas, rather than just being suitable for greenfield applications. [15:29:38] But there is some XML-based dynamism in PEAK; it can generate model.Element classes from a MOF model, and then those element classes can be used to load other XML files. [15:30:02] There isn't any writing to XML built-in though; it's mainly just used to be able to read MOF and UML models. [15:30:28] I always a little bit reluctant to such layered architectures : I have seen to much projects where the data-tier are only objects directly modeled on SQL tables and where even a drop-list in the GUI is called a components into the presentation-tier [15:31:21] Well, I'd consider a drop-list a view, myself. :) [15:31:28] aahhhhhhhhhhhhhhhh [15:31:32] :) [15:31:49] Wouldn't you? [15:32:41] not to me (but lots of discussions here with collegues). Only GUI elements [15:32:42] ISTM the layers there are storage, model, and view -- not an excessive number of layers IMO. [15:33:10] Yes, but it views something - a list of items. [15:33:49] And the dialog in which the drop-list appears is itself a view... it seems to me exactly like your portal situation. [15:34:38] to me a view renders a component [15:34:51] And a list of things isn't a component? [15:35:41] for example, for us a dialog is a view of an assistant component that embed 1 or mode views (edit views) of other components [15:36:00] no, a list of things is an attribut/property of a component [15:36:14] True. [15:36:39] But surely a view can contain attributes and properties of a component. [15:36:44] only a list of components can have views, often rendered here by a view of a layout component [15:36:49] Otherwise, what would it be viewing? :) [15:37:24] * pje still isn't getting why a GUI component isn't a view. [15:37:40] yes, a view contains GUI elements (list a HTML drop-list) that display the component attributs [15:37:41] What if you were generating XUL or XAML from your app? Wouldn't the resulting GUI be a view? [15:38:37] Hm, I think we're having a split between "View" (specific thing in your app/framework) vs. "view" generic term [15:38:46] Sort of like "Component" vs "component". :) [15:38:47] right [15:38:57] to us the views aren't components [15:39:19] So, to me, anything that's a modular rendering of some aspect of the domain model is a "view" [15:39:36] ok, here is the split ;) [15:39:50] But to you, Views render Components, where arbitrary objects are not Components. [15:40:09] right [15:40:15] For me, any old object (like a list) is suitable to be the subject of a "view" (lowercase). [15:40:29] for us components are on "high level" than objects [15:41:14] And that makes sense because you have an integrated framework; PEAK is trying to stay orthogonal, so that you don't *have* to use peak.model in order to use peak.web (for example) [15:41:37] technically speaking, each time we declare components with a XML descriptor and our components generator inject 3 objets by components into Zope [15:41:50] Since anything can be viewed, peak.web has more uses. For example, I plan to make a Python documentation tool using peak.web, since it can create views on any Python object. [15:41:59] 1 object for the view, logic and data component parts [15:42:38] In Zope 2, I would agree that you pretty much have to integrate them... which is why I quit using Zope 2 a long time ago. ;) [15:45:53] ok, I must to go now [15:46:02] Very interesting chat [15:46:03] * pje waves [15:46:10] Thanks, you too. [15:46:14] hope to see you again soon [15:46:21] bye [15:46:25] * pje got a few ideas for adding to peak.web [15:46:34] :) [15:46:41] ** apoirier2 has left IRC ("Using KVIrc 3.0.1") [19:24:47] ** gbay has left IRC ("It's not like I'm leaving or anything...") [19:25:29] ** pje has left IRC (Read error: 232 (Connection reset by peer))