At 09:24 AM 8/29/00 +0100, Steve Alexander wrote:
Shane Hathaway wrote:
Bill Anderson wrote:
Any chance at a BTree Folder w/customizer support in the near future? :)
It should be quite easy to do. I vaguely recall Steve A or Steve S might have done it.
I want to include a BTreeFolder w/ Customizer support in the next release of DataSkinAddons.
If anyone's done one, and you're happy for it to be included in DataSkinAddons, please let me know.
Otherwise, I'll work on this later today.
I've just produced a BTreeDataSkin: ---- BTreeDataSkin is a DataSkin that is an ObjectManager. The ObjectManager stores subobjects in a BTree that is directly in the object (not stored in an attribute provider). On __getattr__, subobject ids are searched before the datamanager is asked to provide attributes. ----
If I may offer a suggestion... it would probably be a lot cleaner to implement this as an AttributeProvider, and use the dataskin's "persistent data slot" to store the b-tree. Otherwise, your b-tree contents can only be used with DataSkins which are not stored "virtually" in a Rack. If you use the slot API, it will work with any DataSkin. In other words, a BTreeAttributeProvider which simply stores attributes in a persistent BTree. Such a thing would be useful independent of the BTreeFolder user interface and could work with any DataSkin. Here's some code that implements a similar notion (using a dictionary in the DataSkin's storage slot, rather than a BTree). It's from the version of ZPatterns I'm currently working on. eaKey = 'ZPatterns.AttributeProviders', 'ExternalAttributes' class ExternalAttributeProvider(AttributeProvider): """ This attribute provider stores persistent attributes outside the object itself, in its persistent 'slot'. This allows persistent attributes to be used even with non-persistent DataSkins (e.g. those which are only virtually stored in a Rack. """ def _AttributeFor(self,client,name,default=None): return client._v_readableSlot.get(eaKey,{}).get(name,default) def _SetAttributeFor(self,client,name,value): """Set the attribute and return true if successful""" attrs = client._v_readableSlot.get(eaKey,{}); attrs[name]=value client._v_writeableSlot[eaKey] = attrs return 1 def _DelAttributeFor(self,client,name): """Delete the attribute and return true if successful""" if client._v_changedAttrs_[name] is NOT_FOUND: del client._v_changedAttrs_[name] attrs = client._v_readableSlot.get(eaKey,{}) if attrs.has_key(name): del attrs[name] client._v_writeableSlot[eaKey] = attrs return 1 # Class Metadata meta_type='Persistent External Attribute Provider' The code works by handling a persistent "slot". Currently, slots are used only by Persistent PropertySheet Providers to store propertysheets. The "_v_readableSlot"/"_v_writeableSlot" objects refer to a PersistentMapping which is associated with the DataSkin. By convention, the entries in the persistent mapping are keyed with a tuple that is the module name and purpose of the entry. This is why things are written to client._v_writableSlot[eaKey] -- eaKey is a constant that ensures that other providers needing to use the slot for persistent storage will not collide with it. You could probably take the code above, and, with some adaptation, produce a BTreeExternalAttributeProvider which used a BTree in place of a dictionary to store the attributes. You would need, of course, to use a different constant tuple to key the slot. _v_readableSlot always returns either a PersistentMapping, or an empty dictionary if the DataSkin's slot has never been written to. _v_writeableSlot always returns a PersistentMapping, ready to be written to. Once _v_writeableSlot has been accessed even once, the slot exists and _v_readableSlot will return the same PersistentMapping object as _v_writeableSlot. This rather odd-seeming setup is to prevent accidental changes to persistent storage when no changes have actually been made.