[Zope-dev] Accessors for DataSkin attributes (was Re: [Zope-dev] Success!Was: Re: [Zope-dev] How is 'retrieveItem intended to work with TTWSpecialists? Was: Re: [Zope-dev] How is 'retrieveItem intended to work with TTW Specialists?
At 06:57 AM 10/5/00 -0500, Steve Spicklemire wrote: > >This brings up another point If I choose 'DataSkin' as a storage >class, then my code hits the security system every time a refer >to any data (simple types) stored directly in the DataSkin. I can either >set __allow_access_to_unprotected_subobjects=1 on each instance, >or I can write accessor methods for each attribute, (yuk!, but >maybe good in some ways...) or I can ask the integrator to create >'dummy' ZClass(es) even for those racks that they don't want/need >to customize (which seems to 'get around' the security system.) >I'm curious to know what you folks do here.. do you write accessor >methods for every type stored in your DataSkins? We never use raw DataSkins, first off. We always create a domain-specific ZClass subclassed from DataSkin. In your case, I would suggest simply including such ZClasses with your product to provide the default implementation of your domain and presentation logic. As for set/get methods, we usually just define DataSkin property sheets in the ZClass, and use permission mappings to define the read/write permissions for each sheet. We group properties in sheets according to the domain model permissions for access. Then the domain logic methods in the ZClass call propertysheets.sheetname.manage_changeProperties() with keyword parameters to set things. Usually, we have domain specific methods that alter the values of multiple attributes at the same time, using the property sheets. We rarely have code outside of the ZClass directly manipulate attributes. In instances where we've needed to set attributes which are of types not supported by Zope propertysheets, we've had to use ExternalMethods or something similar. In the long run we expect to be able to use PropertyHandlers to do this without dropping down to Python. ___ 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] Success! Was: Re: [Zope-dev] How is 'retrieveItem intended to work with TTW Specialists? Specialists?
Yes.. I see what you mean... this is a 'whitebox customization' that I used as part of the integration of my framework into the 'online catalog' system. This is not 'blackbox' code that is integral to my system In fact, I mis-spoke earlier, it's not in my specialist at all... it only appears in a method of a ZClass that I use as the 'storage class' for objects controlled by one of my specialists this is clearly whitebox territory, since this wrapper is chosen by the integrator... The first thing my docs (will) say to do.. is go through all my specialists and choose 'storage' classes for each specialist. This brings up another point If I choose 'DataSkin' as a storage class, then my code hits the security system every time a refer to any data (simple types) stored directly in the DataSkin. I can either set __allow_access_to_unprotected_subobjects=1 on each instance, or I can write accessor methods for each attribute, (yuk!, but maybe good in some ways...) or I can ask the integrator to create 'dummy' ZClass(es) even for those racks that they don't want/need to customize (which seems to 'get around' the security system.) I'm curious to know what you folks do here.. do you write accessor methods for every type stored in your DataSkins? Anyway.. thanks for the great tools! I'm having fun now. ;-) -steve > "Phillip" == Phillip J Eby <[EMAIL PROTECTED]> writes: Phillip> At 09:15 PM 10/4/00 -0500, Steve Spicklemire wrote: >> This was also nice since in my Specialist I could do things >> like: >> >> > "RESPONSE.redirect(this().theRealThing.absolute_url())"> >> >> After the user is finished working in my 'app area' they could >> get redirected back to the actual object that my Specialist was >> 'posing' for... Phillip> I don't really recommend the above, unless it's being Phillip> done by SkinScript. Otherwise, you're unnecessarily Phillip> exposing an implementation attribute (theRealThing). Phillip> Instead, require that your object implement a redirect() Phillip> method, and define it in the class as Phillip> "class_default_for_redirect". Then you can override the Phillip> method in SkinScript or with a class extender (a new Phillip> 0.4.3 feature). Doing it this way means your framework Phillip> code will not incorporate an assumption that your Phillip> whitebox specialist is always going to be wrapping Phillip> someone else's 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] Success! Was: Re: [Zope-dev] How is 'retrieveItem intended to work with TTW Specialists? Specialists?
At 09:15 PM 10/4/00 -0500, Steve Spicklemire wrote: > >This was also nice since in my Specialist I could do things >like: > > > >After the user is finished working in my 'app area' they could >get redirected back to the actual object that my Specialist >was 'posing' for... I don't really recommend the above, unless it's being done by SkinScript. Otherwise, you're unnecessarily exposing an implementation attribute (theRealThing). Instead, require that your object implement a redirect() method, and define it in the class as "class_default_for_redirect". Then you can override the method in SkinScript or with a class extender (a new 0.4.3 feature). Doing it this way means your framework code will not incorporate an assumption that your whitebox specialist is always going to be wrapping someone else's 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] How is 'retrieveItem intended to work with TTW Specialists?
At 08:05 AM 9/30/00 -0500, Steve Spicklemire wrote: > >I'd hate to find out later that someone needs to go in and edit my Python >code to make my framework useable But.. I think what I'm hearing is that >working out the integration at the Rack level is much better than trying >to delgate retrieval at the Specialist level. I'm not sure where I got the >idea that delegating retrieval at the Specialist level was the 'right' way, >maybe in the Drop Zone example? Anyway... thanks again for your reply. I'll You might have gotten it from there, in that the example doesn't get into any detail of *how* retrieval gets delegated. There are many ways to delegate retrieval, but direct delegation is only useful in the case where the thing you're delegating to already has the interface you want. In the example, it was assumed that the SkyDiver implemented the interfaces needed by the different black-box frameworks being re-used, and therefore delegated retrieval would have been the appropriate customization of the white-box specialists. The point, however, is that it's the application integrator's job to rip up your white-boxes in whatever way it takes to do the integration. Again, if they have built their crossover class (e.g. SkyDiver) according to the interface required by the white-boxes, then their customizations are trivial. If not, then they must do more work. If you want to make sure that someone needn't edit Python code, all you have to do is ensure that your Specialist never does any data manipulation except through altering attributes or propertysheets on a DataSkin, and that any multi-item methods (e.g. search methods) are TTW-overrideable methods (using the __replaceable__ property in your Python code). Then, the integrator can override those methods with SQL queries or catalog queries or whatever, and they can script the mappings of the DataSkin's attributes into whatever behavior they want. >march happily along now and see what I run into next! ;-) (I'm especially >grateful for your explaination of using a virtual object (non-persistent) >in a Rack. I've not seen that explained so clearly anywhere else.. and I'm >going to use it! Great. By the way, that is also how one makes a rack that retrieves objects from an SQL or LDAP database. You do a WITH/COMPUTE on the query that retrieves the record and maps it into the attributes you want. The latest version of SkinScript (not yet released) now has a QUERY keyword that makes use of SQL/LDAP queries easier, as you can do: WITH QUERY someSQLMethod(key=self.id) COMPUTE foo,bar,baz instead of having to do this junk: WITH (someSQLMethod(key=self.id) or [NOT_FOUND])[0] COMPUTE foo,bar,baz There is also now an OTHERWISE LET clause for WITH/COMPUTE that lets you specify default values in case the query doesn't find a record. These and a few other new SkinScript clauses should be out in 0.4.3, sometime mid-October. Ty and I have also developed some advanced tricks to allow an SQL database to refer to objects which are in LDAP or the ZODB, allowing one to store different parts of your data in databases which have the best performance or handling characteristics for that kind of data. However, to use these tricks you must specifically design your SQL database for the purpose. It's not terribly tricky, but it's a whole 'nother pattern language of its own, and we're not ready to "publish" yet. Especially since at this stage it'll be just another thing we've invented but not thoroughly documented for others to take advantage of. :( ___ 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] How is 'retrieveItem intended to work with TTW Specialists?
Thanks again... it's great that you're willing to entertain my apparantly twisted use of ZPatterns. ;-) > "PJE" == Phillip J Eby <[EMAIL PROTECTED]> writes: PJE> To put it another way: design your whitebox specialist how PJE> you want it. Make it complete, but of course some parts will PJE> have to be changed if someone wants to use other than your PJE> default implementation. If they want its data to come from PJE> somewhere else, they can plug in the SkinScript or do PJE> whatever else it takes. PJE> So, to sum up... Stop worrying about delegated retrieval! PJE> :) You're stepping into app integrator territory here. PJE> ZPatterns was designed to make it easy to make reusable PJE> frameworks without hardly trying. And it was *especially* PJE> designed for retrofitting object frameworks over legacy PJE> applications and databases. Hmm... OK I see what you mean. I guess I somehow got the idea that ZPatterns worked best when you had two ZPatterns based frameworks that you wanted to work together *after* they had both been designed. I was looking for a way to 'hook up' two 'finished' applications. I was trying to avoid creating a framework that couldn't be easily integrated, by attemting a 'fake' integration myself. How can I be sure I've got all the TTW stuff organized in a way that an integrator can change unless I actually set it up and test it that way? I'd hate to find out later that someone needs to go in and edit my Python code to make my framework useable But.. I think what I'm hearing is that working out the integration at the Rack level is much better than trying to delgate retrieval at the Specialist level. I'm not sure where I got the idea that delegating retrieval at the Specialist level was the 'right' way, maybe in the Drop Zone example? Anyway... thanks again for your reply. I'll march happily along now and see what I run into next! ;-) (I'm especially grateful for your explaination of using a virtual object (non-persistent) in a Rack. I've not seen that explained so clearly anywhere else.. and I'm going to use it! thanks! -steve ___ 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] How is 'retrieveItem intended to work with TTW Specialists?
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 change
Re: [Zope-dev] How is 'retrieveItem intended to work with TTW Specialists?
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? thanks! -steve > "pje" == Phillip J Eby <[EMAIL PROTECTED]> writes: pje> At 08:00 AM 9/25/00 -0500, Steve Spicklemire wrote: >> So my retrieve item gets called. *unfortunately* it gets >> called without any namespace parameter... so my retrieveItem >> DTML method has no way to acquire a namespace so that it can >> delagate to something else! >> >> So... here is what I did... I defined a method in my Python >> subclass of Specialist.. >> >> class MarketItemManager(ZPatterns.Specialists.Specialist): """A >> Market Item Manager""" >> >> # Specify a name for the item type: >> meta_type='MarketItemManager' >> >> def retrieveItem(self, key): """ get an item""" return >> self.__of__(self).delegateRetrieve(self, None, key=key) >> >> Then I made a DTML method called 'delegateRetrieve' like so: >> >> >> >> this way, my integrator can edit 'delegateRetrieve' to point to >> whatever Specialist he wants to... and I have a Python >> implementation of retrieveItem. >> >> Does this sound OK? Am I working way too hard here? (I feel >> like I am! ;-> ) >> pje> Remember in the code where I have "# XXX DTML check?" That's pje> because I was anticipating your problem, but since I didn't pje> personally need to do what you're doing yet, I didn't pje> implement it. For one thing, I was waiting to see if Zope pje> core method binding would get fixed. Unfortunately, I'm not pje> sure that Zope method binding is going to be available for pje> anything but PythonMethods in 2.3. As of right now, however, pje> you should be able to use a PythonMethod for retrieveItem, pje> rather than a DTML Method, and it should work. pje> In short, even now, delegateRetrieve should not be necessary. pje> You should be able to implement retrieveItem using a pje> PythonMethod or a DTML Document rather than a DTML Method. pje> (I say *should* because I have not tried it personally.) ___ 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] How is 'retrieveItem intended to work with TTW Specialists?
At 08:00 AM 9/25/00 -0500, Steve Spicklemire wrote: > >So my retrieve item gets called. *unfortunately* it gets >called without any namespace parameter... so my retrieveItem >DTML method has no way to acquire a namespace so that it can >delagate to something else! > >So... here is what I did... I defined a method in my Python >subclass of Specialist.. > >class MarketItemManager(ZPatterns.Specialists.Specialist): >"""A Market Item Manager""" > ># Specify a name for the item type: >meta_type='MarketItemManager' > >def retrieveItem(self, key): >""" get an item""" >return self.__of__(self).delegateRetrieve(self, None, key=key) > >Then I made a DTML method called 'delegateRetrieve' like so: > > > >this way, my integrator can edit 'delegateRetrieve' to point >to whatever Specialist he wants to... and I have a Python >implementation of retrieveItem. > >Does this sound OK? Am I working way too hard here? >(I feel like I am! ;-> ) > Remember in the code where I have "# XXX DTML check?" That's because I was anticipating your problem, but since I didn't personally need to do what you're doing yet, I didn't implement it. For one thing, I was waiting to see if Zope core method binding would get fixed. Unfortunately, I'm not sure that Zope method binding is going to be available for anything but PythonMethods in 2.3. As of right now, however, you should be able to use a PythonMethod for retrieveItem, rather than a DTML Method, and it should work. In short, even now, delegateRetrieve should not be necessary. You should be able to implement retrieveItem using a PythonMethod or a DTML Document rather than a DTML Method. (I say *should* because I have not tried it personally.) ___ 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] How is 'retrieveItem intended to work with TTW Specialists?
Hello ZPatterns Folk. I'm trying to implement 'delagation' with a custom Specialist. The idea, (I think this is one of the goals of ZPatterns... to allow delegation of responsibility after the Framework is built...) I have: a) MarketItemManager (Python subclass of Specialist) Some of methods, both DTML Methods, and plain old Python Methods, are *meant* to be acquire by the objects (DataSkins) he manages. b) ThingManager (ZClass subclass of Specialist). This is really just a test class that is supposed to represent some later developer integrating my ZPattern based EMarket into their application, (e.g., inventory or whatever...) in MarketItemManager I've defined a 'retrieveItem' (this would really be done by the integrator...) that does something like this: with the hope that when the Specialist class gets traversed it will execute: def __bobo_traverse__(self, REQUEST, name): ob = getattr(self, name, _marker) if ob is _marker: ob = self.getItem(name) <--- traversal invokes getItem if ob is not None: return ob raise 'NotFound' return ob def getItem(self, key): """Get an item""" if hasattr(self.aq_base,'retrieveItem'): <--- getItem invokes retrieveItem return self.retrieveItem(key=key) # XXX need DTML check? for rack in self.rackList: item = rack.__of__(self).getItem(key) if item is not None: return item So my retrieve item gets called. *unfortunately* it gets called without any namespace parameter... so my retrieveItem DTML method has no way to acquire a namespace so that it can delagate to something else! So... here is what I did... I defined a method in my Python subclass of Specialist.. class MarketItemManager(ZPatterns.Specialists.Specialist): """A Market Item Manager""" # Specify a name for the item type: meta_type='MarketItemManager' def retrieveItem(self, key): """ get an item""" return self.__of__(self).delegateRetrieve(self, None, key=key) Then I made a DTML method called 'delegateRetrieve' like so: this way, my integrator can edit 'delegateRetrieve' to point to whatever Specialist he wants to... and I have a Python implementation of retrieveItem. Does this sound OK? Am I working way too hard here? (I feel like I am! ;-> ) thanks, -steve ___ 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 )