At 03:14 PM 9/29/00 -0500, Steve Spicklemire wrote:
Thanks so much for the response...
It turns out, I tried the Python Method and it had the same basic problem as the DTML Method... however I've now moved on, using deletageRetrieve to a new thorny issue. ;-)
When I get an object from of another specialist it appears that it doies not inherit from my specialist, but from *its* specialist. (e.g., my framework specialist has methods that I want the dataskins to acquire). I've currently got it wrapped like so:
def retrieveItem(self, key): """ get an item....""" return self.delegateRetrieve(self, None, key=key).__of__(self)
I've tried several different combinations of __of__ etc, but none of them seems to allow the dataskin to acquire, for example, standard_html_header from my specialist. Is there any way to enforce acquisition at this level?
You can use aq_base before the __of__, but I wouldn't recommend it, because you'll be forcibly ripping off security-related data. Probably aq_explicit would work better, since it would prevent default acquisition but leave security acquisitions relatively intact. I still suspect, though, that your design is not optimal. If you actually need a "bridge" specialist that lets you change the behaviors of the thing you're accessing, then you should really just build a bridge specialist and not simply do directly delegated retrieval. What you want is to set up a rack in the specialist that creates a virtual object which gets all its attributes (the ones you care about, anyway) from an object retrieved from the other specialist. SkinScript example: WITH otherSpecialist.getItem(self.id) COMPUTE theRealThing = (RESULT is None) and NOT_FOUND or RESULT WITH self.theRealThing COMPUTE myAttr1 = RESULT.theirAttr1, myAttr2 = theirAttr2, # equivalent to myAttr2 = RESULT.theirAttr2 SomeAttr, # equivalent to SomeAttr = RESULT.SomeAttr myAttr5 = theirAttr1 * theirAttr6 # Shorthand way of copying attributes with the same names WITH self.theRealThing COMPUTE foo,bar,baz You would put this in a script inside a rack in your "bridge" specialist. You would set up the rack to be "non-persistent" and use "theRealThing" as the existence attribute. Now, when you access the rack, it will create a dummy object and try to look at its "theRealThing" attribute. This will cause the SkinScript to call the other Specialist and attempt retrieval. If it succeeds, theRealThing will equal the object and the Rack will consider the object to exist in the bridge specialist. If it fails, theRealThing will be a non-existent attribute and the Rack's getItem will return None. Let's say it has succeeded. You now have an object with no attributes loaded other than 'id' and 'theRealThing'. You attempt to access attribute SomeAttr. The second SkinScript declaration fires, and computes the values of myAttr1, myAttr2, SomeAttr, and myAttr5, caching them in the DataSkin. Voila. You now have a completely transformed object, in the context of *your* specialist, with *your* attribute names. It has no leftover acquisition context, but of course you had to have permission to access all those attributes on the object and to the specialist you retrieved it from. But here's the real kicker... You determine in *your* rack the precise ZClass it will be implemented as. In effect, you have rewrapped an object's data into another class. Okay, so that works for reads. What about writes? That's a little more complex, as you'll need to write something like: STORE foo,bar USING self.theRealThing.manage_changeProperties(foo=self.foo,bar=self.bar) For whatever combinations of properties are applicable. If the properties are on a sheet, the USING expression gets more complicated. Note, too, that we could have done transformations on the 'id' to look something up, and that we could also have multiple racks, each doing transformations from different Specialists. Now, you may be asking yourself, "This all looks incredibly flexible, but is it efficient?" Hell no, of course not. You are much better off, if you have the option, of specifying to your framework's user the requirements you have for objects in that part of your system. Then, when they are designing their system, they can get the names and features right, and you call *their* specialist for what you need. If they didn't do it the easy way, then it's again *their* responsibility to re-cast your whitebox as a bridge. (Note, by the way, that if the end-user's raw data is coming from something like an SQL database in the first place, then all they have to do is map from SkinScript to SQL, and this is *much* more efficient than mapping Specialist->Rack->Specialist->Rack->SQL, which involves many more layers of object creation, method calls, and security checks.) To put it another way: design your whitebox specialist how you want it. Make it complete, but of course some parts will have to be changed if someone wants to use other than your default implementation. If they want its data to come from somewhere else, they can plug in the SkinScript or do whatever else it takes. So, to sum up... Stop worrying about delegated retrieval! :) You're stepping into app integrator territory here. ZPatterns was designed to make it easy to make reusable frameworks without hardly trying. And it was *especially* designed for retrofitting object frameworks over legacy applications and databases.