[Zope-dev] Re: [Zope3-dev] Re: How To run current Zope 2 3 from CVS on Windows
At 06:12 PM 5/12/04 +0800, Choo Zhi Min wrote: What does import os; print os.name return in Cygwin, nt or posix? Python 2.3.2 (#1, Oct 9 2003, 12:03:29) [GCC 3.3.1 (cygming special)] on cygwin Type help, copyright, credits or license for more information. import os os.name 'posix' ___ Zope-Dev maillist - [EMAIL PROTECTED] http://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope )
[Zope-dev] Re: [Zope3-dev] ZConfig: Section type datatype inheritance
At 12:04 PM 12/29/03 -0500, Barry Warsaw wrote: This is how I'm using extended section types in my code currently. The proposed change won't affect me because I explicitly specify the data types in derived section types. It seems to me unlikely that you'd have a base section type with a non-default data type, with derived section types that rely on the default data type. Yes, it would only be useful if you could also override existing attribute or key definitions in the derived section type. Adding new attributes, but leaving the section's datatype alone wouldn't make much sense. +0 Agreed, unless there's also a way to override/replace existing attributes, as opposed to merely adding new ones. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope )
[Zope-dev] Re: [Zope3-dev] ZConfig: Keytype and section type extension
At 01:53 PM 12/29/03 -0500, Fred L. Drake, Jr. wrote: Phillip J. Eby writes: That reminds me... is there any way for section *names* to be case-sensitive, or at least case-preserving? For example, if one were simulating Apache-style configuration like: There isn't, but there was at some point. Nobody here at ZC seemed to think it useful at the time, so it was removed as a simplification. What we had was a nametype attribute for sectiontype elements; it was just another datatype function. I'd be happy to have that back if there's a real use for it. The current situation, where the conversion is coded directly in ZConfig.cfgparser, isn't very flexible. Agreed. :) Would it suit your requirements if the name type were associated with the section type, and inherited from the base type if not specified? Yep. Currently, IIRC, the '_name' attribute of the resulting section will be '/foo/bar/baz'. The _name attribute is an implementation detail; use the getSectionName() method instead. I'm likely to change the _name detail just to be facetious. ;-) Well, in that case, can we have a 'getItems()' that returns only the key-value pairs for actual attributes, and does *not* include keys for values that weren't explicitly specified in the configuration file and don't have defaults? In PEAK, the binding.Component class has this constructor currently: def fromZConfig(klass, section): Classmethod: Create an instance from a ZConfig 'section' # ZConfig uses unicode for keys and defaults unsupplied values to None data = dict([(str(k),v) for k,v in section.__dict__.items() if v is not None]) if not hasattr(klass,'_name') and '_name' in data: del data['_name'] if not hasattr(klass,'_matcher') and '_matcher' in data: del data['_matcher'] return klass(**data) As you can see, I'm doing a fair amount of work in order to extract a mapping I can use as keyword arguments for the regular constructor. The standard way in PEAK to make a component configurable by ZConfig is simply to specify whatevertype.fromZConfig as the datatype in the ZConfig schema. If there were a 'getMapping' method available, the above would become something like: def fromZConfig(klass, section): Classmethod: Create an instance from a ZConfig 'section' data = dict([(str(k),v) for k,v in section.getItems()] data['_name'] = section.getSectionName() return klass(**data) Unless of course the keys were strings rather than Unicode, in which case it'd be even simpler. (The issue here is that Python requires keyword arguments to be strings rather than Unicode, even though attribute names can be Unicode. ZConfig sets attributes using unicode because ZConfig schemas are XML, and therefore Unicode.) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] PHP vs Zope cost benefit
At 04:55 PM 4/24/02 -0300, Leonardo Rochael Almeida wrote: As for multiple DB rollback, yes, that works as advertised, and is actually really easy to believe if you explain them how it works. Truth is, Two-Phase-Commit was INVENTED (a long time ago, and not in Zope) to make it possible to commit or rollback multiple transactional entities at the same time. Zope is just an implementation of a TPC coordinator (I think, and I hope I got the vocabulary right). Note that this only guaranteed to work if all the database adapters involved in the transaction support two-phase-commit. Many do not, and thus may commit too early or too late in the course of a multi-database transaction. If you need multi-database commit, you'll need to verify that the adapter in question actually implements tpc_vote() as something other than 'pass'. :) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Future of ZPatterns
At 08:22 PM 4/15/02 -0500, Steve Spicklemire wrote: Hi Marcello, Wow.. sounds like a neat book. ;-) Seriously, Phil Eby has suggested that there will be some sort of migration helpers to move from ZPatterns to There probably will not be any migration tools written by me or Ty; we are likely to port our own ZPatterns apps by hand, as the benefits of rewriting specifically for TransWarp far exceed any potential labor savings from an automated port, at least for our projects. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Re: [Zope3-dev] Are there Graphic Designers?
Folks, can we please stop the zope-dev/zope3-dev crossposts and direct this thread to zope3-dev only? You're doubling the volume of posts I have to read. :) Thanks. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Defining Interfaces
At 03:17 PM 1/28/02 +, Chris Withers wrote: Jeffrey P Shell wrote: On 1/27/02 11:25 AM, Steve Alexander [EMAIL PROTECTED] wrote: Hi folks, When I define an Interface, are the methods of the interface supposed to have self as the first argument? No. Can you expand on this a little? It doesn't make sense to me to exclude 'self'... Because when you *call* the methods, you don't pass 'self', it's implied. Since an interface is supposed to document the call signature, it actually doesn't make sense for it to include 'self', since it's not part of the call signature. Make sense? ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] im_self of methods accessed via non trivial acquisition
At 01:12 PM 1/18/02 +0100, Stefan Bund wrote: Phillip J. Eby [EMAIL PROTECTED] writes: Method rebinding is done only when an item is retrieved from the aq_self side, and only if im_self points to aq_self. If these conditions are met, a new binding is created which points to the acquisition wrapper. This is a feature, not a bug. If you rebind im_self on the aq_parent side, and your method assigns a value to an attribute of self, it will be assigned to the wrong object! It is safe in your example to bind m.im_self to B, because B.aq_base is f, the true self of m. But it is not safe to bind m.im_self to A, because A.aq_base is g -- another object altogether. I guess another way to look at it is that a method retrieved from an acquisition-wrapped object will always meet the condition that method.im_self.aq_base is the original object the method was retrieved from. This ensures that the method simply works with an acquisition-wrapped version of its original self. Of course, im_self cannot be A, that would be wrong, but as far as I understand, it could be a *new* acquisition wrapper, something like /B o A/ or even /[f] o A/: C--A--O--[a] | | | | | [b] | | | O--B--O--[c] | | | | | | | [d] | | | | | O--[e] | | | | | [f] | | | [g] | B--O--[c] | | | [d] | O--[e] | [f] (that's what I refer to in the definition of /C/). So if /C/ is one of the aforementioned new wrappers, /C.aq_base/ is indeed [f] and therefore, /C/ would be safe as im_self? Hmm. Is there another reasun, why method rebinding works the way it does (returning a subtree and not a new acquisitionwrapper like described above) or am I completely amiss? Beats me. I guess nobody's asked for the feature, and in any event it requires global knowledge of the tree structure that would be very difficult to code. The current behavior is a rule that is applied locally at each acquisition wrapper, and the wrappers don't know what wrapper is pointing to them, so it's really not practical for them to try and do something that smart. It may also be that what you're asking for is a bad idea, in which case Jim Fulton can probably explain why. :) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Security Gurus Wanted
At 10:43 AM 1/19/02 -0500, vio wrote: * vio [EMAIL PROTECTED] [020119 09:56]: So Globals.InitializeClass(your_class) finds the declaration 'security.declareSomething()' inside a class, but 'security' being a reference to a ClassSecurityInfo object AT THE MODULE LEVEL somehow has no effect at the class level (while I wrongly thought that by declaring it at the module level like that, it will behave more or less like a 'global' variable). I wonder what was carried at the class level, but something definitely was, else Python would have thrown something ugly at me. Check the Python reference manual -- not the library reference, but the language definition. You'll find that Python has two primary scopes: local and global. When a class statement is executing, the local namespace is the future __dict__ of the class, and the global namespace is the module __dict__. If security.Foo() is in the body of a class, and security is not in the *local* namespace (i.e. already defined in the class body), then it will be looked up in the global namespace. Thus, your calls went to the module-level security, but no security object was present in the resulting class (because there was no statement placing one there). IMHO, you don't want to share a security object between more than one class, since presumably they will have different declarations and thus each require their own. So there's no reason to create a ClassSecurityInfo object at the module level, anyway. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] im_self of methods accessed via non trivial acquisition
At 09:42 AM 1/18/02 +0100, Stefan Bund wrote: A--O--[a] | | | [b] | O--B--O--[c] | | | | | [d] | | | O--[e] | | | [f] | [g] ... let /m/ be a method of the objekt /f/. The expression of interest is x := A.m I would expect /x.im_self/ to be an acquisition wrapper C C := A.f where (as far as i understand the rules of acquisition) /C.aq_parent == A/ But instead displaying /x.im_self/ yields the acquisition tree rooted at /B/ !! I find this a bit disturbing. My question: 'Is it a *bug* or a *feature*?'. I hope, I made my point clear. Method rebinding is done only when an item is retrieved from the aq_self side, and only if im_self points to aq_self. If these conditions are met, a new binding is created which points to the acquisition wrapper. This is a feature, not a bug. If you rebind im_self on the aq_parent side, and your method assigns a value to an attribute of self, it will be assigned to the wrong object! It is safe in your example to bind m.im_self to B, because B.aq_base is f, the true self of m. But it is not safe to bind m.im_self to A, because A.aq_base is g -- another object altogether. I guess another way to look at it is that a method retrieved from an acquisition-wrapped object will always meet the condition that method.im_self.aq_base is the original object the method was retrieved from. This ensures that the method simply works with an acquisition-wrapped version of its original self. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] separate mailing list for ZPublisher-only apps (ZPub + cgi + apache)
At 10:06 AM 1/6/02 -0800, Michael Olivier wrote: I'd like to form (or join) a separate mailing list for ZPublisher-only apps. I know there are zope developers like me who use ZPublisher + FastCGI (or whatever) + apache (or whatever) to run a web site. I know we would not have the benefit of some of the expertise here, but the flip side is we would get more discussion for our flavor of zope use. Most of the discussion here is about the full Zope which is a lot to wade through for the occasional helpful tidbit. I'd be interested, and if ZC doesn't want to make it a zope.org list, I'm sure we could set it up at eby-sarna.com easily enough. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] References, persistence, BTrees
At 05:49 PM 1/3/02 -0700, Jeffrey P Shell wrote: 'subscriber' is a reference to the subscribing object, and it's very likely to be to an object in the ZODB. Is it wise to have more than one persistent reference to a single persistent object? I swear that I had once heard Jim say (vocally) that you could do references like this in the ZODB now. I'm trying to avoid using Paths because objects have a tendency to move around[*], and I have performance concerns for a single event service object to have to call 'unrestrictedTraverse' to every subscriber. Unfortunately, you can't take this shortcut. Not because you can't store or retrieve references in this way, but because you can't get an acquisition context this way, which means security is shot, not to mention things like objects knowing their URLs. So although it's perfectly safe to point to objects in the ZODB from more than one place, it's almost always useless to do so with respect to an arbitrary Zope object. :( I don't know if this is changing in Z3, but I'm rather curious about the possibility, myself. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPublisher Q about obj having both __bobo_traverse__ and index_html
At 10:18 PM 12/23/01 -0800, Michael Olivier wrote: I'm using ZPublisher + PCGI w/o the full Zope environment. Is it possible to have an object that defines a __bobo_traverse__ method and also has an index_html method? In the example below, I would want it to traverse if the URL path had more elements on it, and otherwise to call index_html(). Unless I comment out the __bobo_traverse__, the index_html method doesn't work. I also tried returning None in traversal if key was None, but that didn't work either. (I am running 2.0.1, so maybe I'm hitting a bug that's since been fixed.) class MsgDirList: message directory list def __init__(self): pass def __bobo_traverse__(self, REQUEST, key): # traverse if there is more in the URL path... Try putting this in right here: if key=='index_html': return self.index_html return CitiesMsgs(key) index_html is *added* onto the URL for traversal, so your __bobo_traverse__ should get asked for it. Note that you return self.index_html *without* calling it, as ZPublisher will do that for you. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] 100k+ objects, or...Improving Performance of BTreeFolder...
I'm not sure if this is taken into consideration in your work so far/future plans... but just in case you were unaware, it is not necessary for you to persistently store objects in the ZODB that you intend to index in a ZCatalog. All that is required is that the object to be cataloged is accessible via a URL path. ZSQL methods can be set up to be URL-traversable, and to wrap a class around the returned row. To load the items into the catalog, you can use a PythonScript or similar to loop over a multi-row query, passing the objects directly to the catalog along with a path that matches the one they'll be retrievable from. This approach would eliminate the need for BTreeFolder altogether, although of course it requires access to the RDBMS for retrievals. This should reduce the number of writes and allow for bigger subtransactions in a given quantity of memory. At 07:36 PM 12/9/01 -0800, [EMAIL PROTECTED] wrote: Interesting FYI for those looking to support lots of cataloged objects in ZODB and Zope (Chris W., et al)... I'm working on a project to put ~350k Cataloged objects (customer database) in a single BTreeFolder-derived container; these objects are 'proxy' objects which each expose a single record in a relational dataset, and allow about 8 fields to be indexed (2 of which, TextIndexes). ... - Also, I want to make it clear that if I had a data access API that needed more than simple information about my datasets (i.e. I was trying to do reporting on patterns, like CRM-ish types of applications), I would likely wrap a function around indexes done in the RDB, not in Catalog. My requires no reporting functionality, and thus really needs no indexes, other than for finding a record for customer service purposes and account validation purposes. The reason, however, that I chose ZCatalog was for full text indexing that I could control/hack/customize easily. My slightly uninformed belief now is that for big datasets or enterprise applications (whatever that means), I would use a hybrid set of (faster) indexes using the RDB's indexes where appropriate (heavily queried fields), and ZCatalog for TextIndexes (convenient). I'm sure inevitable improvements to ZCatalog (there seems to be community interest in such) will help here. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] 100k+ objects, or...Improving Performance of BTreeFolder...
At 04:08 PM 12/10/01 +, Tony McDonald wrote: On 10/12/01 2:54 pm, Phillip J. Eby [EMAIL PROTECTED] wrote: I'm not sure if this is taken into consideration in your work so far/future plans... but just in case you were unaware, it is not necessary for you to persistently store objects in the ZODB that you intend to index in a ZCatalog. All that is required is that the object to be cataloged is accessible via a URL path. ZSQL methods can be set up to be URL-traversable, and to wrap a class around the returned row. To load the items into the catalog, you can use a PythonScript or similar to loop over a multi-row query, passing the objects directly to the catalog along with a path that matches the one they'll be retrievable from. This approach would eliminate the need for BTreeFolder altogether, although of course it requires access to the RDBMS for retrievals. This should reduce the number of writes and allow for bigger subtransactions in a given quantity of memory. Gad! - are you saying you don't need to store a 1Mb .doc file into the ZODB, but can still index the thing, store the index information in the Zcatalog (presumably a lot smaller than 1Mb) and have the actual file accessible from a file system URL? If so, that's really neat! Yep. By URL path, though, I meant a *Zope* path. However it would be straightforward to create a Zope object that represents a filesystem path and does traversal/retrieval, assuming that one of the 'FS'-products out there doesn't already do this for you. Chris Withers has pointed out that technically you don't even need the path string to be valid, it just has to be unique. However, the standard tools and the method for getting the real object referred to by the catalog record do expect it to be a valid path IIRC. I personally find it most convenient, therefore, to use a real Zope path. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPT Plain Text
At 05:58 PM 12/4/01 +, Chris Withers wrote: Phillip J. Eby wrote: I personally would like to see ZPT support plain text at some point, and it already has some of the things necessary to do it. But that's a separate issue from Zope 3X or Zope 3 itself. It already can: [example snipped] Last I looked, there were still certain constructs that could not have the tag opted-out-of. But that was a month or two ago and TAL moves fast... :) I don't remember seeing tal:omit-tag before, so maybe that was the last piece of the puzzle. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ComputedAttribute, Persitent and too many datafull base classes
At 03:44 PM 10/20/01 +0200, Godefroid Chapelle wrote: Hi, In a product I am writing, I am trying to add a ComputedAttribute to an instance of a Folder descendant class. This is the code I use: def addComputedAttribute(self, attributeName, sourceCode): methodName = '_ca_get%s' % attributeName self.addMethod(methodName, sourceCode) setattr(self, attributeName, ContextComputedAttribute(self.__class__.__dict__[methodName])) I think the problem you're having is that the method object being used in the last line (i.e., self.__class__.__dict__[methodName]) is not persistent. If it is a Python function, it will not be saved persistently within the computed attribute. This is probably why the Zope instance crashes at a later time. This doesn't have anything to do with whether ComputedAttribute is Persistent. It doesn't need to be, which is a good thing because you can't derive a class from both (as you've discovered). You can write a Python version of ComputedAttribute by deriving only from Persistent, but as I said there is really no need to do that. You need the function to be persistent, not the ComputedAttribute itself. If the function is currently a pure-Python function, you need to replace it with some kind of callable object that can be pickled, such as a PythonScript. You could also write your own class to do this, but again it is not the ComputedAttribute part that would cause a problem. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPublisher/ZServer interaction (was Re: A modest proposal)
At 10:23 AM 10/12/01 -0400, Paul Everitt wrote: Wow, this is one hell of a thread. :^) FWIW, Grisha put a Bobo publisher in mod_python a couple of years ago. Thus, if you like ZPublisher-style processing, you can do it in Apache via mod_python. Personally, I prefer to keep a process boundary between Apache and my apps, for both safety and security. Usually they're running as different users, for one thing. We've been very pleased with FastCGI performance using mod_fcgi, so I don't see a whole lot to be gained by using mod_python. Another interesting factor that can affect performance is that we usually run many pre-forked Apache child processes, but rarely have more than 2 or 3 application processes. Using mod_python would probably impact memory usage adversely, since there would then be in effect a larger application pool. A somewhat simplistic analysis of memory usage in the different approaches: O = Fixed application overhead (e.g. Python modules) D = Application dynamic data A = size of an Apache process P = Memory used for a python interpreter (if the OS shares executable segments, ignore the code size, as it will be a constant for all approaches and thus irrelevant for comparison purposes. In that case consider P will be the interpreter's data size) n = Number of threads or processes in the app server pool s = Number of Apache servers Zope w/Apache frontend = P + O + D*n + A*s mod_python = (P+O+D)*s + A*s ZLite = (P+O+D)*n + A*s Since n is usually smaller than s, the ZLite approach uses considerably less memory than the mod_python approach, but can be faster than the Zope+Apache combination on multi-processor machines when the Python interpreter lock is an issue, at an extra cost of only (P+O)*(n-1). In our situations, that usually amounts to at most 2 or 3 times P+O, which is a small price to pay for also being able to ignore all threading issues. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] RE: Component Architecture / A modest proposal: Replace medusa with Twisted
At 01:52 PM 10/11/01 +0200, Jean Jordaan wrote: Hi all I don't know if you're all familiar with this already, but reading about Twisted didn't immediately bring to mind Medusa, but rather certain aspects (specifically, *aspects*) of TransWarp, and of the Component Architecture (interfaces). I'm including a bite from http://twistedmatrix.com/page.epy/twistedphil.html Interesting? What they're doing is more of a design pattern ala JavaBeans to create interface definitions using method signatures which can be recognized using introspection. However, a major point of the Component architecture is to get *away* from this style of doing things in Zope, because it makes it harder to use objects off the shelf, as one is required to code objects from the ground up for Zope use. Whereas, in the New Religion, you can just stick an __implements__ attribute on them, and set up some adapters. (Also, what Twisted is doing is entirely orthogonal to what TransWarp does, but I covered that in my reply to your post on the TransWarp mailing list. :) ) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] ZPublisher/ZServer interaction (was Re: A modest proposal)
At 08:00 AM 10/10/01 -0700, kapil thangavelu wrote: sadly the distinction between zpublisher and zserver is nowhere near as clean, i spent some time looking at it this morning trying to get my server of choice using zope. i thought it would be a mid morning hack, but the rabit hole follows the class heirarchy deeper and deeper:). all i have to show for my results is zope's output dumped to the server logs. its a start though... hopefully we get some new religion in the publisher, please... Hmm... Check out: http://cvs.eby-sarna.com/pylib/ZLite/ Specifically, the ZPlumbing module, for several examples of ZPublisher run loops using CGI and two different FastCGI modules. I don't know anything about Twisted, so I couldn't tell you how easy it'd be to use the ZLite framework for this. ZLite is the beginnings of my work on a Zope Lite distribution. It's sort of the Standalone ZODB distribution's evil twin - intended if you want to use almost anything *but* the ZODB and ZMI parts of Zope. That is, when you just want the app server without the IDE and application framework. Architecturally, it's intended for multi-process, single thread setups using Apache as a front-end, with FastCGI. This shouldn't be considered an announcement or a release, btw. The code in CVS is production-hardened by years of service (many millions of hits served), but is utterly without documentation, nor has everything I've written been checked into CVS yet. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Stored Procedures with Sybase and the Sybase DA
At 01:50 PM 10/1/01 +0200, [EMAIL PROTECTED] wrote: Does anybody know of any development going on regarding Sybase and stored procedures? Christopher Petrilli declared them a future goal, but I urgently need them by now. So if anybody has a workarround, please let me know. Ty did some work on this for Zope 2.2 which you can find at: http://cvs.eby-sarna.com/ZProducts/SybaseStoredProcedure/ There's no docs to speak of. Feel free to use it if you can get it to work. I think that to get this to work, we also had to patch the Sybase DA to handle status result codes, but that patch might have been incorporated into Zope. I'm not positive about any of this. :( All I can tell you is that the code above is in actual use in a production application that needed stored-procedure support. Note that it does not support returning SELECT results from procedures; only non-negative status returns. It assumes a negative status is an error, and if it's one of the standard Sybase status error codes (e.g. -3 for a deadlock), it throws a SybaseProcError with an explanation and the original query text. The return value from calling a StoredProcedure object is always an integer 0 or greater, unless the status return is negative, in which case an exception is raised. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Stored Procedures with Sybase and the Sybase DA
At 03:33 PM 10/1/01 +0200, [EMAIL PROTECTED] wrote: I use the newest version of the Sybase DA, but it doesn't seem to work. Can you help me finding the appropriate patches, etc? Are they available anywhere in that CVS-tree?` I don't think so. Ty was going to submit them to ZC for inclusion; I don't know if he did or not. It had to do with a Sybase discriminator code that the existing DA didn't handle. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Re: [ZPatterns] HowTo: Make an Image/File a DataSkin ???
At 08:03 AM 7/11/01 +0100, Steve Alexander wrote: Steve Spicklemire wrote: Hi Ulrich, Hmm.. can you just call DataSkin.__init__(self, id) in the File's constructor? You might need to do it like this: DataSkin.inheritedAttribute('__init__')(self, id) Actually, I'm not sure you need to do anything special at all. If you use the File DataSkin in a Folder w/Customizer Support, you shouldn't need to do anything special, because in that mode the 'id' attribute is never used by ZPatterns. If you need to use these File DataSkins in a Rack, though, you'll need to include a SkinScript that says:: WITH SELF COMPUTE id=getId() Racks still use the id attribute directly, I'm afraid. Your '__init__' method will still need to accept an 'id' parameter, also, and you'd need to set the __name__ attribute instead of id. Ugh. Anyway, I will take a look at Rack and see if it can be made to use the 'getId()' and 'setId()' methods. Of course, you can also subclass Rack and replace the '_getClientID(client)' method with one that uses 'getId()', but it might be that I could do this safely in the base Rack class. The SkinScript examples should also probably be changed to use 'getId()' instead of 'id' so that people don't use them as a justification for continuing to indulge in deprecated behavior. :) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] UML and XMI support now available in TransWarp CVS
Recently, there has been much interest (on Zope-Dev and elsewhere) in creating Zope and Python applications from UML diagrams. Since to my knowledge there are no other Python libraries currently available for UML/XMI processing, I decided to get busy and release a version of TransWarp with support for querying/manipulating UML models and reading XMI files. That version is now available at cvs.eby-sarna.com, for brave UML hackers to experiment with. I say release, but if you've ever heard the jokes about Klingon programmers, you'll know that Klingon programmers do not *release* code. Their code escapes, leaving the bloody corpses of testers, users, and documentation writers in its wake. This is pretty much the case for this rough draft of UML/XMI support. It is functional, but the interfaces are subject to future upheaval as I continue refactoring. This release is ONLY for people who have a good understanding of UML, and aren't afraid to UTSL (Use The Source, Luke). Current Features: * Load an XMI file into a UML Model object * Query UML model using full StructuralModel features and querying interface * Create your own custom classes for UML elements - e.g. you could redefine ModelElement to include a method to print out a nice report on the element's features. You could also implement executable UML with this approach. Current Limitations: * **ALL** model attributes are strings, rather than their correct type, so booleans for example are represented as the strings true and false. Note that this doesn't mean you can't manipulate a UML model which *defines* non-string attributes. It's the attributes of the model *itself* (like the 'isRoot' attribute of a 'GeneralizableElement') which are currently all strings. (This will be fixed when I finish refactoring to the full Service-Element-Feature pattern, and every element class has a corresponding Service object responsible for marshalling to/from strings.) * Only the InMemory StructuralModel implementation can currently be used, mainly because there aren't any other implementations of the StructuralModel. Example of use (note, this is *all* subject to interface upheaval in future): # begin example code from TW.UML import UMLRecipe from TW.StructuralModel.Queries import Type, ANY # if you have your own specs for classes, add them to UMLRecipe first UMLModel = UMLRecipe(name='UMLModel') myModel = UMLModel() myModel.importFromXMI('someXMIfile.xml') # print the names of all classes print myModel.Where(Type('Foundation.Core.Class')).Get('name') # Shortcut to get a type name if you only know the short form... But # it's better to just do this manually once to find out the name for # future use; I'm not guaranteeing that _XMINames will always exist in # its present form! Package = UMLModel.Package._XMINames[0] isPackage = Type(Package) # print the names of all packages which contain other packages print myModel.Where( isPackage ANY('ownedElements',isPackage) ).Get('name') # end example code I'm willing to answer questions about the TW parts of this (how-to's, problems, etc.), but can't provide handholding for anything else. For example, me explaining XMI or the UML metamodel in general is out of scope. So if for example, the code barfs in the 'xml' package because it can't parse your XMI file, it's probably a problem with the program that generated the XMI. If it barfs in the 'TW' package, it's probably something to do with my code, unless you just have a very nastily malformed XMI file (in which case I'll want to see the smallest version you can send me that still produces the error). Feedback from UML/XMI hackers is welcomed and encouraged. Please direct all responses to the TransWarp list, [EMAIL PROTECTED] To subscribe to the TransWarp list, visit: http://www.eby-sarna.com/mailman/listinfo/TransWarp Thanks. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] Re: [ZPatterns] Best Free UML, XMI, Zope/Transwarp tools
At 10:35 AM 6/28/01 -0700, jimbo wrote: I've been looking for a standard *FREE* tool that I can use to design Zope apps. I think my search is over. It seems to be a good tool for students because it's free and comes with support for Java, Persistence and XMI, Full and partial exchange. I wonder if Transwarp is at the point of being able to use UML/XMI stuff. Well, the current CVS has a full UML metamodel in it, and the test suite actually performs some operations such as creating a UML model, adding items to a package, and so on. But I still haven't rewritten the XMI support. I expect it to be another month or so before that shows up in CVS. (By the way, the best place for discussion regarding TransWarp is the mailing list [EMAIL PROTECTED], and the zope-dev list generally frowns on crosspostings for discussion. If you reply to this message, be sure to only reply to [EMAIL PROTECTED] Thanks!) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] ZPatterns DATA LOSS BUG and FIX (0.4.3p1 patch release)
ZPatterns 0.4.3final contains a serious bug which deletes all ZODB-stored contents of a Rack when you use the manage_pack method. This bug only affects you if you store Rack-mounted objects or attributes in the ZODB, and does not affect you if your objects are entirely contained in an RDBMS or other mechanism external to the rack. If you've upgraded to 0.4.3, please do not use manage_pack! I have uploaded new versions of ZPatterns and PlugIns to fix the problem with packing racks, and to provide experimental support for Zope 2.4b1. (Specifically the problems reported below with expr_globals and ts_regex have been fixed.) Please upgrade to 0.4.3p1 before using manage_pack, or if you wish to experiment with ZPatterns on Zope 2.4b1. Thanks. Thanks too, to Juan Palomar and Itai Tavor for providing information and patches. At 11:01 AM 6/26/01 +0200, Juan David Ibáñez Palomar wrote: With Zope 2.4b1 and ZPatterns 0.4.3, the following error raises when starting Zope: 2001-06-26T08:24:40 ERROR(200) Zope Could not import Products.ZPatterns Traceback (innermost last): File /home/jdavid/Zope-2.4.0b1/lib/python/Products/ZPatterns/Expressions.py, line 38, in ? (Object: ComputedAttribute) ImportError: cannot import name expr_globals expr_globals is not available in Zope 2.4, the fix is: ... Besides this error, there're some warnings: /home/jdavid/Zope-2.4.0b1/lib/python/ts_regex.py:87: DeprecationWarning: the regex module is deprecated; please use the re module import regex, regsub #, Sync /home/jdavid/Zope-2.4.0b1/lib/python2.1/regsub.py:15: DeprecationWarning: the regsub module is deprecated; please use re.sub() DeprecationWarning) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Bulletproof ZCatalog proposal
At 04:58 PM 6/8/01 -0400, Shane Hathaway wrote: On Thursday 07 June 2001 21:28, Phillip J. Eby wrote: Upon being told to perform a transaction or subtransaction commit, the transaction would notify all the ruleAgents, and then all the indexingAgents. Objects could still subscribe to either queue while this notifying is taking place. (So that triggered actions could cause indexish objects to register as indexingAgents, not to mention causing updated objects to fire additional triggers.) Once all agents in a queue are notified, that queue should be cleared so that notifications are on a per-subtransaction basis. Once both queues are cleared, normal transaction behavior goes forward. Would you say this would occur before tpc_begin() messages or just after? Before. I'm saying this would take place immediately at the start of the existing Transaction.commit() method. Hm. That's simpler than I thought it was going to be. Shoot, I can even see how to implement it as a runtime patch, that would've been simpler than all the shenanigans ZPatterns goes through to fake out the transaction machinery... and it's a better implementation. Ah well. At the time I wanted to avoid trying to convince Jim to add machinery to transactions just for ZPatterns, given that ZPatterns wasn't a particularly established product at the time. Let me know if you guys put something like this in, though, and I'll definitely look at reworking ZPatterns to use the mechanism. It could potentially cut a lot of code out and improve the robustness at the same time. I don't foresee us adding this capability right away since we need to understand it better and it only applies to one working product and a hypothetical product. I'd suggest you go ahead with the runtime patch. I think I'll wait until ZPatterns works with Zope 2.4, unless it becomes necessary otherwise. Replacing what I've got now is a pretty significant undertaking, and risk-prone to boot, so I don't want to delay the finishing of ZPatterns' support for Zope 2.3.x. Basically, the runtime patch would be to replace ZODB.Transaction.Transaction with a subclass that implemented the notification queues in the commit() method. There'd be a few other little extensions needed, like clearing the queues on any abort operation, and adding registerIndex() and registerRule() or some such methods. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Bulletproof ZCatalog proposal
At 02:07 PM 6/7/01 -0400, Shane Hathaway wrote: On Thursday 07 June 2001 12:17, Phillip J. Eby wrote: The only catch was that this would still produce conflicts at the head end of the linked list. :( Of course, that was in the days before ZODB conflict resolution. Nowadays, you could probably implement it as a simple sequence object with the conflict resolution method implemented. But then there'd be the question of how to resolve conflicts if more than one thread or ZEO client decided to apply the queued changes... a 100 conflicts vs 1 situation. Ugh. I was thinking the queue would only last the duration of a transaction and that the queue would be thread-specific. That's not hard to do - you could just toss an object into the transaction queue to do it during transaction commit, similar to what ZPatterns does in a more general way. (Note that ZPatterns users can already get the benefits of deferring catalog changes until the end of a (sub)transaction, by using triggers to implement automatic cataloging). Anyway, I'd be really interested in seeing a solution for all the issues in conflict resolution. I was thinking that certain types of objects would be committed by the transaction manager before all others. In this case, the catalog (or a special object in the catalog) would be committed first. It would resolve all conflicts in the contained indices before they occur by replaying the changes in the persisted queues from the transaction history, then setting the _p_serial attributes to convince the storage that the conflicts have already been resolved. Hm. Sounds to me like what you actually want is for the transaction manager to do this *after* everything else, rather than before. Thus, you would catch any changes which occur *during* transaction commit - such as commit-phase cataloging (as some folks do with ZPatterns currently). That is, in ZPatterns one can specify triggers such as: WHEN OBJECT DELETED, CHANGED CALL someCatalog.manage_uncatalog(self.absolute_url(1)) WHEN OBJECT ADDED, CHANGED CALL someCatalog.manage_catalog(self,self.absolute_url(1)) Which will be executed during transaction commit if the conditions apply. If you have the catalog process its queue *before* other objects commit, it will not have received these calls yet. This will end up making the catalog try to commit itself a second time, which will fail with a conflict error - 100% of the time. (And retry won't help, because the transaction is conflicting with itself.) Of course, this issue could be fixed by minor adjustment to the ZODB API and implementation such that it is permissible to store() an object more than once during a transaction's commit phase without creating a ConflictError. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Property Storage
At 09:29 PM 6/7/01 +0100, Chris Withers wrote: If I change one property on, say, a DTML Document, does that store a whole new copy of the document in the ZODB? It updates the object in the ZODB. Whether that causes a copy to be made, depends on the underlying storage. FileStorage makes copies, BerkeleyStorage (at least Ty's first implementation thereof) does not. Is so, then how about storing properties in their own mini-class that just subclassed Persistent, so each property got its own pickle jar? There are a lot of things you'd have to tinker with to get that behavior. You would probably be better off just using a storage that doesn't make copies, or using ZPatterns to store selected attributes in such a storage (such as a differently-backed ZODB, the filesystem, or an SQL or LDAP database). ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Bulletproof ZCatalog proposal
At 07:07 PM 6/7/01 -0400, Shane Hathaway wrote: Phillip J. Eby wrote: That is, in ZPatterns one can specify triggers such as: WHEN OBJECT DELETED, CHANGED CALL someCatalog.manage_uncatalog(self.absolute_url(1)) WHEN OBJECT ADDED, CHANGED CALL someCatalog.manage_catalog(self,self.absolute_url(1)) After I read this again I realized what you were saying. This capability of ZPatterns is very brittle, don't you think? Yep. That's why I've previously described ZPatterns as a hack. :) If the catalog is updated manually before the special ZPatterns object is added to the queue, the behavior is undefined AFAIK--either the later changes to the catalog will be ignored, will cause a conflict, or some objects will be written twice in the same transaction. True. But this behavior is avoidable through the use of subtransaction commits, in the event that someone has to have transactions which update a ZCatalog directly. Usually, when someone is using catalogs with ZPatterns, they use triggers to do all the updates and don't touch the catalog manually. Note that I'm not saying this still isn't a hack. But it's the best I could do without either fixing the multi-commit issue in ZODB, or with some kind of priority scheme. However, if we could specify transaction commit priorities, and the ZPatterns update came first, auto-indexing came second, and everything else followed, I think it would work. Or perhaps ZPatterns should be able to register things that occur *before* the two-phase commit protocol. Yep. One of the last two times I spoke with Jim in person (either the January DC visit or IPC 8, I forget which), he said something about it maybe being a good idea to have some kind of priority system like that. I'd love to see something like it exist, if it would make some of ZPatterns' hackery unnecessary. The implementation could consist of two subscription queues: ruleAgents and indexingAgents. ZCatalog would register in indexingAgents, and ZPatterns objects would register in one or the other, usually ruleAgents. (I can think of some circumstances where it would be nice to use the indexingAgents queue, but right now ZPatterns apps have to work around this by defining their rules in execution priority order.) Upon being told to perform a transaction or subtransaction commit, the transaction would notify all the ruleAgents, and then all the indexingAgents. Objects could still subscribe to either queue while this notifying is taking place. (So that triggered actions could cause indexish objects to register as indexingAgents, not to mention causing updated objects to fire additional triggers.) Once all agents in a queue are notified, that queue should be cleared so that notifications are on a per-subtransaction basis. Once both queues are cleared, normal transaction behavior goes forward. Hm. That's simpler than I thought it was going to be. Shoot, I can even see how to implement it as a runtime patch, that would've been simpler than all the shenanigans ZPatterns goes through to fake out the transaction machinery... and it's a better implementation. Ah well. At the time I wanted to avoid trying to convince Jim to add machinery to transactions just for ZPatterns, given that ZPatterns wasn't a particularly established product at the time. Let me know if you guys put something like this in, though, and I'll definitely look at reworking ZPatterns to use the mechanism. It could potentially cut a lot of code out and improve the robustness at the same time. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] getPersistentItemIDs not cooperating?
At 05:48 PM 5/23/01 +0200, Christian Scholz wrote: Hi! It works.. partially. For some reason it looks like getPersistentItemIDs does not always return a *complete* list. I need to run this method several times to completely exhaust the Rack's storage. Thoughts? The only way I ever create Track objects is via a different method that is only accessed once (a long time ago!) Well, I experiences something similar when changing a Racks storage from persistent to non-persistent. The included objects are marked as orphaned then and should be deleted with the Clear-Button. This also works, but only the half of them gets deleted every time I click on that button.. So I also have to press it several times.. Sounds like the same problem.. I just thought of how this happens... if you delete an object from the Rack, it's being removed from the virtual list of keys your loop is traversing. So as you iterate from 0..n, and you delete items from the rack, they are removed from the keys list too, the list shortens, and every other item in the list is skipped! This is why you get half the list every time. The fix would probably be: foo = getPersisentItemIDs() while foo: foo[0].manage_delete() I should probably do this in ZPatterns too. I'm working on upgrading it for 2.3.2 right now anyway. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] getPersistentItemIDs not cooperating?
At 12:33 PM 5/23/01 -0500, Steve Spicklemire wrote: Hi Phil, FYI.. this doesn't work in a PythonScript since indexing into a BTreeItems is (apparently) not allowed by the Security Machinery. So... a simple list is looking better and better! ;-) Hmmm. Good point. I'll have to think about that one. I just hate to load all those keys if they're not really needed. I suppose if you call getPersistentItemIDs(), you usually want them all... It's just that if you use the BTreeItems object, it can toss out keys that aren't needed. Maybe what I'll do is implement a wrapper over BTreeItems that fixes this somehow. I'll also have to look at how this works with the new BTrees trees, because I *know* they don't implement indexing the same way, and may not have this problem! ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Experiments with ORMapping
At 12:26 PM 5/14/01 -0400, Shane Hathaway wrote: Chris Withers wrote: Shane Hathaway wrote: One would define an ObjectMappingSchema whose job it is to store and retrieve objects of a specific type and in a specific location. It would usually grab a database connection object to do its work. When loading, it would perform a query then manually put attributes into a persistent object. When storing, it would grab specific attributes from the persistent object and execute a statement to store those attributes. How does this differ from ZPatterns? Phil? ZPatterns implements storage logic on the application level. Applications have to be aware of (in fact they have to be centered around) ZPatterns. This alternate approach keeps storage logic independent of application logic. It lets you take any code written for the ZODB and move it to your RDBMS schema without changing the code (most of the time :-) ). I am reminded of a passage from Dirk Gently's Holistic Detective Agency, wherein Dirk decides to cut to the heart of the problem, and simply writes down the answer. Now, he declares, he is faced with only a relatively much easier problem: What strange language did he write the answer down in? While I'm not saying that what you're doing isn't possible, I *will* say that I believe you are replacing a small amount of API-specificity in the code with a similar amount of specificity, coupled with a much larger complexity in the mapping layers. It is, IMHO, much harder to write generic mappings at the schema layer where you propose, than to do so at the domain logic layer where ZPatterns operates. Ty and I spent many weeks chewing over designs in the space you're talking about, back before ZPatterns existed, after consulting at length with Jim Fulton and Michel Pelletier. Our conclusion was that yes, it was *possible* to do the mapping you're talking about, but that it was very high impedance for the kinds of applications we had in mind. I'll give a simple example to show what I'm talking about. Consider a task framework where TaskPerformers are assigned Tasks, in a simple one-to-many relationship. TaskPerformers, in this framework, perform up to hundreds of tasks per day, thousands per month. Assuming an RDBMS backend, how do you propose to map this in your storage model? My thought on this, is that you will be forced to explicitly consider the nature of this relationship and its storage at the application level. If you write explicitly for ZODB, you might use a BTree, for example. Or perhaps you'd have some kind of global container for the Tasks, with a Catalog to index them, and a method on TaskPerformer to query the Catalog. How would you propose to map this to an RDMS? Well, substituting catalog queries might be relatively straightforward, but perhaps rather time consuming to develop in a generic way. The BTree might give you a bit more trouble. Probably you'd have to end up using some sort of generic queryable containers that translated to BTrees or Catalogs or RDBMS tables, depending... And lo! You now have an application framework. Oops. We haven't even addressed performance issues yet, which are the real killer. The only way (again IMHO) to get reasonably high performance that is portable across different databases is to be able to write code that is optimized based on the back-end. The only way you can push this code under the hood is to create an all-purpose query mechanism. Otherwise, you must expose enough of the inner workings to the application developer that they can include platform-specific code for each circumstance. All this is of course just my opinion, and quite possibly wrong. But I think that an application developer would get more mileage out of your DBAPI product (coupled with some utility classes to replace Racks) or from ZPatterns than they would from this approach to O-R mapping. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Experiments with ORMapping
At 05:42 PM 5/11/01 -0400, Shane Hathaway wrote: Phillip J. Eby wrote: I'm not quite clear on how exactly you suggest mapping from RDMBS - ZODB. There's a *significant* (IMHO) impedance mismatch between ZODB's arbitrarily identified variably structured single records and SQL's content-identified fixed-structure record sets. This is what application frameworks/toolkits (such as your own DBAPI product) are needed for. If you implement this at the Storage level, yes, there is a major mismatch. But at the Connection level it makes a lot of sense. Connection basically exposes a pile of pickles as objects; an OR mapping exposes a complex schema as objects. I think that understanding will change the rest of your response. :-) Nope. As far as I can see, all that does is leverage ZODB Connections as a crude sort of Rack that only provides a mapping-like interface for retrieving objects, without helping any of the higher-order needs of an application. I guess if you define O-R mapping as can you store and retrieve an object's properties from a database, then I guess you've succeeded at that point. But if that was all my O-R apps needed, there would've been no reason to use the RDBMS; I could've just used ZODB and a BTree with less bother. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Experiments with ORMapping
At 11:01 AM 5/11/01 -0400, Shane Hathaway wrote: Joachim Werner wrote: The current design plans of SmartObjects are mainly based on the assumption that we will not be able to change Zope itself. This is not a dogma for us, however. I guess doing OR-mapping in the Zope core would be fine with us ;-) FYI by replacing I don't mean changing anything in the Zope core. I mean using a different class in place of Connection, which you can do just by creating a custom_zodb.py. Hm. So you're suggesting creation of a Storage class that returns a special root object which emulates the standard ZODB root PersistentMapping, and contains another object that emulates a folder, with a bunch of other foldoids that are actually tables, or something of that sort? And maybe exposes some query methods ala ZCatalog? I'm not quite clear on how exactly you suggest mapping from RDMBS - ZODB. There's a *significant* (IMHO) impedance mismatch between ZODB's arbitrarily identified variably structured single records and SQL's content-identified fixed-structure record sets. This is what application frameworks/toolkits (such as your own DBAPI product) are needed for. But the more important one for us is that we still believe that even with ZCatalog Zope can not really do efficient croos-tree queries in all cases. A query like Give me all users who have bought this and that product and are aged 20 or above can not be handled by the catalog, I think. Yes it can. :-) That's not to say that it has as much flexibility as a SQL query, but it can do most of the things people usually do with one table at a time. Here's the goal I envision for OR mapping: to be able to move between OODBMS and RDBMS seamlessly. It makes sense to develop on top of ZODB then move to an RDBMS for testing and deployment. Unfortunately, I think that this requirement can *only* be met through a common API or access pattern/framework/what-have-you, be it DBAPI, ZPatterns, SmartObjects, or TransWarp. The ZODB is both too powerful (in its flexibility) and too weak (in lack of any ZODB-level notions of record sets, schemas, and indexing) to be useful as a cross-database-platform API. That's not to denigrate any of the value of ZODB itself - an explicit goal of both ZP and TW is to leverage ZODB's flexibility in combination with other kinds of databases. (And, recently, I have been speculatively eyeing the ZODB for some mortgage-industry related projects which involve complex variable data structures, distribution requirements ala ZEO, and local data stores on intermittently-connected laptops.) SmartObjects is more of a programming framework than just adding OR-Mapping to Zope. So if we can solve the storage and query parts more efficiently by just having Zope itself extended a bit, this would be very cool ... You see, I think it is not necessary to create a programming framework if the goal is OR mapping. The framework is already defined, and it's Python / ZODB. But SmartObjects seems to have many loosely related goals, making it difficult to assist. I think the goal for SO, and all the other frameworks that have been created or are being created, is to *make application development easier*. OR mapping is just a means to that end. LDAP connectivity, or other types of non-ZODB data access are important to many of us, as well. This boils down to abstraction of how data attributes are represented. For example, if I am an ISP, and I want to implement an active flag on an account object, I would like changing it to automatically go out and add or remove routing entries and password entries on my servers when I update the record through my Zope interface (web, SOAP, or whatever). Could you make a ZODB Storage object that supported this? Maybe. But from an architectural standpoint it would be rather messy - akin to writing OO code with giant switch statements. The Java (and CORBA, actually) solution to this, is to use a property pattern, where a property is a non-real thing that actually only has setters and getters. An object's users always go through these accessor methods, so the implementation can be anything you like. (Notice, btw, how the solution is once again a framework pattern...) ZPatterns was an effort to produce a Pythonic emulation of this concept that didn't need actual methods. It unfortunately inherits some of the flaws of __getattr__ hooks, such as forced semi-centralization of implementations. TransWarp does away with that and instead introduces property (feature) objects which themselves have methods, but are not data. This provides a bit more extensibility than the Java approach, since it is conceivable one could add an observable interface to a property object and thus subscribe to it, for example. Anyway, all I'm really trying to say is, if you want implementation independence, you have to have implementation hiding. ZODB makes it easy to store
Re: [Zope-dev] ZPatterns Rack question..
At 06:00 PM 4/28/01 +0200, Christian Scholz wrote: Hi! First of all one note to the sql attribute provider: My problem seems to be solved now. Actually it was quite easy.. dunno why it took the long way.. thanks anyway to Phillip and Steve! But I have another problem now: I have some rack with persistent objects in it. Now I want to migrate my site to production. Problem: If I do this more often and the objects are within some Rack, then also these get copied to the production site and the old objects will get deleted there. Is there any way to first backup the contents of some rack? Or do I need to construct it all as external storage? (basically most things are in an sql db already, I just put image data etc. into the rack directly as I don't need relational access to it..) Actually I know how to read the objects from the BTree but I dunno how to store them again into another rack (which has the same storage attribs of course). Can I simply use _setRack()? I guess not, eh? :) My suggestion would be to copy the Rack using normal Zope copy/paste (assuming that works), and then from Python poke the old rack's BTree into the new Rack. Then delete the old rack. This really sucks as a mechanism, however. The way I originally intended to solve this issue was to allow the Rack's persistent data to be stored outside itself somewhere. That's why some versions of ZPatterns have a little dropdown on the Storage tab which only has one selection - stored inside the rack. The idea was that maybe someone would create storage providers which could be kept external to the Rack and then acquired. This could still be done, if somebody wanted to take up the coding. Then you could upgrade/replace a rack without damaging data stored in it. Ty and I never got around to doing it because so far, all our ZPatterns apps have not had any ZODB-based data, only SQL and LDAP. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] Re: hack for refused authorization with virtual dataskin
At 01:37 PM 4/23/01 +0200, Godefroid Chapelle wrote: Hello, After rereading the ZopeSecurityPolicy source code, I tried the following hack. I add in the skinscript : WITH 1 COMPUTE __allow_access_to_unprotected_subobjects__=RESULT which does work : it fools the security mechanism. I can live with it but feel that there is only a slight problem which could allow me to avoid the hack. I hope this can hint some of you to help me to understand what is badly settled in my installation. It sounds to me like you need to be using the getId() method instead of the .id attribute. I think that the id attribute is being phased out in favor of getId(). I'm somewhat reluctant to enable access to unprotected subobjects in the DataSkin base class; it seems a little too broad of an access level. The other alternative would be to allow SkinScript expressions free rein as regards security - but that's too broad also. The optimum would be to allow SkinScript expressions full access to the targeted DataSkin's direct attributes, but normal (validated) access to everything else, but I'm not sure how to do this safely. This is an example of why I consider ZPatterns a hack - too many places where it depends on Zope innards like this. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns AttributeProvider question
At 03:07 PM 4/22/01 +0100, Steve Alexander wrote: As a simpler workaround, you can use your_object.commitSubtransaction() instead of redirecting to a new page. Um, this shouldn't be the issue here. _SetAttributeFor() should be called when the attribute is set; it's not transaction-driven. Something weird is happening with Christian's situation that I haven't investigated yet. You really should be able to create a new object and set its attributes in the same transaction. The status of the object (_v_status in DataSkin.py) will be ChangedStatus, if you're adding and changing in the same transaction. That's a good place to look for where the problem is. Actually, the status should be AddedStatus, and it should stay that way throughout the transaction, unless the object gets deleted in the same transaction. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns AttributeProvider question
At 08:29 PM 4/22/01 +0200, Christian Scholz wrote: Hi! A little update.. Actually I was mistaken and SetAttributeFor() is called. Just _objectChanged() is not called in that case.. and thus my attributes are not stored to the database. When an object is newly added, only _objectAdded() is called. _objectAdded(), _objectChanged(), and _objectDeleted() are mutually exclusive within a given transaction. That is, only one of them occurs in a given transaction. See more below. Maybe some more code will help (just the important pieces): def _objectAdded(self,client): """ store cached data in database """ ... here we do an sql query to insert things in database ... def _objectChanged(self,client): """ store cached data in database """ ... here we do an sql query to update things in database ... def _objectAdding(self,client, _tmap={ None:AddedStatus, DeletedStatus:ChangedStatus, ChangedStatus:AddedStatus } ): t = client._getTokenFor(self) s = t.status t.status = _tmap.get(s,s) # we need to do a commit here in order to store the record into the database! # and we need to have it stored as an AttributeFor() of the primary key will # return None otherwise (as this also just makes a query). client.commitSubtransaction() This is broken. Don't do this! commitSubtransaction() is an application-level operation. Only. If you have to use it inside of provider-level code or code called from SkinScript, chances are that you are doing something horribly wrong. You run the risk of causing a recursive commit operation in the Zope transaction machinery. Don't do this! def _SetAttributeFor(self,client,name,value): """Set the attribute and return true if successful""" # attribs stores the attributes we care about if name in self._attribs.keys(): client._getCache()[name]=value client.__dict__[name]=value; client._p_changed = 1 return 1 return None This also looks broken to me. Why are you changing both the cache and the persistent state? There's no reason to do both. So _objectChanging() is not overridden, the rest I have ommitted.. So as you also can see I already do a subtransaction commit but it does not seem to help for this problem.. I think you're seriously over-engineering this. I don't see anything that you're doing here that couldn't be done more easily with SkinScript statements. If all you want to do is store the data in an SQL database, a few SkinScript triggers would suffice. Now, if you're trying to get a row to be inserted in an SQL database at the actual time of the newItem() call, there is a trick you can use to do that from SkinScript also. Do this: INITIALIZE OBJECT WITH someAttr1=default1, someAttr2=default2,...,dummyAttributeName=myInsertQuery(primaryKey=self.id) Where myInsertQuery() is an SQL insert query that takes primaryKey as a parameter, and dummyAttributeName is some attribute name you don't care about. You should also set any default values for fields that will be inserted. Your insert query will be called, initializing the row in the database, and then use something like this: WHEN OBJECT ADDED,CHANGED STORE foo,bar,baz USING UpdateMethod(widget_id=self.id, foo_field=self.foo, wbar=self.bar) To update the data at transaction commit time. Voila. No need to make any custom attribute providers just to do this. Just to clarify the event sequence that should take place: 1. newItem() is called, which fires an _objectCreating() event 1.1. The SkinScript INITIALIZE OBJECT statement is triggered by the _objectCreating() event, and calls myInsertQuery() to insert a row in the database, with default values for everything but the primary key. 1.2. newItem() fires an _objectAdding() event, which does nothing except flag the object as "AddedStatus" and pass the event back to the DataManager (Rack). 1.3. The Rack passes the _objectAdding() event to all appropriately registered providers. The WHEN OBJECT ADDED,CHANGED statement is such a provider, so it receives the message and notes that the DataSkin was added, but does not act on it yet. Instead, it registers a proxy for itself with the Zope transaction object so that it will be notified of transaction commit. 2. newItem() returns a new DataSkin to your application, bearing the contents set up by the INITIALIZE OBJECT WITH statement. 3. Your application calls manage_changeProperties, to change an attribute. 3.1. The DataSkin fires an _objectChanging() event, which flags the object as "ChangedStatus", and the event is propagated to all registered providers in the Rack. (Such as the WHEN OBJECT statement) 3.2. The WHEN OBJECT statement ignores the _objectChanging() event, because from its point of view the object is in AddedStatus. 3.3. The DataSkin calls
Re: [Zope-dev] ZPatterns AttributeProvider question
At 08:29 PM 4/22/01 +0200, Christian Scholz wrote: Hi! A little update.. Actually I was mistaken and SetAttributeFor() is called. Just _objectChanged() is not called in that case.. and thus my attributes are not stored to the database. When an object is newly added, only _objectAdded() is called. _objectAdded(), _objectChanged(), and _objectDeleted() are mutually exclusive within a given transaction. That is, only one of them occurs in a given transaction. See more below. Maybe some more code will help (just the important pieces): def _objectAdded(self,client): """ store cached data in database """ ... here we do an sql query to insert things in database ... def _objectChanged(self,client): """ store cached data in database """ ... here we do an sql query to update things in database ... def _objectAdding(self,client, _tmap={ None:AddedStatus, DeletedStatus:ChangedStatus, ChangedStatus:AddedStatus } ): t = client._getTokenFor(self) s = t.status t.status = _tmap.get(s,s) # we need to do a commit here in order to store the record into the database! # and we need to have it stored as an AttributeFor() of the primary key will # return None otherwise (as this also just makes a query). client.commitSubtransaction() This is broken. Don't do this! commitSubtransaction() is an application-level operation. Only. If you have to use it inside of provider-level code or code called from SkinScript, chances are that you are doing something horribly wrong. You run the risk of causing a recursive commit operation in the Zope transaction machinery. Don't do this! def _SetAttributeFor(self,client,name,value): """Set the attribute and return true if successful""" # attribs stores the attributes we care about if name in self._attribs.keys(): client._getCache()[name]=value client.__dict__[name]=value; client._p_changed = 1 return 1 return None This also looks broken to me. Why are you changing both the cache and the persistent state? There's no reason to do both. So _objectChanging() is not overridden, the rest I have ommitted.. So as you also can see I already do a subtransaction commit but it does not seem to help for this problem.. I think you're seriously over-engineering this. I don't see anything that you're doing here that couldn't be done more easily with SkinScript statements. If all you want to do is store the data in an SQL database, a few SkinScript triggers would suffice. Now, if you're trying to get a row to be inserted in an SQL database at the actual time of the newItem() call, there is a trick you can use to do that from SkinScript also. Do this: INITIALIZE OBJECT WITH someAttr1=default1, someAttr2=default2,...,dummyAttributeName=myInsertQuery(primaryKey=self.id) Where myInsertQuery() is an SQL insert query that takes primaryKey as a parameter, and dummyAttributeName is some attribute name you don't care about. You should also set any default values for fields that will be inserted. Your insert query will be called, initializing the row in the database, and then use something like this: WHEN OBJECT ADDED,CHANGED STORE foo,bar,baz USING UpdateMethod(widget_id=self.id, foo_field=self.foo, wbar=self.bar) To update the data at transaction commit time. Voila. No need to make any custom attribute providers just to do this. Just to clarify the event sequence that should take place: 1. newItem() is called, which fires an _objectCreating() event 1.1. The SkinScript INITIALIZE OBJECT statement is triggered by the _objectCreating() event, and calls myInsertQuery() to insert a row in the database, with default values for everything but the primary key. 1.2. newItem() fires an _objectAdding() event, which does nothing except flag the object as "AddedStatus" and pass the event back to the DataManager (Rack). 1.3. The Rack passes the _objectAdding() event to all appropriately registered providers. The WHEN OBJECT ADDED,CHANGED statement is such a provider, so it receives the message and notes that the DataSkin was added, but does not act on it yet. Instead, it registers a proxy for itself with the Zope transaction object so that it will be notified of transaction commit. 2. newItem() returns a new DataSkin to your application, bearing the contents set up by the INITIALIZE OBJECT WITH statement. 3. Your application calls manage_changeProperties, to change an attribute. 3.1. The DataSkin fires an _objectChanging() event, which flags the object as "ChangedStatus", and the event is propagated to all registered providers in the Rack. (Such as the WHEN OBJECT statement) 3.2. The WHEN OBJECT statement ignores the _objectChanging() event, because from its point of view the object is in AddedStatus. 3.3. The DataSkin calls
Re: [Zope-dev] ZPatterns AttributeProvider question
At 08:18 PM 4/21/01 +0200, Christian Scholz wrote: Hi! Good evening everybody! I have some question regarding attribute and agent programming for ZPatterns. I have some provider which is registered for the "handlers" and "attributes" methods and some attributes. My problem is when trying to create a new object and directly editing it, e.g. obj=newItem() obj.propertysheets.data.manage_changeProperties(foobar=13) the propertysheet is defined and my provider is also registered for handling the property "foobar". Unfortunately my SetAttributeFor() method is never called. Have you defined a namesForRegistration method in your provider? Yes, as said above it registers for handlers and attributes. Also _objectChanged and _SetAttributeFor() etc. are called. They're just not called directly after creating the object (when being in the same request that is). _objectChanged() is a transaction-commit message. You'll only get it when the (sub)transaction commits. You'll receive _objectChanging() just *before* the object changes. As for _SetAttributeFor(), it should be called at the time manage_changeProperties executes, not at object creation. Are you sure that you have it properly named and that it isn't still being defined by one of your ancestor classes instead? The "AttributeProvider" and "GTMixin" base classes in ZPatterns implement _SetAttributeFor() by simply noting the change for later. If you don't override this behavior, your class won't see _SetAttributFor() itself. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] SkinScript Questions
At 10:59 PM 4/1/01 -0700, Michael R. Bernstein wrote: 1) Are there any naming conventions for SkinScripts? Not that I'm aware of. I think Ty names all of his methods "SkinScript", but then, he tends to name all his working/temporary files "x", so what does he know? ;) 2) Is there any reason (other than factoring) to split SkinScripts up, or is putting all your declarations in one SkinScript ok? The compiler creates a seperate attribute provider or agent for each declaration anyway, so there's no reason not to put them all in one if you don't need to interleave non-SkinScript providers/agents into the priority order. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns Image Archive Project
At 01:45 PM 4/1/01 -0700, Michael R. Bernstein wrote: It seems as though the manage_upload method is supposed to hand off the image data to RenderingKinds, which in turn either replaces the image data in existing Renderings, or creates new ones, by iterating through the rows in the TinyTable. [shudder]. No, not at *all*. The calling pattern goes like this: anArchiveImage.upload: for kind in RenderingKinds.getKindsFor(self): Renderings.setRenderingFor(self,kind,data) The ArchiveImage is responsible for knowing the image data. The RenderingKinds specialist is responsible for knowing what renderings should be made for an ArchiveImage. The Renderings specialist is responsible for creating and storing a rendering, given an image and a kind of rendering to be made. However, it may ask the kind object for dimensions or other assistance in actually creating the rendering. Don't think "iterating through rows in the TinyTable". Outside RenderingKinds, nobody knows there's a TinyTable. *You* don't know there's a TinyTable, because the application integrator might decide to do it with a table in an SQL database or a ZODB folder. Don't think "RenderingKinds replaces the image data in existing Renderings", because that's "meddleware" - objects meddling in each others' business. Renderings is responsible for renderings. RenderingKinds is only responsible for knowing about *kinds*. This is probably the hardest part of ZPatterns design for people to learn. Ironically, it's nothing more than the most fundamental of O-O design principles. Everybody thinks they know O-O, incredibly few do. I was doing O-O for almost *fifteen years* before I realized I wasn't even close to doing it right at this level of design! In turn, are RenderingKinds *also* responsible for returning the appropriate Rendering based on a 'size' attribute? No. RenderingKinds are responsible only for knowing about *kinds*, not the details of a particular image. Thus, it makes sense for RenderingKinds to implement rules about what renderings an image *should* have, but the ones it *does* have are the domain of the image itself (but delegated to the Renderings specialist for actual implementation). are ArchiveImages supposed to access Renderings directly to find whatever Renderings exist for them? Which SPecialist now has a getRenderingFor(archiveImage,imageKind) method? Renderings. ArchiveImage should have getRendering(imageKind) which then calls Renderings.getRenderingFor(self,imageKind). I can also see a problem with the following situation: after several Archive images are created along with their appropriate Renderings, the configuration information in the TinyTable is changed, with new sizes added, and existing sizes deleted or edited. I would not expect the entire image database to be resized and new sizes created automatically, so the data in the Renderings Specialist would be out of sync with the sizing meta-data, with Renderings possibly 'orphaned', and other Renderings 'missing' I *think* that these problems can be avoided, if the Renderings Specialist is still responsible for reporting what Renderings an ArchiveImage *has* (and possibly what their dimensions are), and the RenderingKinds Specialist is responsible for removing orphan renderings and creating missing Renderings when the Image is either uploaded again or 'refreshed'. How would you reccomend handling this? That depends on what the requirements are. If you need to implement this, then the sensible place to do it is probably in the RenderingKind objects and RenderingKinds specialist. That is, adding a RenderingKind might include the option to go through and create the missing renderings, and deleting or altering one might similarly prompt for updates. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns Image Archive Project
At 08:59 PM 3/30/01 -0800, Michael R. Bernstein wrote: "Phillip J. Eby" wrote: Aha. I think I understand what you're doing now. You have an "Image" and you have a "Rendering". Two classes, different behaviors. I'm assuming that originals and thumbnails and whatever other renderings exist have no real behavioral differences and can be implemented with the same class and storage characteristics. The terminology I'm using is ArchiveImage (for the 'Image' class) and RackImage (for the 'Rendering' class). I'd recommend a name change for RackImage, at least at the Specialist level. If you don't like Renderings, then maybe RenderedImages, ActualImages, or some such. Specialist names should reflect the *purpose* of a thing in the application rather than the nature of the thing itself. I think that different sizes would have the same behavioural characteristics (simply an image file, really), but am less sure about storage. My application will attempt to store all the renderings in the ZODB, but if I want this to be reusable, I have to assume that someone (including me) might want to store the image data on the FS instead. If it's going to be stored on the FS, it would be natural to dump different sizes into separate directories, or even separate partitions. Two years from now, this web application could contain around 300 Gb of images (current prices on that much storage are about $1,000 for ten 30 Gb hard-drives, so I'm not too worried on that score). This can still be accomplished with a single specialist, if your 'id' format contains the necessary information to distinguish between image sizes/types. If a user of your framework wants to seperate the storage, they can create more than one rack and have the specialist distinguish between them using the contents of the 'id'. It's best to keep implementation simple in the reference implementation of a framework. That's what I meant, sorry. The RackImages need to appear to be attributes of the ZClass, and I'll use SkinScripts to accomplish that. That's really only practical if you have a fixed set of rendering types and names, but it'll work for retrieval. It won't really help you with creation and assignment, though. I'd suggest specialized methods on Image which delegate to the Renderings specialist. I was thinking of a manage_upload method on the ArchiveImage, that iterated through a list of sizes and used an external method that imports PIL to resize the image data, then passes the resized image data into the RackImage manage_upload method. Does that seem reasonable? It seems to me that sizing renderings should be the responsibility of the Renderings specialist. That is, the ArchiveImage upload method would look something like this: for imageKind in ('fullsize','thumbnail'): Renderings.setRenderingFor(self,imageKind,imageData) The setRenderingFor method would take the ArchiveImage's id, tack the imagekind onto it, and either retrieve the current image or create a new one, then re-size the image according to your rules for what size fullsize or thumbnail is, and pass it to the current or new rendered image object. (A counterpart method, getRenderingFor(archiveImage,imageKind) would do a similar id transformation to retrieve a rendering when called by the ArchiveImage's getRendering() method.) Of course, this means that the Renderings specialist has to know what sizes different size names mean, and that ArchiveImages have to know the possible sizes. Such knowledge being spread across two specialists means there's a specialist missing: RenderingKinds. This may be a sub-specialist of Renderings, or a peer of Renderings within ArchiveImages. If a sub-specialist of Renderings, Renderings must expose a method to retrieve the sizes, and the upload method above would look like this instead: for imageKind in Renderings.getRenderingKindsFor(self): Renderings.setRenderingFor(self,imageKind,imageData) Although, it may be in your framework that ArchiveImages are responsible for knowing which kinds of renderings they should have, and the RenderingKinds specialist will simply deal with implementation details such as how each kind is sized and which rack they're stored in within the Renderings specialist. By the way, RenderingKinds is a sort of specialist that hasn't been discussed much outside of the apps Ty and I work with - the "constant" Specialist, one which contains application configuration or metadata rather than "content". Oftentimes it's handy to simply base a Specialist on a TinyTable or similar product in order to set up configuration of constant items like RenderingKinds. Consider the TinyTable data below: Columns: name:string scaling:float width:int height:int rackname:string "fullsize",1.0,0,0,"bigimages" "halfsize",0.5,0,0,"bigimages" "thumbnail",0.0,64,64,"thumbnails" The Re
Re: [Zope-dev] (ZPatterns) Speeding up Skinscripts
At 01:57 PM 3/29/01 -0800, John Eikenberry wrote: We have a fairly large and complex app framework built on ZPatterns. It uses MySQL for storage and the standard Specialist/Rack/DataSkin setup with skinscripts for attributes and triggers. We've found that the speed of getItem is a bit slower than we need. For instance retrieving 200 dataskins takes about 8 seconds on a P2-300. After profiling and digging around I think I've found the primary bottleneck. Its the running of eval() on the skinscript's python expression (stored in the Compute class as _fromex and Triggers as callexpr). Congratulations, you're the first person (that I know of, anyway) to hit a wall here. However, I think you may be barking up the wrong tree on your profiling. See below. The optimization I've been looking at is changing the code from storing a string and eval()ing the string to using compile() at save time and exec() when evaluated. Profiling these 2 ways in little test programs seems to indicate about a 2.5x speedup. Not huge, but combined with better hardware should be enough. But I'm curious why this avenue wasn't taken to begin with. Seems like the way to do it to me. Am I missing something? Yes, as your later message mentions, ZPatterns already does that caching. I think what's more likely to be taking up time is either: 1) Zope security checks on the expressions, or 2) DTML execution of your SQL queries Or perhaps something else altogether. First a few comments on the above, then I'll ask some more probing questions regarding your setup. SkinScript expressions execute using Zope security checking. If you're using a "WITH QUERY SQLmethod() COMPUTE attributelist" statement, security checks are applied to both the query expression and to every name referenced in 'attributelist'. So the longer the attribute list, the slower the execution. Although, now that I think of it, eval() is not used if you use a pure attribute name list like "name1,name2,name3", so the problem probably isn't on the attribute list side. This makes it much less likely that the security machinery is to blame (unless you have a very slow user folder which also doesn't cache well, and you haven't given your SkinScript proxy roles to shortcut the security checks.) Now, for your SQL query... is it by any chance dynamically generated in a complex way? I mean, more complex than an sqlvar or two? Keep in mind that when Zope caches SQL queries it does it by generating the text of the query and using it as a cache key. That means any DTML in your query will be executed each time. It'd have to be pretty complex, or else there'd need to be lots of slow security lookups, to get the kind of poor performance you're seeing, though. Okay. Here are a few things to look at in your app: 1. If you're not using LoginManager as your user folder, and maybe even if you are, your SkinScripts should have proxy roles. Proxy roles can slash the overhead of performing security checks, and are usually appropriate for SkinScripts because SkinScript is "internal" to the object and Zope security will apply to the results of the SkinScripts as well. 2. Why are you retrieving 200 dataskins? Is this all in one transaction? If so, you may have a design issue. Multi-object operations should generally be implemented as domain-specific methods on the Specialist, so they can be implementation-specific (and thereby take advantage of speedups like a ZCatalog index or specialized SQL queries). In other words, you probably want to iterate directly over a 200-row query result from an SQLMethod, rather than retrieiving 200 DataSkins. (You're accessing over 10 times as many DataSkins in one transaction as our most complex ZPatterns application touches in its most complex type of transaction, which involves about 4 or 5 Specialists at once!) Pretty much, if you're displaying a list or report or doing some kind of summary analysis or mass update, it belongs in an implementation-specific method in the Specialist. 3. If you *really* need 200 dataskins in one transaction, and the overhead is *really* in SkinScript, then you can bypass the overhead by writing an AttributeProvider of your own in Python. I'm guessing, however, that SkinScript per se is not the source of the slowdown, and you need to look more closely at the things the SkinScript is calling. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] LoginManager question
At 12:19 PM 3/27/01 +0200, Bertrand Croq wrote: Hi, I am currently using LoginManager to authenticate users from a MySQL database. I followed the tutorials and it works quite well; but there are other data associated with users in the database that I would like to use in Zope. I have found a solution but I think it is quite complicated: - first, I added SQL_id_user (ZSQL-method) in the acl_users: select id_user from user where dtml-sqltest username column=user_name type=string - then, I added id_user (DTML-method) in the acl_users: dtml-in expr="SQL_id_user(username=username)" dtml-return id_user /dtml-in - now, when I want to get the id_user value associated with the current user, I need to do: dtml-with REQUEST dtml-var expr = "AUTHENTICATED_USER.id_user( AUTHENTICATED_USER, username=AUTHENTICATED_USER )" /dtml-with Isn't there an easier way to get the id_user value? Yes, there is. Get rid of the "id_user" DTML method and add the following to a SkinScript method inside your UserSource: WITH QUERY SQL_id_user(username=self.id) COMPUTE id_user You should then be able to do "AUTHENTICATED_USER.id_user" to retrieve the attribute. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] FYI: TransWarp talk slides posted
HTML Version (frames JavaScript required): http://telecommunity.com/TransWarp/IPC9Talk.htm PowerPoint Version: http://telecommunity.com/TransWarp/IPC9Talk.ppt ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: External Attribute Provider question
At 07:48 PM 3/11/01 +, Steve Alexander wrote: Is there a good reason that ExternalAttributeProvider sets up a dictionary to put its attributes into, rather than a PersistentMapping? It's mainly to avoid a proliferation of persistent objects, based on the assumption that if you're using a PEAP, you probably don't have that much else in the PersistentMapping. If an External Attribute Provider instead set up a new PersistentMapping in its slot, only that PersistentMapping would change in the ZODB on updates. Do you think this is a reasonable change for the External Attribute Provider class? Or, should I write my own provider, derived from External Attribute Provider, that uses a PersistentMapping instead of a dict? I would suggest creating your own provider(s). ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] State of ZPatterns
At 10:16 AM 3/11/01 +1100, Itai Tavor wrote: I'm wondering where TransWarp leaves ZPatterns users. Until a couple of weeks ago ZPatterns was the best thing to happen in the Zope world since, well, Zope. Now it's described as a 'hack', Those things aren't mutually exclusive, you know. :) demoted into 'maintenance only' mode, and superceded by something that is described as being as much better than ZPatterns as ZPatterns was better than standard Zope development. It hasn't been superceded. TransWarp has several layers of functionality planned; only one of those layers has been released to date. (By the way, I also don't recall ever saying even that TransWarp was "better" than ZPatterns, let alone that it was some giant leap forward. I did say that it expanded further on the model which was the basis for ZPatterns, however.) As for "maintenance only", ZPatterns hasn't had any changes in months, except for patches provided by its users. That's largely because it hasn't needed any. There's not much you can *add* to ZPatterns, without a major upheaval. I figure, let the major upheaval be directed at making something completely different, rather than have major reworking to make something only marginally better. So what do we do now? Wrap up current ZPatterns work, writing it off as a loss for future reuse? Or can we count on 'maintenance only' being sufficient to support continued reused of ZPatterns efforts long enough to justify the original development effort? Someone asked a similar question of me at the conference. I told them that if I needed to develop a web-based application today, I would use ZPatterns with Zope. It works, it's stable, it gets the job done. Also, recall that the RIPP model concept was introduced to the Zope community last January, and it was many months before ZPatterns' first release, then many more before it was stable enough to be ready for production use. Expect the same to be true of TransWarp. The tools released so far are rock solid, but there isn't anywhere near enough there to compete with ZPatterns yet. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Designing ZPatterns/Python-product-based, reusable applications - take 2
At 10:24 AM 3/11/01 +1100, Itai Tavor wrote: Then I need Specialists to manage collections of PD classes. I think that these would also benefit from being product-based, so I subclass Specialist to create a manager for each role in the application. Now, since an existing application might be expanded, the Specialists all need factory methods and will all show up in Zope's Add New Object menu. Or you may want to just create one factory method that creates an entire family of related Specialists. Specialists do support TTW overriding of their methods, if you set up the methods properly in your Python code. (I forget how this works, though, you'll probably need to check the source code.) - Many of the classes will also have web user UI, and since this has to be designed to fit the design of the web site in which the application is used, the UI methods will have to be located where designers can modify them - in the ZODB. For the Specialists, I can install a default set of UI methods when an instance of the Specialist is installed. But where do I store PD class UI methods? EMarket's solution is to store them in the Specialist, but this not only breaks O-O rules, it can also be very ugly. Say I have a Specialist managing 3 PD classes. Instead of an index_html method for each class, I'll need class1index_html, class2index_html, class3index_html in the Specialist. And each class would have to define: def index_html(self, REQUEST, RESPONSE, **kw): return self.class1index_html(REQUEST, RESPONSE, kw) This is unacceptably ugly. But the only other thing I can think of doing is creating a ZClass for each PD class and store the UI methods there. But that's also pretty unacceptable. Is there a better solution? Yes. Use "class_default_for_X" methods. (e.g. "def class_default_for_index_html"). This will make them capable of being overridden with a Class Extender in the Rack or Specialist. Next, I need object connections - these are created using SkinScripts. And as far as I can tell, I can't manage SkinScript in the product - they have to be in the ZODB. Which is ok in O-O land as they're not strictly part of the PD classes, but this means that PD classes don't actually work at all until someone comes and fills in the SkinScripts - so the class actually misses a lot of the code it requires to function. Also, it means SkinScript code can't be reused with the rest of the application's components (except by cutting and pasting code pieces from an existing application). Your factory code can set this up, although I admit it's ugly. Finally, I need to wrap the whole thing up as an application. So I create a Folderish class which installs instances of all Specialists, and add application-wide utility methods. Or do I simply place all Specialists in a Folder? Placing them in a folder would be fine. Actually, it would suffice simply to install a meta type which creates all the Specialists in the selected folder. Note that Zope does not require that a meta type correspond to some physical class, or that an add operation result in a single object being added to a container; you can add as many objects as you want in the same operation. Now, about reuse. O-O reuse, as far as I understand it, takes place at the class level. So how do I start a new application? Do I subclass its main container class and and my own init method that adds any added or subclassed Specialists I use? Or do I create my own application class and import PD classes from the old application? Do I copy the old classes into my new product, or do I import them from the old product, which then would require that the old product is kept on the server, even if the application that product defines isn't used on this server? If I understand you correctly, then you'd just instantiate another instance of the application metatype, and then customize whatever needed to be customized. And, as mentioned above, how do I reuse SkinScripts, Rack methods and SQL methods? Copy and paste? It seems funny that if I create a new instance of the product, I don't get a new copy of a working application... If your factory methods set this stuff up, then you're okay. On the other hand, considering that ZPatterns is now being superceded before it even had a chance to mature, maybe nobody cares to hear about it anymore :-( But more on that in a separate post. IMHO, ZPatterns is actually pretty mature - in terms of its code. By that I mean, it has gone about as far in capabilities as its internal architecture will allow. There are many minor improvements that could be made, but they would be costly compared to their benefit. I would rather invest the effort in something that will produce a greater gain for me and the rest of the community. TransWarp will be much better for filesystem-based, Python products than ZPatterns, which is almost 100% through-the-web focused. The key phrase, though, is
Re: [Zope-dev] TransWarp preview release (AOP tools only)
At 10:52 AM 3/6/01 -0500, Shane Hathaway wrote: "Phillip J. Eby" wrote: There's actually a simpler way. Aspect objects can be pickled as long as all the objects in them can be pickled. Which means that as long as all their methods are Zope objects, and all the nested classes are also Aspect objects, you can save an aspect into the ZODB, and load it at a future time. Further, since adding aspects together makes new aspects, you can save the combined aspects, so you only have to perform one call to transform the aspect into a family of classes. That still means some load-time complexity, however. Perhaps... but as I see it, pickling the aspect weaving information into each object makes it harder to vary the aspect weaving after objects have been created. That's not what I said. *Aspect objects* can be pickled. You're talking about *instances* of *classes* created by weaving the aspects, and that's a whole different kettle of fish. Check out the "AOPTutorial" in the Wiki, which sorts out the differences between the three. I would want to be able to create a portal, add some content, then change the aspects that apply to the content after it has been created. Of course, just as you can currently upgrade a class that has instances in the ZODB. Regenerating the class from different aspects would have exactly the same pros and cons as upgrading a .py module containing a class that's used in the ZODB. I'm also planning outside the ZODB. The goal is to design apps using pure and simple ZODB and not be required to do anything special to make it work later with other forms of storage. Other databases will not be able to store aspect information. Again, this is a confusion of instance and class. Aspect information is *not* per-instance - heck, even *classes* in TW don't know what Aspects they were woven from. The aspects are like flour and eggs that go into making a cake (class or set of classes). Once it's baked, the ingredients are no longer visible. :) That's actually the kind of functionality we have now, but we're using subobjects rather than tabs and we achieve many of the things AOP would give us through simple delegation. You should check out the CMF as soon as the beta is released. One of the interesting things I learned at the Python conference this year (through some of the papers, like the Virtual Worlds and Thin Client projects) was where the best trade-offs between a delegation approach and an AOP-style approach are. The spectrum seems to be that if your instances need to make lots of different choices, or if they need to be able to add and remove aspects on an ongoing basis, then some type of delegation is probably the way to go. If your choices are more about *configuration* that applies to *multiple classes*, then aspects are probably more appropriate. By the way, I have never tried to promote AOP as even being relevant to the CMF. :) AOP is mostly about *reuse*, so any single run-time environment (such as CMF or even Zope as a whole) will not see much benefit that you can't get through delegation. ZPatterns, for another example, is one gigantic web of delegation internally. AOP is of more relevance to the developer who has a piece of code they would like to use for the CMF, *and* for a command line tool, *and* a testing tool, *and* And thus they need to be able to assemble their code into a variety of useful configurations. After Michel's presentation the other day, I understand a lot better how Zope will address this issue with "adapters", and that will help *a lot* with a lot of things. However, people may also have other environments besides Zope to use their code in, or other configuration choices to be addressed that are not exposed to Zope (such as the database schema), and having AOP available will presumably be helpful to them. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] TransWarp preview release (AOP tools only)
At 03:53 PM 3/2/01 -0500, R. David Murray wrote: On Fri, 2 Mar 2001, Shane Hathaway wrote: "Phillip J. Eby" wrote: One reason I've been racing like mad to get the preview release out is so that, after seeing the usefulness of TW for the Zope 3 component architecture, y'all might be interested in considering implementations for module persistence besides proxying. :) IMHO, a "rollback importer" approach ala unittest might be better suited for TW-ish components, and have fewer weird side effects for persistent modules generally. I don't like unittest's mechanism for *doing* the rollback, and Zope would need a thread-specific version of sys.modules, as well as a mechanism to purge the cache of any objects which were loaded after any of the purged modules, but I think the basic idea is sound. Hmm. I'm afraid I don't see how TW helps with module persistence. I could be wrong, but I didn't read what Phillip wrote as saying he was suggesting TransWarp as a player in the Module Persistence implementation, but rather that he wanted people to see the value of TransWarp first hand so that they would want to make sure that Module Persistence and TransWarp could play together Yes, that's exactly what I meant. :) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] TransWarp preview release (AOP tools only)
At 12:39 PM 3/2/01 -0500, Shane Hathaway wrote: We've been separating concerns in the PTK/CMF for the last year now. We've been moving as many responsibilities of the content objects as possible into per-portal "service" objects. The services provide user interface, discussion capability, workflow integration, etc. In doing so, IMHO we've lost a little simplicity. In the current way of doing things, content objects should not know about their own workflow, instead they should be associated with a portal-specific type object and the type object is associated with a set of workflows. And the user interface depends heavily on acquisition now. Now, let's say that instead everything were reintegrated into the content objects using aspects. To retain flexibility, different portals would weave the content objects in different ways because of variations in user interface, workflow, etc. Would this be a good application for TW? Absolutely. And as you've probably guessed, you can insert the implementations at whatever level of the class hierarchy - insert global policies into a base ContentObject, override them at a more detailed level, whatever. This could be achieved by generating a new Python module for each portal instance, but that would mean sys.modules would have to be pre-loaded with the information about each portal instance and that's not the ZODB way. It would be better to create a new class loader that can weave a new class on the fly based on persisted component metadata. Note that class loading is currently quite simple; see lib/python/Zope/ClassLoader.py (sp?). It could bear some complexity. :-) There's actually a simpler way. Aspect objects can be pickled as long as all the objects in them can be pickled. Which means that as long as all their methods are Zope objects, and all the nested classes are also Aspect objects, you can save an aspect into the ZODB, and load it at a future time. Further, since adding aspects together makes new aspects, you can save the combined aspects, so you only have to perform one call to transform the aspect into a family of classes. That still means some load-time complexity, however. I haven't given a whole lot of though to through-the-web use of TransWarp's AOP stuff; I've mainly thought of it as being a "Product"-level tool. But I imagine you could perhaps make some sort of "ZAspects" (ala ZClasses) that wrap through-the-webness onto aspects. (Of course, if you can do through-the-web modules, no special magic is required.) Actually, any Python class or ExtensionClass can be used as part of a TW aspect, so you could in fact use ZClasses as part of an aspect right now, if you wanted to. Handling the class hierarchy of a ZClass could be tricky, though, if you wanted to be able to deal with them as a class family. ZClasses have so many parent classes by default. It would be interesting if you could take an arbitrary Zope service object (like a portal), and go to its "Aspects" tab, and add or remove aspects to be woven with its class family. But I suspect it will be a long time before I'll have a need for that personally or professionally, as I am focused primarily on TransWarp as a CASE tool and Python application toolkit at present. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] TransWarp preview release (AOP tools only)
At 09:37 AM 3/1/01 -0500, Shane Hathaway wrote: This looks very interesting, Phillip. I haven't downloaded the package yet, but I read the wiki and it finally made sense once I understood the goal (I think): TW lets you set up the class inheritance hierarchy at runtime. In normal OO methodology, you can only extend classes. With TW, you can also slip your own version of a base class into a class hierarchy (without actually modifying the Python class hierarchy, of course.) That's a good way of describing the *function* of the AOP part of TransWarp. The goal is not so much to set up the inheritance hierarchy at runtime, as to allow you to configure various versions of the same component, and to write seperately-managed "aspects" for different areas of concern. The targeted time is not really "runtime" so much as "build time". Runtime is a side-effect of how it's done, and it can be useful for things like selecting an OS-specific or other environment-sensitive aspect at application startup. But the main goals of the AOP portion are being able to instantiate customized versions of "third-party" components, and to be able to mix-and-match implementations for different areas of concern. For example, wxPython vs. Tkinter vs. Win32, SQL vs LDAP vs ZODB, and so on. TransWarp in the larger picture will also deal with generative programming; the UML-driven parts will generate aspects that contain structural information (inheritance, associations, aggregations, attributes, etc.) that can then be merged with non-structural aspects. The ability to "set up the class inheritance hierarchy at runtime" provided by the AOP tools will then allow you to define what an "attribute" is, and give it publishability, security permissions, or a GUI rendering. There is actually code in the preview release to do this structural generation for the UML metamodel (if loaded from MMX format), and it's even rudimentarily tested (one unit test that just makes sure it doesn't blow up altogether) but the "StructuralModel" aspects that implement attributes and associations are currently broken, not yet updated for the true AOP model. Earlier versions of TransWarp did class generation as an integral part of the GP system, not as a GP+AOP system, and I'm still adapting a lot of stuff to take advantage of AOP and to use a cleaner metadata mechanism. What is your vision of integrating AOP into a persistent object system? Would one drop in an object that modifies the class loading mechanism so that the classes come from a TW component rather than Python modules? Not necessary. If you dig into the TransWarpFAQ page in the Wiki, you'll see a question that explains how to make TW-generated classes work with pickle and cPickle. It just requires one additional argument at aspect-weaving time, to specify the module which the generated classes should be registered with. This means that TW's AOP features are functional right now, today, with ZODB. (As long as the classes are generated in good ol' Python module files.) Now, as to whether TW will be fully compatible with Zope 3 "persistent modules", that's a different question. In the conversation I had with Jim in January, based on his description of the module refresh mechanism and of import proxies, I would say that TW-generated classes would not properly refresh when a persistent module that they were dependent on changed. (Because TW will generate new class objects from the imported classes rather than referencing them via the proxy.) But that's based on a very early notion of how Z3 persistent modules would work. One reason I've been racing like mad to get the preview release out is so that, after seeing the usefulness of TW for the Zope 3 component architecture, y'all might be interested in considering implementations for module persistence besides proxying. :) IMHO, a "rollback importer" approach ala unittest might be better suited for TW-ish components, and have fewer weird side effects for persistent modules generally. I don't like unittest's mechanism for *doing* the rollback, and Zope would need a thread-specific version of sys.modules, as well as a mechanism to purge the cache of any objects which were loaded after any of the purged modules, but I think the basic idea is sound. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns goes crazy after ZClass change
At 10:29 AM 2/21/01 +1100, Itai Tavor wrote: I think I've severely misunderstood how Racks work. I thought persistent Racks just store properties, and then use the ZClass set in the Storage tab to wrap that data when providing it. Which means that I can change the class set for storage and all the objects in the Rack will be provided as the new class. But if changing the storage class doesn't change the object provided by the Rack, it means the actual ZClass instance is stored. Is this right? Yes... unless you use a Persistent External Attribute Provider, and set the "load attribute" so that the rack is virtual. The "store objects persistently" option stores the actual ZClass instances. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns and SQL
At 05:29 PM 2/19/01 +0100, Christian Scholz wrote: You need to use an attribute which the object has *if and only if* it exists in the database. If the class has the attribute defined, all instances exist, and you can't even load it with SkinScript because ZPatterns uses __getattr__ to redefine attributes, and that doesn't work if the attribute already exists in the class. So I shouldn't define it inside the ZClass propertysheet? Do I understand this right? (I remember having problems when using properties not defined in a sheet somewhere.. or am I mistaken completely somehow? ;-) You can't do this with a load attribute, because a default value will exist. The easiest way to deal with this is simply to have a seperate attribute name just for loading, or use an attribute that isn't on a property sheet. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns and SQL
At 05:50 PM 2/19/01 +0100, Christian Scholz wrote: (though I am still confused a little, as I tried one non-existing attribute and it didn't work. But this one also was not defined inside the SkinScript and the database). As I said, the attribute must exist if and only if the row is in the database. Thus, it must *not* exist on the propertysheet, and it *must* exist in your SkinScript. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Waaagh! Python Script won't allow __setitem__
At 05:25 PM 2/19/01 +, Chris Withers wrote: Hmmm arguably a bug in ExtensionClass, but not one I'm gonna try and fix ;-) It's not a bug, it's a feature -- the feature that is the reason for the very existence of ExtensionClasses in the first place: merging of the notion of type and class. Of course, type() could always be replaced with a safe_type function that checked whether the type() was an ExtensionClass and returned something inert. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Python Product as DataSkin
At 12:51 PM 2/18/01 -0800, Michael R. Bernstein wrote: I have an existing Python Product that I would like to use as a DataSkin in a Rack. What do I need to change (import/subclass) in order to use it in this way? from ZPatterns.DataSkins import DataSkin class MyClass(DataSkin,...all other bases...): ... ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Python Product as DataSkin
At 09:49 PM 2/18/01 -0800, Michael R. Bernstein wrote: Ok, assuming that the 'normal' instantiation is either solved or a non-issue, do I need to do anything special to get the newItem() method to call my products manage_add method? newItem() will not do that. A Rack's newItem() method always takes only an 'id' method. You'll need a method on the object itself that can be given anything else you want to give it, which you'll call from a method you create on the specialist, e.g. a "myAdd" method that takes all four parameters and then does something like: newObject = self.newItem(id) newObject.setup(extraParm1,extraParm2,...) return newObject ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Python Product as DataSkin
At 10:47 PM 2/18/01 -0800, Michael R. Bernstein wrote: Hmm. So I need to refactor the 'manage_add' method inside the python product into two methods, 'manage_add' which would be used by the 'normal' object creation process and that would also call a second 'setup' method which could be called by the specialists 'myadd' method directly, bypassing the 'manage_add' method entirely. Is that correct? Pretty much Is there anything else I would need to change? Anything that carries any assumptions about the normal Zope management creation process. For example, manage_afterAdd is only called when a DataSkin is added to a Folder, not a Rack. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Q: Specialists, Racks, and ZCatalogs?
At 08:38 AM 2/4/01 -0800, Michael Bernstein wrote: On that subject, does anyone know why SkinScripts don't support cut-n-paste or copy-n-paste? 'cause I never thought of implementing it, probably because I've never yet needed to move a SkinScript. Patches cheerfully accepted. :) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Specialist/Rack scalability
At 07:12 PM 1/21/01 +, Steve Alexander wrote: So, storing things in a Rack happens in a number of stages: Your application interacts with the Rack The Rack (perhaps) stores the object persistently in its BTree The BTree is a collection of persistent ZODB objects The ZODB objects are stored as Python Pickles in a FileStorage We can consider what the effect of storing 60 000 objects is at each of these interfaces. The Rack shouldn't have a problem with 60 000 objects. I doubt a BTree would have a problem. The ZODB might not like accessing many large objects during a single transaction, as all those objects need to be in memory at once. A FileStorage should have no problem reading 60 000 stored objects. However, if these objects are changing much, your Data.fs will grow fast. In any case, you may find undo and history screens take a long time to appear. However, if you are using a Rack, you have a lot of choice about where you put your data. You can put frequently changed aspects of your data on the filesystem, and the rest in FileStorage for example. Just to expand a little on the abov... Racks should scale at least as well, if not larger than a ZCatalog, given the same storage backing for the ZODB. This is because ZCatalog has to manage a minimum of one forward and reverse BTree for *each* index, plus another few BTrees for overall storage and housekeeping. Also, keyword and full text indexes store multiple BTree entries per object, so that's a factor as well. So don't worry about the Rack. If you're using a Rack, you can store the data anywhere, and you can index it in an RDBMS, LDAP directory, ZCatalog, or some combination thereof, using triggers to keep the data in sync. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] LoginManger: multiple LoginMethods
At 06:38 PM 1/7/01 -0800, John Eikenberry wrote: Anyways... I want to be able to support both cookie based auth and basic auth. With cookie based auth being the default unless they don't have cookies (either because they have them turned off, behind a proxy filter, etc), in which case they should use basic auth. The problem is I'm not sure how to get it to use something other than cookie based auth. The default setup tries to use cookie auth whether or not cookies are in use. Any tips on how to get this working? I know there is no great way of detecting cookies, besides setting one and testing for it. But even if I did this, how do I say I want basic auth if the test cookie isn't found. Doing a: raise "Unauthorized" or RESPONSE.setStatus(401) will tell the browser to pop up an authorization dialog. Note that if you do this, you won't be able to also display a login form for cookies. For all practical purposes, you need a seperate login page for cookies vs. basic auth. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] skinscript and URL traversal question
At 09:41 AM 1/19/01 -0500, Aaron Payne wrote: At 09:38 AM 1/19/01 -0500, Phillip J. Eby wrote: Thus, your SkinScript is running as anonymous, and probably doesn't have rights to access the SQL method. You might need to change the proxy roles setting on the SkinScript method so that when the SkinScript runs it always has appropriate roles to do what it needs to do. I gave the skinscript trigger a proxy role of manager. Actually, I gave all methods involved a proxy of manager. The same error was produced. What version of Zope are you using? Zope version: Zope 2.2.1 Platform: freebsd4 Hmm. You've got me, then. Have you tried taking the Python Method out of the mix and using the SQL method directly, like this: WITH QUERY searchBy_Name(name=self.id) Also, have you tried running Zope with logging ("STUPID_LOG_FILE") enabled? What gets added to the log when you try to access the object via bobo_traverse? ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
RE: [Zope-dev] Specialists and __bobo_traverse__
At 04:41 PM 1/17/01 +0200, Roch'e Compaan wrote: I don't have the slightest idea what you're trying to accomplish here - I probably missed the beginning of this thread. Do you want to change the way the specialist processes the string "dataskin1", or the way dataskin1 processes the URL component that comes next? Each requires a different approach. I want to process the way dataskin1 processes the URL component that comes next. Just to make sure I communicate some sense :) Okay, then your SkinScript *should* work, so long as your dataskins don't already inherit a __bobo_traverse__ method. If your DataSkin inherits from ObjectManager or any of its derivatives, for example, then it won't work. Of course, the bobo_traverse you're supplying has to be able to be bound to the DataSkin. Not all types of Zope "method" objects can do this binding correctly. ZPublisher will call the method with two arguments, but your method will (presumably) need three: one of which is "self" - the DataSkin itself. I'm pretty sure DTML methods *won't* work. "Python Methods" might. I don't know about external methods, python scripts, etc. If I was trying to solve your problem, I would just write a __bobo_traverse__ in a Python base for my class. If I needed it to be replaceable on the fly, I'd write it so that it looked for another attribute, maybe __skin_traverse__, and called it if it existed. But I'd have it pass three parameters, including self, so that I could use almost any kind of Zope method and make it work. Then if I needed to customize it I could use SkinScript or a Class Extender to add the method in. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Specialists and __bobo_traverse__
It sounds to me like you're trying to have SkinScript supply a bobo_traverse for the Specialist itself, and this you cannot do. (There are other ways to change a Specialist's bobo_traverse behavior, but SkinScript is not one of them.) The SkinScript you're doing is meaningful only if you want to go to specialist/skin1/something, in which case your traversal_method should be called to process "something". I don't have the slightest idea what you're trying to accomplish here - I probably missed the beginning of this thread. Do you want to change the way the specialist processes the string "dataskin1", or the way dataskin1 processes the URL component that comes next? Each requires a different approach. At 07:28 PM 1/16/01 +0200, Roch'e Compaan wrote: I'm still lost as to when __bobo_traverse__ is checked for object traversal and when not. I have very simple piece of SkinScript: WITH SELF COMPUTE __bobo_traverse__ = traversal_method. Looking at the traverse method in BaseRequest.py it looks to me as if an object is always checked if it has a __bobo_traverse__ method but this is not what is happening. If I manually type in a url, say path.to.specialist/dataskin1, where dataskin1 exists, my traversal_method is not called. When I type in path.to.specialist/dataskin2, where dataskin2 does not exist then my traversal_method is called. Noticing that the traversal_method is called when an object can not be found I tried path.to.specialist/dataskin1/dataskin2, where dataskin1 is in the specialist's rack but dataskin2 is in another specialist's rack and will therefor not be found. In this case my traversal_method was not called. If it was then I could retrieve it from the appropriate specialist. I hope the above is clear because I'm somewhat desperate at the moment. If I'm trying the impossible, a simple "forget about it" will also do. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: catching exceptions raised by triggers
At 12:49 AM 1/6/01 +, Steve Alexander wrote: WHEN OBJECT ADDED, CHANGED CALL self.ensure_conditions_hold() I write the ensure_conditions_hold method so that it returns None if everything is ok, but raises an exception if there is a problem with the new state of the object. That's all fine. However, I want to catch this exception in my application, and handle it in a friendly way. However, I've tried using dtml-try blocks and try: except: blocks from Python Scripts, and either way, I cannot catch the exception. It still causes Zope to return the standard_error_message screen. I can only speculate that this is all due to the way that triggers get executed at the end of transaction. I guess I'll have to validate the data twice if I want to provide helpful feedback to the user. How do I catch an error raised by a Trigger? What Ty and I usually do is raise user-friendly error messages (in HTML) to begin with, so there's no need to trap them in an except block; Zope's normal handling works okay then. This is the "as designed/intended" solution to your overall problem. (We often use dtml-raise for this, as it makes it easier to create a full-screen HTML error page.) But to answer the question you asked, you can do it by performing a subtransaction commit, wrapped in a try or dtml-try block. This will fire the triggers in a context where you can trap the exception. We suggest you only use this trick when you really need it, however, and in your situation as described I don't think you really need it. Even if "ensure_conditions_hold" can't be changed to raise friendly exceptions, you can always put a wrapper routine around it that catches and re-raises them. The key idea here is that it's perfectly okay to let an exception propagate to the user, if formatted properly. You probably *want* it to happen, to ensure that *everything* gets rolled back. Even if you do the subtransaction trick and trap the error, you still want to make sure the transaction as a whole aborts, since SQL (for example) might already have been sent to a database. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns; possible bug?
At 06:03 PM 1/4/01 +, Steve Alexander wrote: I think what is happening in the broken example is that when the zope security machinery asks for __roles__, name is also computed. The machinery must request __roles__ before changing anything. The behavior is as documented, though I'm not sure I'd call it "intended", exactly. :) You can fix this with either a seperate statement, as you've noticed, OR by placing the __roles__ computation *first* in the WITH SELF statement. This will ensure that it is already computed before the other items execute. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Objects with multiple parents and storage flexibility, ZPatterns?
At 05:15 PM 1/3/01 +, Chris Withers wrote: What I'd like: 'Zope' objects of type 'X', which can have multiple parents and can contain other objects of type 'X', where storage isn't necessarily tied to the ZODB but where the objects have a normal properties page (in terms of use, again, it'd be nice if it could be stored anywhere) and participate in all the normal Zope security and management interface processes, and they need to be catalogable. This sounds like ZPatterns to me, am I right? If so, it appears there are two choices: 1. Folder w/Customiser Support (FwCS ;-) and DataSkins 2. Specialist with one or more Racks and DataSkins Which one of these would be most appropriate? FwCS containg DataSkins that also mix in the Folder class sound like they'd give a closer approximation to 'real Zope objects', but Racks sound like the only way that objects of the same metatype can come from different sources (eg, some objects of type 'X' from ZODB, some from SQL, some from LDAP ,etc) and seem to be more flexible in general, but can I have DataSkins that nest stored in a specialists' rack, eg: http://server:8080/specialist/dataskin1/dataskin2 How about doing something like: http://server:8080/specialist/dataskin1/dataskin2/manage You can't really "nest" DataSkins inside each other in a rack, and you really don't want to, anyway. But there's nothing that says you can't create a DataSkin subclass whose __bobo_traverse__ looks up related objects. You just can't "really" store the DataSkins inside each other. Note that if your __bobo_traverse__ uses a specialist "getXforY()" call, you can "store" objects from different databases (racks) "inside" each other. :) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns example update....
At 03:08 PM 1/2/01 +1100, Itai Tavor wrote: Hi Steve, Steve Spicklemire wrote: "Itai" == Itai Tavor [EMAIL PROTECTED] writes: Itai Maybe with this Itai SkinScript: WITH Doers.getItem(self.doerID) CALCULATE Itai self.doerID=RESULT.id or '' ? But I'm not really sure about Itai this... Ahh.. I think my brain just imploded in a recursive death spiral, but I get intent of the idea. This would work I think: WITH Doers.getItem(self.doerID) COMPUTE self.myDoer=RESULT or Doers.getItem('doNothing') where there is a default 'doer' named 'doNothing' in one of the Doers Racks. This guy would 'fill in' for the ToDo's doer when no 'real' doer can be found... I like that. ;-) Yeah, this looks good... whether it's appropriate or not depends on how you expect the case where there's no Doer to behave - if you needed to know explicitly that a Doer doesn't exist, returning a 'nothing' doer could confuse things. BTW, I can't see the recursion in my script... but maybe my brain is still in vacation mode :) Your script uses an attribute (doerID) in the WITH clause that is provided by the COMPUTE clause. This is infinitely recursive in theory. In practice, it will result in the non-existence of the doerID attribute, as ZPatterns treats recursive attribute references as non-existence of the attribute. The WITH clause will fail with an AttributeError. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns, ZClasses, Specialists: Assigning responsibilities
At 05:13 PM 12/21/00 +1100, Itai Tavor wrote: I think you're right about this being an OrderLineItem. A couple of fine points, however... First, I don't think there needs to be an "OrderLineItemsWithGraphic" specialist, since there is nothing else that would talk to it. It's fine in this case to have the line item classes (either with graphic or without) handle their own UI snippets. UI delegation is for when an object needs to display UI for some *other* object than itself, since you can always use class extenders and other techniques to reshape the apparent class of an object retrieved from a specialist. The interface which other objects deal with is "OrderLineItem", and they simply expect a portion of the form to be rendered, and it's okay for the class to handle that. I got a bit confused here... the UI snippet for uploading a graphic actually comes from the Graphics Specialist. That's fine, but it should be by way of an object that's filling the OrderLineItem role, yes? Or I could eliminate the problem by uploading the graphic from a form displayed by the order line item after it has been added. That's actually what I thought you were doing/intending. Here's the question... how many behaviors are different in the order line item itself? Are you also using fulfillment line items? If the only difference to the order line item is that it references some additional data, then I'd say a single class would be fine. Most of the behavior probably comes in on the fulfillment line item, yes? Again, you can ask your FulfillmentLineItems specialist to create "newLineItemFor(orderLineItem)" and let it decide what kind of implementation to hand back. In this case, it probably will be a different class, while for the order line items, it may or may not buy you anything. I haven't thought of using fulfillment line items... not sure what they are for? An order is considered fulfilled once all items have been shipped, so order line items are responsible for tracking everything that happens until a ShipmentLineItem is created. The order line item for a customizable product tracks the product using state values like 'sent to factory', 'received from factory', etc. So it needs a new set of state values, as well as methods like 'sendManufacturingOrderToFactory'. What exactly does the fulfillment role you're referring to do? Does it do more than a shipment role? Fulfillment would be between ordering and shipping, covering such things as pulling items from the warehouse to customizing them with the graphic. I assumed that an order line item was only meaningful until you have a completed order. You may not need the complexity, but to me it seems like a seperate phase with a very different set of behaviors than what I would think of as an order line item. If I were doing an app like this, I'd at least have some sort of state/status objects to delegate these different behaviors to. But I'd say this could be left to the taste of the chef. :) P.S. By the way, I'm off on vacation later today, and won't be active on the list again for a little over a week. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns, ZClasses, Specialists: Assigning responsibilities
At 04:21 PM 12/18/00 +1100, Itai Tavor wrote: This is how I see it: - Products Specialist productRack customizableProductRack - OrderLineItem Specialist lineItemRack lineItemWithGraphicRack - product.addMeToOrder(): order.addLineItem(product_id=id, add='lineItem') - custimazable_product.addMeToOrder(): order.addLineItem(product_id=id, add='lineItemWithGraphic') This should probably be more like: product.addMeToOrder(): item = OrderLineItems.newLineItemFor(self) item.setQuantity(...) etc. order.addLineItem(item) customizable_product.addMeToOrder(): item = OrderLineItems.newLineItemFor(self) item.setGraphic(...) item.setQuantity(...) etc. order.addLineItem(item) This approach makes things more declarative. The product classes can have properties or interfaces that the OrderLineItems specialist can use to decide what kind of line item would serve them best. You can then change your line item assignment rules without necessarily requiring changes to the product classes. I imagine, then, that the UI for uploading the graphic would be included in product.addMeToOrderForm, using a UI snippet from the OrderLineItemsWithGraphic Specialist. Then I could pass REQUEST on to order.addLineItem and to OrderLineItemsWithGraphic.add, which would then upload the file? I think you're right about this being an OrderLineItem. A couple of fine points, however... First, I don't think there needs to be an "OrderLineItemsWithGraphic" specialist, since there is nothing else that would talk to it. It's fine in this case to have the line item classes (either with graphic or without) handle their own UI snippets. UI delegation is for when an object needs to display UI for some *other* object than itself, since you can always use class extenders and other techniques to reshape the apparent class of an object retrieved from a specialist. The interface which other objects deal with is "OrderLineItem", and they simply expect a portion of the form to be rendered, and it's okay for the class to handle that. Second, you need to define that interface so that the Order can give the line item constraints on how it does that UI, so it can share the screen and REQUEST with other objects/data that the Order needs. One easy way to do this is to use a namespace parameter, that simply gives the line item a name prefix to use on its fields. Alternatively, you can use the "record" approach, like this: INPUT TYPE="TEXT" NAME="lineitem1.desiredSize:record:int" VALUE="4" INPUT TYPE="FILE" NAME="lineitem1.imageFile:record:file" ... The resulting REQUEST object from submitting the form will contain a single object, "lineitem1", with "desiredSize" and "imageFile" attributes, so you'll only have to pass a single parameter back to the line item. I've never tried doing a record with a file in it before, so I don't really know how well that works. Woof... so long. I'd appreciate any comments on this - especially on the question on whether it's better to have a specialized type of OrderLineItem, or to link the standard OrderLineItem to a Product object in case of a standard product, or, in the case of a customizable product, to a new object which stores the graphic and tracks the fabrication of the customized item. Here's the question... how many behaviors are different in the order line item itself? Are you also using fulfillment line items? If the only difference to the order line item is that it references some additional data, then I'd say a single class would be fine. Most of the behavior probably comes in on the fulfillment line item, yes? Again, you can ask your FulfillmentLineItems specialist to create "newLineItemFor(orderLineItem)" and let it decide what kind of implementation to hand back. In this case, it probably will be a different class, while for the order line items, it may or may not buy you anything. Anyway... remember that Specialists are there to hide implementation decisions like what classes are being used. If you look at the ZPatterns Wiki you'll see references to some of the design patterns which Specialists are an instance of, which will give you some hints as to the many kinds of things they can "hide" for you (and which therefore you should avoid revealing in other code). One of those patterns is that as an object "trader" or "broker", Specialists can be used to create new instances of objects that meet a certain interface, but whose implementation has been selected on the basis of declarative criteria by the requesters. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: persistant objects hold DataSkin-Items - KeyError: _v_dm_
At 02:49 PM 12/14/00 +0100, Ulrich Eck wrote: after a while I think I got it now. I use a FcWS as a Folder like usual in Zope and if i create an object of a type which is "customized" certain attributes will be set through the customizer. Yes. so for a database app that handles multiple tables it isnt useful to handle with a FwCS. Um, not necessarily. You can create regular Folders under the FwCS if you want to keep them seperate. You can even use BTreeFolders or other ObjectManagers, if you like. All that's required is that they support the ObjectManager protocol. So you can have a folder for each meta_type. Of course, the primary storage of the object has to be the ZODB. First I thought there is the same "magic" as if i ..getItem() with a specialist .. in a FwCS No. The FwCS is to allow more "traditional" Zope objects to blend in data from other sources, and/or to have trigger support. Due to the Folders Rules, there can only by one object with the same id at a time in one FwCS .. Yes. But you don't have to place the DataSkins directly under the FwCS, they can be any number of nesting levels below it. I'll switch back to a Specialist which has many racks as data-providers which i can choose the right one with a method that has a "meta-type" parameter. is this right so far ?? Pretty much, although I'm not sure why you want to pick by meta type, since one of the major reasons for having a Specialist is for the rest of the application not to know about specific meta types. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: General Design Question
At 02:42 PM 12/14/00 +0200, Roch'e Compaan wrote: As part of a Customer Relationship Management system our company is developing, we have a Licenses specialist which manages product licenses. All license objects do not have the same attributes however. The various attributes relating to different licence types are not known attributes from the outset. My first reaction to this is that I would use a different class for each type of license, and a rack in the specialist for each class. This would allow maximum behavioral flexibility, since each class can have its own methods for inputting or displaying data. However, if your application needs to have end-user (as opposed to integrator-user) definition of license types, then you need to add LicenseType to your domain model and create a specialist for it (possibly nested inside the Licenses specialist). As I see it one can take two approaches to this: a) either add a single dictionary property for both license and licensetypes which holds user defined attributes or b) explicityly call manage_addProperty per instance to add properties. Option "b" will make your application ZODB-dependent, since there is no way to map arbitrary attributes to an SQL database, for example. Option "a" is better, since a dictionary attribute can be handled with WITH/COMPUTEs and triggers, with a little work. There is also an option "c", which would be to model LicensePropertyDefinition and LicenseProperty objects in your domain model. This approach leads to a bit more work defining your model, as well as in setting up the specialists and their interactions, but the payoff is in better documentation of what your app is doing and easier re-mapping from one database type to another. Ty and I recently experienced something similar, in an application where we were using a dictionary attribute to represent something that was better modelled as a seperate object. The complexity of the associated SkinScript and DTML/Python/SQL methods went down after we bit the bullet and added a nested Specialist. (When a role in a domain model is only accessed from one other role, it is reasonable to nest that role's Specialist inside the other's, as it keeps the higher-level app namespace cleaner. Usually there is some clustering to domain models that puts a small number of supporting classes in a position to do this for each major class.) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: persistant objects hold DataSkin-Items - KeyError: _v_dm_
At 06:31 PM 12/13/00 +0100, Ulrich Eck wrote: after one more day of source-code-reading i got that far: When I want to use a Folder /w Customizer (FwCS) I cannot/don't need to use Specialists. Not to store your objects, no. You can still use Specialists to concentrate search methods, constructors, UI snippets, and the like. Typically, in that configuration some of your Specialists may contain (or be) ZCatalogs which index selected objects from your FwCS hierarchy. i create a FwCS and put my 'Framework' in it. if i want to access (get/new) an object handled by a customizer i can ask FwCS._getDataManagerFor(client,default) for my datamanager (DM) Not necessary. If you retrieve your DataSkin as an attribute of its container, the DataSkin __of__ method will automatically find and bind the DataManager (assuming you're not using some class that overrides __of__). Do I need to implement methods like createItem/retrieveItem/_v_itemConstructor as well or how do i "get" my objects ?? Just retrieve the objects from their containers in the normal Zope way. Ditto for creation - use the standard way of constructing objects in an ObjectManager. If I have an object whose metatype is handled via customizer/skinscript/sqlmethod it'll probably work managing attributes .. Yes, it should. Likewise triggers, if you want to set up cataloging triggers. I'm searching for something that handles a newItem(meta_type,key) function that is provided from the FwCS who decides which object-type is created and gets those attributes from the customizer Just use the normal Zope "add list" to create one manually, or call the appropriate constructors (e.g. SomeZClass.createInObjectManager()). is there an example those newItem(meta_type,key) - getItem(meta_type,key) ?? You want examples? You forget, this is ZPatterns. ;) Seriously, look for examples of how to create an object by meta_type in a Zope ObjectManager. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] [ZPatterns] DataSkin object ownership
At 08:04 PM 12/12/00 -0500, BS wrote: Do DataSkins have ownership? I want to give multiple users the ability to add objects to a rack and only allow the 'owner' to view/edit the object. When a user adds a DataSkin to a rack does he get ownership of the object? I can't seem to get the ownership information for these objects. Is there a way to do this? DataSkins stored in Racks do not participate in the Zope ownership mechanism, nor the creation of the 'Owner' role. This is because they are not being stored via the normal ObjectManager protocols. If you want this behavior, you'll need to use Folders w/Customizer support, which let you use most of DataSkins' dynamic features with "almost ordinary" Zope objects. BTW - I'm talking about virtual object that totally live in MySQL. Folders w/Customizer Support require the DataSkins' primary storage to be in the ZODB. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] FW: ZPatterns, ObjectDomain, UML and all that.....
At 09:44 PM 12/5/00 +0200, Roch'e Compaan wrote: If you want to store one DataSkin inside another, where either one of them is stored in a Rack, you will have to create appropriate SkinScript or custom attribute providers to do so. But what if I always store dataskins in there own racks but simply assign an attribute of one Dataskin to the instance of another Dataskin? I simply want to be able to say Customer.Address.Street... As implied above, you cannot, unless you do so with an appropriate provider. Just like ZODB-stored objects, ZPatterns objects cannot function if you break the rules that govern their behavior. (E.g. if you change a mutable value of a ZODB object, it has no way to know it should be saved to the database.) This is a "by design" limitation of ZPatterns. Also, it's not that bad of a limitation. You can easily work around it with SkinScript or an attribute provider, and more commonly, this is done by delegation to another specialist. Specifically, rather than breaking encapsulation by having application code write to an attribute directly, you use a method which delegates to the foreign specialist, asking it to link or create an associated object. You can then still use SkinScript to retrieve your "Address" attribute, again by delegation to the other Specialist. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] changing/storing Properties with ZPatterns
At 10:07 AM 12/1/00 +0100, Joachim Schmitz wrote: this works fine. Now I wanted to have attributes which I don't want to display in the form, for example complete attribute. I therefore created another dataskin propersheet Internal in AZ with a property complete and tried to set it with: dtml-call "ni.propertysheets.Internal.manage_changeProperties(REQUEST,complete='1')" But I don't manage to store retrieve this attribute. All attributes in the Basic propertysheet I can store and retrieve. what is the magic behind this ? Beats me. I know that we use a variety of DataSkin propertysheets in our apps with no problems, although we are not using persistent storage at the present time. What happens when you try to store "complete"? Is it simply not saved, or do you get some kind of error? Have you tried other values? Have you checked your permissions to ensure your code has rights to change the "Internal" sheet? ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] OracleStorage, and possibly others
At 08:10 AM 11/30/00 -0500, Jim Fulton wrote: I don't think Data.fs will go away. I do expect it to be relagated to initial evaluation and development projects. Use of Berkely DB in transactional mode requires a significant andminstration commitment. Log files need to be purged. Backup and recovery processes need to be in place. FWIW, Ty and I talked about using a daemonic thread in BerkeleyStorage to run periodic checkpoints and purge logfiles. AFAIK, backups of BerkeleyDB require only that you make a copy of all the associated files. Recovery's a bit trickier, of course. (We never got around to implementing it because our tests showed that BerkeleyDB didn't solve the performance issue we were trying to solve. So we quit working on it at that point.) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: using PythonMethods from Skinscript
At 04:39 PM 11/30/00 +0100, Ulrich Eck wrote: I've a db_sequence specialist who serves the Framework with db_id's for new Records like: May I suggest calling your Specialist "Sequences" or "Counters" since it appears that it returns objects which produce sequential integer values? >>> newid = db_sequence.getItem('sequence_name>').nextid The Attribute nextid is provided by a Skinscript-Method: WITH getNextId(seq_name=self.id) COMPUTE seq_name=seq_name,nextid=_.int(nextid) I would not suggest using nextid as an attribute. This should really be a method, e.g. getNextId(). The method should then return the result of calling Counters.getNextId(seq_name=self.id). However, if you insist on using the above approach, your SkinScript should read: WITH getNextId(seq_name=self.id) COMPUTE nextid=RESULT['nextid'], seq_name=RESULT['seq_name'] Notice that since your Python method returns a dictionary, RESULT is a dictionary, not an object, so you have to retrieve the elements you want in your expressions that way. Of course, you could just have getNextId() return an integer result, and use: WITH getNextId(seq_name=self.id) COMPUTE nextid=RESULT WITH SELF COMPUTE seq_name=id to achieve the same effects. My Second "little" Problem: i'm not the first one who had problems to manage data with rdbms and zpatterns. i can get Attributes through SSMethods easily and now tried to setup ADD/CHANGE/DELETED Rules to manage data. Here my SSMethod for this(getEventById/insertEvent/updateEvent are ZSQL-Methods): WITH QUERY getEventById(id=self.id) COMPUTE sid=_.int(id),name,time_start WHEN OBJECT ADDED CALL insertEvent(id=self.sid) WHEN OBJECT ADDED,CHANGED STORE sid,name,time_start USING updateEvent(id=self.sid,name=self.name,time_start=self.time_start) I access the Item through loadAttribute: "sid" I set up a ZClass derived from Dataskin which acts as Storage-Class. I call dtml-let ni="newItem(key=db.getItem('data_event').nextid)" nips="ni.propertysheets.get('Basic')"> dtml-var "nips.manage_changeProperties(REQUEST=REQUEST)"> /dtml-let> and get back an empty object without any attributes (propertysheet-problem??) the record in the database is created (but only because I reduced the ZSQL-Insert Method to id-parm only) this again seems to be a Problem of the namespace I'm in while the _objectAdded() ... method. Here's what you're missing. There is no "sid" attribute when you add an object. You need to add this to your SkinScript (assuming I'm guessing correctly what sid is supposed to be): INITIALIZE OBJECT WITH sid=_.int(self.id) Otherwise, your two ADDED triggers will execute with no value for the sid attribute. - Do I need a PropertySheet when I only want to access/change/create/delete Items/Attributes from a RDBMS ?? If yes: Which one (CommonInterfaceProp/DataSkinProp) If no: how do i Access/Change my Properties ?? Yes. DataSkin Property sheets would be the ones you need to use. - and another Question related to this: Which object fires the Trigger-Event (ADDED/CHANGED/DELETED) .. is it the PropertySheet itself ??? When you change the attributes of the object, the action is logged for the trigger to fire at transaction commit time. The Property Sheet is just a way to change the attributes. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPetterns implementation qustions
At 06:19 PM 11/29/00 +1100, Itai Tavor wrote: Hi, I'm trying to figure out the right way to implement a set of classes and roles in ZPatterns. I asked some questions about this a while ago, and then went away and did some learning, but I'm stuck again and I'm afraid I need to ask more questions. I have two types of actors - Person (with properties name, phone, email, password) and Organization (with properties name, phone, fax, business_number). I also have two participants - Customer and Reseller. Each participant can be either a Person or an Organization. The participants can fill several roles, like OrderingEntities, BillableEntities, etc. Starting from the bottom, I create a Specialist for each role, each one with two virtual Racks - customerRack and ResellerRack, so I can refer to an OrderingEntity without caring if it's a Reseller or Customer. My problem is in implementing the Participant Specialists and storing Participant and Actor classes. Do I create Specialists for the Actors? It seems to me that since there is either one Person or one Organization per Customer, then the actor object should be created in the Customers Specialist. So Customers will have 3 Racks - defaultRack (using Customer object), personRack (using Person object) and organizationRack (using Organization object). Does this make sense? I think what you want is to have an Actors specialist containing a personRack and organizationRack. That is, treat "Actor" as a role relative to either Customer or Reseller. The reason I say, "I think", is because I'm really not clear on why you're doing certain things here to start with. See below. If this is a good way to do it, how do I handle creating and accessing the Person and Organization objects? Do I call personRack.newItem(newCustomerId) in the script that creates the customer? Or do I somehow do it in a SkinScript in defaultRack? And how do I get to the Person data? With an attribute provider? Or in Here's a red flag: why are you creating a person when you create a customer? If a person is something that you only make when you have a customer, then the actor-participant-transaction pattern isn't really valid, IMHO. For Actor-Participant-Transaction to make sense, you have to have Actors that exist seperate from the Participants. While it makes sense to be able to create an Actor at the same time, your model needs to also include a way to select an *existing* Actor as the Participant, otherwise you are not gaining anything from the A-P-T pattern and you might as well just have the Participant. Here's a pattern for mapping A-P-T interactions onto ZPatterns, however... If you are doing A-P-T, make sure you use a Specialist for access to the Actors. For example, in some applications Ty and I write, "acl_users" is designated as the Specialist for actors if all actors in the system have to be able to use the application. The user interface and implementation for creating and/or selecting actors to fill a participant role is placed in the actors' specialist - acl_users in our case, or perhaps a specialist called "Actors" in yours. (But I'd recommend you use a domain-specific name, if possible.) So you would not be worrying about whether to create a person or organization or what fields they need or anything else in the specialist for your "participant" objects. Indeed, you wouldn't be worrying about whether a new one was being created, or an old one selected, if you delegate that aspect of the UI to the actors' Specialist. Also, if Actors are stored in the Specialists that implement the roles they participate as, there is no place to store methods that are common to an Actor regardless of role - for example, a method that checks if a password is secure enough and called when adding a Person object. So I either duplicate these methods in every Participant Specialist, or create more Specialists - which seems like a waste either way. Again, this is solved by using a specialist for the role "Actor". Another problem is how to edit these objects - if I have a form which includes fields for a Customer properties and for the properties of the Person object linked to that Customer, can I change the Person object from the Customer SkinScript? I don't think I can do this: WHEN OBJECT CHANGED STORE name, password USING personObject.propertysheets.manage_changeProperties(name=self.name, password=self.password) Right? Because name and password are not properties on the Customer DataSkin. So I have to call person.manage_changeProperties(...) in the method that changes Customer... it seems to me that I always end up doing object connections work in methods and the SkinScript can't help with anything :( You're making this entirely too hard. The Prime Directive of ZPatterns design is, "if it looks too complicated in any one place, your design is probably wrong. If almost every individual piece looks simple, even though the whole is
RE: [Zope-dev] Create Virtual DataSkin
At 02:34 PM 11/27/00 -0800, Ben Schochet wrote: Seems that way Steve. I have tried to do this in an external method with self.get_transaction.commit(1) before doing the changeProperties, but that didn't seem to work. You want get_transaction().commit(1), if you're doing it from Python. DataSkins also have a commitSubtransaction() method that can be used to do this. Is there another way to do this? the CHANGE trigger works fine on its own. How are others creating new items with properties from an HTML FORM? Should I be doing this another way? I can't wait to figure out ZPatterns, I think it is the best way to create Zope applications! It seems to allow you to have the best of Zope objects along with your data secure and accessible from a RDBMS. (At least that is the value I see, there are probably others...) You can't have an ADDED and CHANGED both fire in the same subtransaction. ADDED, CHANGED, and DELETED are mutually exclusive. So your ADDED trigger has to perform the same operations to save data as your change trigger would. One easy way to do this is to do: WHEN OBJECT ADDED ...stuff to do for adding only WHEN OBJECT ADDED,CHANGED ...stuff to do when changing or adding Since the triggers are fired in order, and both triggers fire on add, that should be pretty easy to set up. Note that in this case, you won't need to commit a subtransaction. Subtransaction commits are really pretty rarely needed. About the only time you should *normally* need a subtransaction commit is that if you have triggers you want to take effect before you move on, like triggers that update an index you're about to search. The normal assumption in Zope however is that you generally keep your read and write transactions seperate; i.e. a POST usually results in a redirect to the updated object, or something of that sort. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Create Virtual DataSkin
At 08:34 PM 11/27/00 -0500, [EMAIL PROTECTED] wrote: Thanks Phillip. Is there a way to pass my REQUEST info to the ADD Trigger? I am under the impression that only "self" and some other ZPattern specific properties are available to the trigger. You also have access to everything in the acquisition hierarchy of the trigger or SkinScript method itself, which of course includes REQUEST. So either REQUEST (which would look it up in the trigger's acquisition hierarchy) or self.REQUEST (which would look it up in the DataSkin's acquisition hierarchy) should work fine. Now that I've told you *how* to get at it, however, I should warn against making too much use of the request to get information that could've/should've been passed to the DataSkin by application or domain code. It makes sense to use the request if you want to log things about the request that caused the change, but it's probably not a good idea to be looking at form fields and such, since that would introduce an undesirable coupling between your application structure and your triggers. Ideally, triggers should only look to the DataSkin for anything other than methods or constants they need to carry out their job. In practice of course, if you want to do something like log the AUTHENTICATED_USER and whether they were logged in via SSL, then of course the REQUEST is the right way to do it. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns and ZCLasses
At 10:29 AM 11/22/00 +0100, Joachim Schmitz wrote: I created a FwCS and in it a customizer, but in my list of to customize object types are only meta_types listed, which have the Base class "_ZClass_for_DataSkin",. Is this a requirement, and if yes, is there a way to add this to existing ZClasses ? It is a requirement. The only way to add it (or any other base class) to existing ZClasses is to use the "setbasesholdontoyourbutts" hack, which I have never done, but a search of the mailing list or Zope site might reveal the technique. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: Methods of specialits
At 12:41 PM 11/22/00 +0200, Roch'e Compaan wrote: I have a specialist Contacts and for Contacts I have a method getAllContactsForCustomer. Whenever I want to call this method I have to pass on the whole namespace and the object itself to get it to work eg: getAllContactsForCustomer(this(), _, _.None). Why is this the case? And what does _.None actually mean? If your method is a DTML method or document, it does not automatically supply a "self", so currently you must call such methods in a specialist like this: Specialist.someDTMLthing(Specialist,_,...) Where "..." represents any other arguments you wish to pass the method. (They must be passed as keyword arguments.) This is a DTML issue, not a ZPatterns one. Hopefully, in later versions of Zope, if method binding is standardized across DTML, Python, etc. method objects, then you will be able to avoid this issue by setting binding settings on the method object itself. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
RE: [Zope-dev] ZPatterns Project Help!
At 10:21 AM 11/22/00 -0500, [EMAIL PROTECTED] wrote: Thanks for answering Steve. Unfortunitly I am working with version 0.3 of ZPatterns so I have to use GAP. When I try to translate your Skinscript into GAP like this "attrsexprs:account_object=(RESULT is _.None) and NOT_FOUND or RESULT" and I try to access the object's id with dtml-var "account_object.id" I get a "NameError" on account_object. Alternativly if I do dtml-var account_object I get a "KeyError". (BTW. for testing I used "accounts.getItem('1434')" which is a valid object. If I do "account_object=RESULT.id" it works fine.) Perhaps this is a security issue? When you set account_object=RESULT.id, then the account_object attribute is a string, and has no security protection from access by DTML. When it is an object, however, your DTML must have permissions to the object itself. I am not positive, but I think ZPatterns 0.3 may have executed GAP expressions as the superuser, so it may be that your GAP is able to access the object, but not the DTML which is using the DataSkin. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns and ZCLasses
At 11:08 AM 11/21/00 +0100, Joachim Schmitz wrote: I have an existing ZClass/Data Structure like this RecruitingPlatform Company Recruiting Candidates Student Profiles Address Highschool IT Jobprefs ... I want to store the data in the ZClass instances, must each ZClass have the Base class _ZClass_for_DataSkin and do I need a Rack for each class ? If you are storing dataskins in a regular folder hierarchy (or other persistent hierarchy), you don't need racks. You just need a Folder w/Customization support in the objects' acquisition hierarchy. Of course, if you don't need DataSkin-ish behavior (i.e. triggers and attribute providers), you don't need the FwCS either. DataSkins stored outside of Racks will "pretend" to be ordinary persistent Zope objects if they can't find an appropriate Customizer. That is, they act like regular Zope objects, only it takes them more work because they're pretending. :) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Folders w/Customizer Support
At 02:46 PM 11/16/00 +, Chris Withers wrote: To put it another way, could you have a FwCS that provided soem properties and let another FwCS further up the acquisition tree supply the rest? Nope. But there's nothing stopping you from writing a new version of the "link to parent providers" plug-in that would get providers from a higher-up FwCS... :) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] __replaceable__ or whatever it is ;-)
At 11:14 AM 11/15/00 +, Chris Withers wrote: Thanks... I guess the behavior that was associated with ObjectManager.NOT_REPLACEABLE is obtained by just not havign a __replaceable__ attribute? ..or does ObjectManager.NOT_REPLACEABLE exist, just in an undocumented fashion ;-) Also, when is it going to land in a erleased Zoep version? 2.3 I guess... That's the plan. Bad question, I know, but any idea when that'll be? FYI, if you want to play with this before then, the current release of the PlugIns package has support for the proposed behavior in the PlugInContainer class, using a code snippet cribbed from Zope CVS. So you should be able to make PIC subclasses with overrideable methods. I put in that support because I wanted Specialists and such to be able to use overrideable methods. I haven't gotten around to actually putting any in, though. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: Remapping object from on to another specialist
At 05:51 PM 11/13/00 +0200, Roch'e Compaan wrote: Should I still set up a rack and set it's storage to the Customer ZClass and add a skinscript method to copy attributes from the Customer specialist? or Should I simply write a method for Requester, getRequester, which asks the Customers specialist for a Customer. Do the former if you need to implement different behavior. Do the latter if Customer already provides the needed interface for a requester. Be careful, however, that you do not mix the interface of Customer and Requester, but have clearly defined them seperately (even if both interfaces may share a method, or one interface is derived from the other.) Another question: If I pass an attribute that is not registered with any attributeproviders in a manage_changeProperties call to the object's propertysheet, will that attribute automatically be added on top of the object? Should one explicitly call manage_addProperty? Yes, it would be necessary for you to add the property, since Zope security ordinarily frowns on setting arbitrary object attributes. :) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Membership and latest LoginManager
At 01:37 PM 11/13/00 -0500, Dan L. Pierson wrote: I've been trying to get Membership 0.7.6 working with LoginManager-0-8-8b1 (and it's associated ZPatterns) under Zope 2.2.2 on RedHat 6.2. After probing around it seems that there is a problem storing member passwords. The following trace from print statements inserted in PersistentUserSource illustrates the problem: Dan, can you check what class you're using for users, what kind of propertysheet SystemProperties is on that class (DataSkin or CIPS), and whether it actually has a "password" property? Thanks. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Specialists, Racks, and Objects, oh my!
At 04:14 PM 11/13/00 -0700, Bill Anderson wrote: I want a specialist to have two (or more hypotheticaly) racks, and each rack is to contain one type of object. I then want to be able to add objects. I have the two racks set up, but I am unclear as to how to specify that I want to add an item of a certain type, or to a certain rack. Ideas appreciated ... You can either give your specialist methods to create objects of each type, which call the respective Racks' newItem() methods, or give your specialist a single method that determines based on input parameters which class would be better suited. The choice depends on the requirements of your problem domain. In either case, the specialist is also the natural place to put the UI ("add forms") for creating the objects. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
RE: [Zope-dev] ZPatterns: Non-ZODB storage and Racks
At 09:18 AM 11/9/00 +0200, Roch'e Compaan wrote: I set "loaded by accessing attribute" to the attribute "id". You should only do that if you want an "infinite rack". That is, one which contains all possible objects. Using "id" means that if the Rack tries to see if an object exists, it will *always* exist, whether it really exists or not. (Because the "id" attribute will always exist.) Given your example SkinScript below, you should probably be using "name" as the attribute to load off of. Then, the rack will only return an object if it exists in the SQL database. (Btw, you should probably be using WITH QUERY in your SkinScript.) Storing items in the RDBMS works fine. But when I try to retrieve them with getPersistentItemIDs() nothing is returned? That's because getPersistentItemIDs() only returns the id's of objects which are stored in the ZODB. That method exists only so you have some way of iterating over objects when you're using the "stored persistently" storage mode. It can also be used to find the id's of objects which have some of their attributes or propertysheets stored persistently. It is *not* a "get me everything in the rack" method. I have a skinsript method getCustomer: WITH getCustomerSQL(CUSTOMER_ID=self.id) COMPUTE id=CUSTOMER_ID, name=NAME and getCustomerSQL is a SQL method. If your objects are stored in an SQL database, then to get a list of objects you need to use an SQL method. Here is the "recommended approach" for iterating over objects in ZPatterns: 1. Define domain-specific retrieval methods in your specialist. For example, "getPastDueToDoItems()" and "getAllToDoItems()". 2. Create methods in your rack(s) which actually implement the retrieval; these may be named the same, or depending on your application, they may be smaller chunks of code which you aggregate or pass parameters to, in order to implement the higher-level functioning. If a given rack uses ZODB storage, its implementation methods may use getPersistentItemIDs(), but they should otherwise be using SQL methods, catalog searches, or other means of retrieving a list of objects. 3. Have the domain-specific methods call the methods in the racks to implement the desired behavior, and have *all* other code call the methods in the Specialist. The key here is to remember that: 1. A Specialist is a singleton object (i.e. only one instance per app) that is responsible for dealing with objects of a particular interface. Specifically, it is responsible for: a) Creating objects which supply that interface, according to given criteria b) Retrieving objects which supply that interface, given an identifier c) Manipulating groups of objects which supply that interface, through a domain-specific API (e.g. getPastDueItems(), purgeCompletedItems(), etc.) d) Providing an application-level UI for all of the above, as/when needed by the application e) Providing UI "snippet" methods to create selectors (e.g. form fields, dropdowns, etc.) for other objects to use in their UI's, so that they can relate to or otherwise interact with objects the Specialist is responsible for. (Notice, by the way, that this list effectively puts everything that an application integrator might want to customize all in one place...) 2. Racks are essentially *private objects* belonging to the Specialist to help it carry out its responsibilities. Each rack is responsible for retrieving objects of a *particular class and storage location* which implement the interface the Specialist serves. Multiple racks are used when there is more than one class that implements the interface in the application. 3. Because Racks belong to the Specialist, it's okay for the Specialist to "know" things about its racks as a whole (e.g. which ones provide what concrete classes, what search order to use, how to combine the results of queries from them, etc.), but it should still delegate the actual *implementation* of behaviors to them wherever possible. If you follow this approach, you will end up with an application whose functioning is cleanly divided, and any developer familiar with ZPatterns will know where to call things, and where to go to change implementations. Further, if that developer needs to change from an SQL database to using the ZODB, or vice versa, or change from one database schema to another, they will be able to do so without changing code outside the racks, or at most, the specialist, and all other application code, including your classes and ZClasses, will be unaffected by the changes. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: Non-ZODB storage and Racks
At 10:45 AM 11/9/00 +0100, Rik Hoekstra wrote: [rh]I've been following this thread. This may be a bit of a newbie question, but it's been bugging me for a while. I see how I can store propertysheets in Racks using ZClasses and Skinscripts, but the propertysheet term suggests that there should always be an object that the properties are attached to. Depends on what you mean by "attached". One of the most annoying things about Zope propertysheets is that there are two kinds. ZPatterns implements one of the kinds (WebDAV sheets), but not the one that most people have encountered (the kind used in ZClasses). Although WebDAV sheets are associated with a particular object, they are objects in themselves. ZClass instance sheets are "virtual" and store all their data in the associated object. To do ZClass-style sheets in ZPatterns, all you need to do is implement the attributes; the sheets can take care of themselves. To do WebDAV-style sheets in ZPatterns, you need a SheetProvider or you need to simulate propertysheets using an attribute provider to make an attribute that is actually another object, and which supports appropriate methods. Is that an actual ZODB object or is it the Specialist object that can 'create' virtual objects on the fly? Racks create "virtual" objects when set to "load by accessing attribute ___". [rh] If I read this right, this suggests that an object stored in a SQL database and 'masquerades' as a Zope object? Or does an object always have to exist in the ZODB (with it's own id that corresponds to the id in the RDB or knows how to retrieve it). In other words, does the ZPatterns framework need an 'anchor' in the ZODB to connect it's properties to, or can you create pure virtual objects, that retrieve all of their properties from a specialist, including the ID. When set to store objects persistently, "real" Zope objects are made and stored in the rack. When set to load via an attribute, the rack creates a dummy Zope object with its "id" attribute set appropriately, then tries to access the specified attribute. If the attribute exists (i.e., an attribute provider succeeds in loading the data from the external data source), then the object is considered to "exist" and can be returned. This would be a "pure virtual object" in your question. If the last is the case, could someone give an example how to implement it. A very simple one would suffice I suppose (hope). Roche's situation is an example, at least if he used the "name" attribute as the load attribute, rather than the "id" attribute. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns: Non-ZODB storage and Racks
At 06:10 PM 11/8/00 +0200, Roch'e Compaan wrote: In Rack.py I noticed the following: a = self.loadAttrib if not a: slot = self._writeableSlot(key) slot[SelfKey] = item.aq_base# strip acquisition wrapping item._setSlot(slot) # Not needed for non-ZODB storage If item._setSlot set is not needed for non-ZODB storage should I subclass rack and override createItem? I'm not sure I understand your question. If you don't have something special you want to do by subclassing Rack, then the answer would be "no". :) The comment is perhaps misleading. What it means is that the _setSlot call isn't needed if your Rack implements a non-ZODB storage mechanism. The reason *why* it isn't needed, is that the DataSkin will ask for a slot on demand, so that a ZODB record is only created if something needs to be stored persistently. However, in the case where you have not set a "load" attribute (i.e., you are storing actual objects in the ZODB), then one might as well tell the object its slot, because the slot is where the object itself is going to be stored. Technically, the _setSlot call isn't necessary even then, because the DataSkin could still ask for it on demand. However, since the code at this point has gone to the trouble of getting the slot object, it might as well pass it to the DataSkin immediately. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] Re: Problems with LoginManager 0.8.8b1
Jeff, The behavior is exactly the same with a "plain" Zope User Folder. It also has nothing to do with acquisition, at least not in the way you think. The problem is that a user who is defined in a subfolder is *not* granted roles to any folder above them. This means that they have no access to "standard_html_header", unless it is set to be viewable by Anonymous. Hope that answers your question. At 11:50 AM 11/7/00 -0500, Jeff Hoffman wrote: Phillip and Ty, I posted this to the Zope list two to three days ago. No one has responded, so I am writing you directly in the hopes that one of you may have some insight on my problem. If I can do anything to help you narrow it down, such as tarring up my Zope install and sending it to you (with my ZODB and products), let me know. Thanks, --Jeff --- Jeff K. Hoffman 704.849.0731 x108 Chief Technology Officer mailto:[EMAIL PROTECTED] Going Virtual, L.L.C. http://www.goingv.com/ -- Forwarded message -- Date: Sun, 5 Nov 2000 16:02:14 -0500 (EST) From: Jeff Hoffman [EMAIL PROTECTED] To: [EMAIL PROTECTED] Subject: [Zope] Problems with LoginManager 0.8.8b1 Hello, I am having an odd problem with LoginManager 0.8.8b1 and am writing the list in the hopes that someone can either help me out, or confirm that I've encountered a bug. I am running Zope 2.2.2 with Python 1.5.2 on a Linux box. I installed LoginManager as described, and compiled DynPersist and so forth for ZPatterns. All seems to be working well. I created a temporary folder called 'sandbox', inside of which I instantiated a LoginManager. In its UserSource (a Generic User Source), I created four Python Methods (with Python Methods v0.1.7): --- userAuthenticate paramsself, REQUEST, username, password/params if username == 'XXX' and password == 'XXX': return 1 else: return 0 --- userExists paramsself, REQUEST, username/params if username == 'XXX': return 1 else: return 0 --- userDomains paramsself, REQUEST, username/params return [] --- userRoles paramsself, REQUEST, username/params if username == 'XXX': return ['Manager', 'Member'] else: return ['Member'] Once done, I pointed my browser to http://myhost/sandbox/index_html. This method is a standard DTML Method, inluding standard_html_header and footer and putting some text in the middle. I get the following error: Traceback (innermost last): File /usr/local/zope/lib/python/ZPublisher/Publish.py, line 222, in publish_module File /usr/local/zope/lib/python/ZPublisher/Publish.py, line 187, in publish File /usr/local/zope/lib/python/Zope/__init__.py, line 221, in zpublisher_exception_hook (Object: Traversable) File /usr/local/zope/lib/python/ZPublisher/Publish.py, line 171, in publish File /usr/local/zope/lib/python/ZPublisher/mapply.py, line 160, in mapply (Object: index_html) File /usr/local/zope/lib/python/ZPublisher/Publish.py, line 112, in call_object (Object: index_html) File /usr/local/zope/lib/python/OFS/DTMLMethod.py, line 172, in __call__ (Object: index_html) File /usr/local/zope/lib/python/DocumentTemplate/DT_String.py, line 528, in __call__ (Object: index_html) KeyError: standard_html_header Zope can't find standard_html_header. I am guessing the acquisition path is getting hosed somewhere along the way. If I simply delete acl_users from sandbox (my LoginManager), index_html works fine. Moreover, it is not just standard_html_header that I can't acquire. I created a DTML Method called foo, and could not acquire it, either. Any ideas? --Jeff --- Jeff K. Hoffman 704.849.0731 x108 Chief Technology Officer mailto:[EMAIL PROTECTED] Going Virtual, L.L.C. http://www.goingv.com/ ___ Zope maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope-dev ) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] ZPatterns and Properties that are objects
At 01:01 PM 11/7/00 +0200, Roch'e Compaan wrote: I created a couple of ZClasses based on Dataskin. In the way I grok ZOPE, properties that are objects can not go onto property sheets. So if I have a Customer ZClass that has a property Address (a property that is an object) then I would create the address object as a "method" of the Customer that makes references like Customer.Address.Street possible. The way Ty and I usually handle "object" properties is to give an object setter methods (e.g. "setAddress()") that simply set the property (e.g. self.Address = addr). The only downside is that you have to do this in a Python base class or an External method. Later, we expect to replace this approach with PropertyHandlers, and we already have a primitive form of PropertyHandler we have used with some success, but it's too crude at this point for a product release. To achieve this without ZPatterns I would base my ZClass on a objectmanager so that I can create an instance of an Address object within Customer. So how does one do this with ZPatterns. In one posting I picked up that one does not have much joy with ZPatterns and the ObjectManger base class? I have created ObjectManager and Folder dataskins before and had them work, but at the time I was testing with Zope 2.1.6, and it was an older version of ZPatterns. I haven't done much lately with them. If people are experiencing problems, perhaps someone could send me a bug report? ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] DataSkins containing DataSkins
At 05:39 PM 11/6/00 -0800, John Eikenberry wrote: The base DataSkin will be in a Rack. Would there be any issues in making the embedded DataSkins (contained on the base DataSkins) use this Rack as well? Seems like it might result in the confusion about which DataSkin a PlugIn on the Rack worked with. Yes, it would, if you persistently stored the DataSkins in the other DataSkins. If you use an Attribute Provider, however, that loads them from a different Specialist+Rack, you'd be fine. Would it be better to use Customizers in some way... either have the base Dataskin or perhaps the Specialist also inherit from the Customizer? Ugh. Well, you might be able to make the DataSkin a Folder w/Customization Support... but I don't know if it would work. I've never tried mixing a DataSkin with the classes that support DataSkins. I think there might be some horrible method naming conflicts. Phillip, I think you've considered this (didn't you once mention converting PropertySheets to DataSkins). What issues do you think I should be aware of in planning for this. Doing DataSkin propertysheets would be done by having the propertysheets come from a different Specialist. Thing is, if you want to store DataSkins arbitrarily nested within one another, you can do it in the regular Zope management structure, without using a Specialist/Rack combo. On the other hand, if you have a structured nesting, (e.g. object type A contains some number of object type B), then you should be using attribute providers/SkinScript to define how those sub-objects get stored. To use ZPatterns for its intended purpose, it is critical that you step back and NOT think in terms of how you'd implement a solution in Zope without ZPatterns. In fact, it is important that you not think of implementation *at all*, because it will distract you from the real question, which is how to segment the responsibilities of your application. Once those responsibilities are segmented, implementation is simply a matter of writing the necessary methods and SkinScript. In this case, segmenting according to the RIPP model means that objects are never truly "contained" in other objects. An object just gives you ways to get at related objects. And if there is a relationship between objects, that means that the object on the "other end" of the relationship plays some role in your system, and where there's a role there almost always needs to be a Specialist. Now, it may seem that this is needlessly constraining, because it is more restrictive than Zope. After all, Zope lets you put anything in anything -- just like Basic lets you go to any line in the program. :) ZPatterns, however, exists to make interconnectable frameworks possible. You can still do the kinds of things Zope can, but you must explicitly think through your application's role model, and seperate the responsibilities accordingly. The payoff of this more rigorous design approach is that your application can be backed by *anything* that can support the data, including combinations of different kinds of data stores. And, your application will be a potentially re-usable framework. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Questions about implementing object models with ZPatterns
At 05:19 PM 11/1/00 +1100, Itai Tavor wrote: Ok... I think I get the "Specialist per role, not per class" part. But I still can't make the jump from a class diagram to a ZClass/Specialist setup. A class diagram contains all the roles - they're the lines between the classes. :) Look at it this way... if an object has a particular association role that it needs filled, and there is more than one kind of object that can fill that role, then presumably those objects must all implement a certain interface, right? You need to create a Specialist for that interface. In other words, there is usually one Specialist per collaboration interface -- which is NOT a one-to-one mapping with classes, since some classes may implement multiple interfaces, and some classes may all implement the same interface. I can solve some of it by subclassing ZClasses. So, if I need Customers and Resellers, I'll make a Specialist for each, and a Customer and Reseller ZClasses, both subclassed from Person which stores common properties for a person. This part is ok. What *role* do Customer and Reseller objects play in your system? It sounds to me like perhaps they play the role of "thing that places orders" or "thing that orders are shipped to". Depending on your application's functions, you could need as many as FOUR specialists: Customers Resellers BillableEntities ShippingDestinations Where the latter two specialists would contain a pair of Racks that mapped back to the Customers and Resellers specialists, respectively. But it gets more complex than that. Take this example: Every OrderLineItem object can have one or more Payment objects associated with it. There are 3 possible payment types - Check, Charge and BankDeposit, so I make a ZClass for each one, all subclassed from a general Payment ZClass. I create one Payments Specialist with 3 Racks. Where do I store methods that are specific to one payment type? In the Rack? I can't store them in the Specialist - it would be a mess, and I can't store them in the ZClass, because the ZClass doesn't know about the rest of the application. Huh? What do you mean by "methods that are specific to one payment type" in this context? What do payments do that requires knowledge of the rest of the application? If it's a problem-domain method, it belongs in the ZClass. Actually, writing this down makes me realize that it could work... would Payments.getItem(some_payment_id).someMethod() call someMethod in the Rack if one exists, and the one in the Specialist if not? No. DataSkins acquire only from the Specialist, not the Rack. However, you can use ClassExtenders in the Rack to provide methods to an object. But you *can't* override methods that already exist on the ZClass. This should not ordinarily be an issue since you should only be doing problem domain methods on your ZClasses anyway, and there should be no need to override them. Another problem I'm having is how to store id's for different objects in the the same field. In the Payments example above this is not a problem, because all payments are supplied by the Payments specialist. But what about another example - Customers and Resellers are two totally different roles, so they each get a Specialist. the Payment object has from_id and to_id fields, and each of those can hold the id of a customer or reseller, or some special code to indicate the store. I could add from_type and to_type fields, or I could prefix the id with a code letter, but neither seem like a good solution. Is there a recommended approach for solving this problem? See above, where I mention BillableEntities and ShippingDestinations. Having only one specialist per role means that you never have to worry about ambiguous identities. Please note, however, that at this stage of design you shouldn't be looking at how the references are going to be stored. At the abstract design stage, you would just have "Payor" and "Payee" attributes that are the actual related objects. When you write your SkinScript later, you can set up how the linkages work, using ID fields, or SQL columns, or whatever. ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )