At 03:46 PM 10/3/00 -0700, John Eikenberry wrote:
Ok, I'm feeling pretty stupid right now but I have to ask what you mean by "define the property sheets as part of your class"? Do you mean using something like this in the DataSkin subclass:
def __init__(self,id): self.DataSkin.__init__(self,id) ps = self.propertysheets ps.manage_addPropertySheet('CompanyData','CompanyData') ps.get('CompanyData')._properties = ( {'id':'name', 'type':'string', 'mode':'w'}, ... )
That'd be one way to do it, although it's not compatible with what I had in mind. (i.e., you'd have to write SheetProviders rather than using AttributeProviders.) I was actually suggesting that you create pseudo-propertysheets by just providing methods that change a set of related attributes on the object. Such methods are a lot easier to use than actual propertysheets.
up a single trigger that checks whether any of the attributes you want to mirror have changed, and then fires that off to the SQL db. It would
By 'trigger' you are referring to a RuleAgent plugin? Hmm... I had briefly thought about this, but most of the discussions relating to interfacing to an external RDB seemed to indicate subclassing a SheetProvider was the best course of action. I'll have look into this (hadn't spent much time figuring out RuleAgents yet).
At one time, it was the best course of action because RuleAgents didn't exist and couldn't be written. Now, Generic providers and triggers (or their SkinScript equivalents) are available and more convenient than writing a SheetProvider from scratch. I am actually becoming somewhat disillusioned with the original propertysheets extensibility setup, in that as I've been designing and building real apps with ZPatterns I've not as yet found them to be a useful route to take. Anything that you can do with a propertysheet can be as easily done by providing an attribute that actually returns another DataSkin representing that "sheet", and seems much more natural as an interaction model at the application design level. Instead of "foo.propertysheets.get('CustomerProperties').whatever", you can say "foo.asCustomer.whatever". IMHO it would appear that the shortcut route to property set integration in ZPatterns is not to design custom property sheets, but instead to define interface names for your integration points. And this is only in circumstances where you can't simply make a whitebox specialist map things with virtual objects (per my recent post to Steve about framework integration). What's happened is that ever since the advent of the Generic providers/triggers, and especially of SkinScript, things have gotten a lot easier. In my original envisioning of ZPatterns, I thought that AttributeProviders and SheetProviders would end up being written for LDAP, SQL, etc., and would be relatively specialized. Under those circumstances, the best way to do this would have been a propertysheet. Now, I'm beginning to wonder if I shouldn't go back and deprecate all those references to sheet providers and such, leaving them in place purely for WebDAV support. Actually, what I should probably do is add a new declaration to SkinScript that lets you declare a mapping from a propertysheet name or namespace to an attribute on the base DataSkin. Then, you could use the attribute mapping facilities to create propertysheet objects of your own devising. I'd probably also have to provide a suitable base class for those propertysheet objects, based on DataSkin and providing all the Zope standard methods for a property sheet. I'll consider this for 0.4.3 (coming in a couple weeks or so) but more likely it'll be an 0.4.4 or later.
actually be a bit easier to set up if you were using a ZClass, since you could create the property sheets there by just adding "DataSkin Property Sheet" objects to the ZClass. But the basic principle would still apply.
We've come to the conclusion that ZClasses really are more a hinderance than a help, trading functionality for shorter learning curve. With straight python code you get much more control and the ability to use conventional editors and tools (cvs), without losing anything besides a bit of time figuring things out (which is better in the long run anyways).
Ty and I use ZClasses because you can see your changes much more quickly than if you have to restart Zope. Basing your ZClasses on DataSkin makes the limitations pretty much disappear, from our point of view, because we never put any actual "implementation" code in our ZClasses: just domain logic, property sheets and UI (DTML) methods. All the actual mapping to/from data storage is carried out in the appropriate Rack or Specialist, neatly seperated. Occasionally we need an ExternalMethod in either the ZClass or the Specialist, but these are getting rarer as we find ways to create method-like helper objects that can be added through the Zope UI to accomplish common tasks. In general, we prefer that Python written outside of PythonMethods be re-usable for a variety of projects rather than a one-up for a specific application. YMMV. :)