Hello, I would like to know if it is possible for an object stored in a BTree to use acquisition to see its parent object (either the BTree itself or the object that holds the BTree). Here's an example of what I've tried: Python 2.1.1 (#1, Jul 29 2001, 19:04:01) [GCC 2.96 20000731 (Red Hat Linux 7.1 2.96-85)] on linux2 Type "copyright", "credits" or "license" for more information.
from Acquisition import Implicit from BTree import BTree
class A(Implicit): ... pass ... class B(Implicit): ... pass ... class D(Implicit, BTree): ... pass ... a = A()
a.d = D() a.d <D instance at 8118330> a.d.aq_parent <A instance at 8114c28> a.d[1] = B() a.d[1] <B instance at 8114c18> a.d[1].aq_parent Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: aq_parent
The Acquisition machinery has no problem with the regular objects. Class D, which wraps a BTree and implicit acquisition, lets the BTree see its parents, but an acquisition-enabled object placed in an acquisition-enabled BTree still can't see its parent. Any suggestions? Or is this a bad idea? Should I implement another mechanism? The number of objects stored in the BTrees in the final product is unlikely to be more than a few hundred, so another data type might work. Thanks, Joe
Joseph Barillari wrote:
Hello,
I would like to know if it is possible for an object stored in a BTree to use acquisition to see its parent object (either the BTree itself or the object that holds the BTree).
Here's an example of what I've tried:
Python 2.1.1 (#1, Jul 29 2001, 19:04:01) [GCC 2.96 20000731 (Red Hat Linux 7.1 2.96-85)] on linux2 Type "copyright", "credits" or "license" for more information.
from Acquisition import Implicit from BTree import BTree
class A(Implicit): ... pass ... class B(Implicit): ... pass ... class D(Implicit, BTree): ... pass ... a = A()
a.d = D() a.d <D instance at 8118330> a.d.aq_parent <A instance at 8114c28> a.d[1] = B() a.d[1] <B instance at 8114c18> a.d[1].aq_parent Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: aq_parent
The Acquisition machinery has no problem with the regular objects. Class D, which wraps a BTree and implicit acquisition, lets the BTree see its parents, but an acquisition-enabled object placed in an acquisition-enabled BTree still can't see its parent.
Any suggestions? Or is this a bad idea? Should I implement another mechanism? The number of objects stored in the BTrees in the final product is unlikely to be more than a few hundred, so another data type might work.
You should likely try another mechanism. A BTree's items don't consider the BTree to be their acquisition parent. And it's bad form to manually wrap them (via a = a.__of__(btreeinstance); btreeinstance['a'] =a) because when you stick an acquisition-wrapped object into a BTree, the buckets inside a BTree will eventually be committed to storage and aquisition wrappers can't be stored inside ZODB. Try storing a tuple as the value inside the BTree where the first element of the tuple is the path to the object you want to be the acqusition parent of the object you're storing, and the second element is the object (.e.g. ('/FolderA/SubfolderB', <object A>)), then use restrictedTraverse to get the object related to the path and manually wrap the object that is the second element in the one you get from restrictedTraverse (via __of__, e.g... path, ob = tup; ob = ob.__of__(self.restrictedTraverse(path)). -- Chris McDonough Zope Corporation http://www.zope.org http://www.zope.com "Killing hundreds of birds with thousands of stones"
On Tue, Aug 07, 2001 at 10:32:42PM -0400, Chris McDonough wrote: (snip quoted explanation of problem)
You should likely try another mechanism. A BTree's items don't consider the BTree to be their acquisition parent. And it's bad form to manually wrap them (via a = a.__of__(btreeinstance); btreeinstance['a'] =a) because when you stick an acquisition-wrapped object into a BTree, the buckets inside a BTree will eventually be committed to storage and aquisition wrappers can't be stored inside ZODB.
Try storing a tuple as the value inside the BTree where the first element of the tuple is the path to the object you want to be the acqusition parent of the object you're storing, and the second element is the object (.e.g. ('/FolderA/SubfolderB', <object A>)), then use restrictedTraverse to get the object related to the path and manually wrap the object that is the second element in the one you get from restrictedTraverse (via __of__, e.g... path, ob = tup; ob = ob.__of__(self.restrictedTraverse(path)).
Thanks! I tried storing the tuples, but two questions came up: (1) How do I access the elements of a tuple in a URL? accessing /BTreeName/BTreeKey/1(the tuple index)/SomeMethod doesn't seem to work. When Zope looks up the key in the BTree, it chokes on the tuple, complaining that it is missing a doc string. Since the object has a docstring, I assume it wants the tuple's docstring. This is impossible to satisfy, right? AFAIK, you can only attach docstrings to classes and methods. (2) Would it be easier just to add the parent URL to the object when it's inserted into the BTree? I.e., from the parent object, call self.data[key] = A() self.data[key].path = self.id* and when it's necessary to access the parent, call self.__of__(restrictedTraverse(self.path))? *on the assumption that the parent object is at the root level of the website. I tried a variant on this with the code I'm working on. Testing in the intended environment for the code (DTML that refers to data stored in lower-level objects) proved difficult, so I examined it with the debugger: (Note that a JTree is a class composed of a BTree mixed with implict acquisition.) (Pdb) self <Tournament instance at 875b2e8> (Pdb) self.jdb <JTree instance at 88a1e28> (Pdb) self.jdb['Homer Simpson'] <Judge instance at 88b3b50> (Pdb) self.jdb['Homer Simpson'].path 'foobar' (Pdb) self.jdb['Homer Simpson'].aq_parent *** AttributeError: class RoleManager has no attribute 'aq_parent' (Pdb) self.jdb['Homer Simpson'].restrictedTraverse(path) *** AttributeError: class RoleManager has no attribute '__getitem__' [snip syntax error] (Pdb) self.jdb['Homer Simpson'].restrictedTraverse(self.jdb['Homer Simpson'].restrictedTraverse(path)) *** AttributeError: class RoleManager has no attribute '__getitem__' I assume that I haven't imported and subclassed the modules I need to do this. However, at this point, the question is academic: I've stopped using BTrees to organize the data -- I'm using ordinary folders. I may switch to the BTreeFolder product if they prove inefficient. Thanks, Joe
Joseph Barillari writes:
(1) How do I access the elements of a tuple in a URL? accessing /BTreeName/BTreeKey/1(the tuple index)/SomeMethod doesn't seem to work. When Zope looks up the key in the BTree, it chokes on the tuple, complaining that it is missing a doc string. You do not (directly).
You can use a Python Script, say "P", with "traverse_subpath" bound and use: /BTreeName/P/BTreeeKey/1 Inside "P", you would have "traverse_subpath = ['BTreeKey','1']" and do with it what is adequate...
(2) Would it be easier just to add the parent URL to the object when it's inserted into the BTree? I.e., from the parent object, call self.data[key] = A() self.data[key].path = self.id* and when it's necessary to access the parent, call self.__of__(restrictedTraverse(self.path))? It seems that I lack essential context from previous thread history. At least this looks very strange....
The usual way would look something like: class Product(...): def __init__(self,...): self._btree= BTree(...) def accessor(self, key): return self._btree[key].__of__(self) But, as said, I do not know your precise problem.... Dieter
participants (3)
-
Chris McDonough -
Dieter Maurer -
Joseph Barillari