[Zope] reindex_object in __setattr__ method not working. (was: Losing acquisition wrapping between method calls)

Casey Duncan casey at zope.com
Thu Feb 5 12:34:14 EST 2004


On Thu, 05 Feb 2004 09:59:39 +0200
Etienne Labuschagne <elabuschagne at 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



More information about the Zope mailing list