On Thu, 05 Feb 2004 09:59:39 +0200 Etienne Labuschagne <elabuschagne@gmsonline.co.za> wrote:
Hi there,
I am using __setattr__ in my class to decide if the class needs to be reindexed or not. The problem is, the moment you enter the __setattr__ method, self is not acquisition wrapped anymore, which means that reindex_object does not work since it cannot acquire the Catalog.
This can be illustrated with the following small test class:
class AQTest(CatalogAware, SimpleItem): '''Test class''' meta_type = "Health Window Test"
def __setattr__(self, attrName, attrValue): if attrName.startswith('abc'): self.reindex_object() #This doesn't work, since self is no longer acquisition wrapped here, eg. self.aq_parent raises an error self.__dict__[attrName] = attrValue
def test(self): '''Test method''' self.abcname = 'John'
Any suggestions on how to fix this?
I think you have found that __setattr__ is too low-level for this to work. Many operations may do setattr without your knowing it also (like ZODB), so indexing there although attractive for automation purposes is not going to work in practice. The canonical, if less automated, way it is done is to have mutator methods change attributes and call reindex object at the end. If you want to, you could just have a single mutator method which lets you set any attributes. In fact this would be more efficent then reindexing on every attribute change. Plus you can protect it with permissions so it can be called from untrusted code:: def set(self, **kw): """Set attrbiutes and reindex""" for name, value in kw.items(): setattr(self, name, value) self.reindex_object() OTOH, this method doesn't give much guidance as to which attributes to set. In general it is considered bad practice to manipulate attributes of objects directly and informally. You could improve this without loosing generality however:: def set(self, **kw): """Set attrbiutes and reindex""" for name, value in kw.items(): getattr(self, name) # Assert the attribute exists setattr(self, name, value) self.reindex_object() Ultimately, this is probably best though:: def edit(self, foo=None, bar=None, baz=None): if foo is not None: self._foo = foo ... self.reindex_object() That makes it clear what is editable from the signature and breaks if you typo a name. hth, -Casey