[Zope-CMF] Re: How do deal with cmfcatalog-wrapped objects?
Philipp von Weitershausen
philipp at weitershausen.de
Fri Mar 31 07:11:58 EST 2006
yuppie wrote:
> Andreas Jung wrote:
>> we have a CMF-based application where I am trying to migrate from
>> TextIndexNG 2 -> 3.
>>
>> For a content-type class A I have configured an adapter to implement
>> IIndexableContent. However when the object is reindexed CMF wraps
>> the object as IndexableObjectWrapper which by itself implements
>> the IndexableObjectWrapper interface. The low-level indexer of TXNG
>> get the wrapped object and has no idea what to do with the object
>> since the interface of the wrapper shadows the interface of the
>> wrapped object.
>> Any idea how to deal with this problem?
>
> I'm currently fighting with the same issue. And I was in the process of
> writing a mail to the Zope-CMF list when your mail came in. AFAICS this
> is more a CMF issue than a Five issue, so I add Zope-CMF to the
> recipients list.
>
>
> Just for the records, I'm sure you already figured that out yourself:
>
> Plone 2.1 doesn't have this issue because it has no interface
> declaration on its ExtensibleIndexableObjectWrapper. If the wrapper
> doesn't have its own __providedBy__ attribute the __getattr__ method
> looks it up in the wrapped class, making the interface declarations
> completely transparent.
>
> Plone 2.5 has an interface declaration so I guess it has the same
> problem as the CMF.
>
>
> The quick and dirty solution would be to remove the interface
> declaration from the wrapper. The clean solution would be to make sure
> that all the interfaces that are actually provided - the wrapper
> interface *and* the interfaces of the wrapped object - can be looked up.
> But implementing that seems to require deeper knowledge of the interface
> machinery than I have.
This problem has already been solved in Zope 3. There we like to wrap
objects that don't provide ILocation (__parent__ and __name__
attributes) in something that *does* provide ILocation. The resulting
object is a proxy for the original object and in addition that it
provides __parent__ and __name__ attributes. The proxy provides whatever
the original object provides plus ILocation.
We call this concept a /decorator/. This is not to be confused with
Python 2.4's function decorators. In Zope 3's case, think of decorator
as a proxy that also adds stuff to the object (e.g. the ILocation API).
Hence, it decorates the original object, like a Christmas tree if you will.
There are two options:
1. I think for the long term, IndexableObjectWrapper could be made a
decorator. This works as follows:
from zope.proxy import getProxiedObject
from zope.app.decorator import Decorator
class IndexableObjectWrapper(Decorator):
def allowedRolesAndUsers(self):
ob = getProxiedObject(self)
allowed = {}
for r in rolesForPermissionOn(View, ob):
allowed[r] = 1
localroles = _mergedLocalRoles(ob)
for user, roles in localroles.items():
for role in roles:
if allowed.has_key(role):
allowed['user:' + user] = 1
if allowed.has_key('Owner'):
del allowed['Owner']
return list(allowed.keys())
2. In the short term we can apply the following trick
(IndexableObjectWrapper needs to be a new style class!):
from zope.interface import providedBy
from zope.interface.declarations import ObjectSpecificationDescriptor
from zope.interface.declarations import getObjectSpecification
from zope.interface.declarations import ObjectSpecification
class IndexableObjectSpecification(ObjectSpecificationDescriptor):
def __get__(self, inst, cls=None):
if inst is None:
return getObjectSpecification(cls)
else:
provided = providedBy(inst.__ob)
cls = type(inst)
return ObjectSpecification(provided, cls)
class IndexableObjectWrapper(object): # new-style!
implements(...) # it can implement as much as it wants
__providedBy__ = IndexableObjectSpecification()
...
This is obviously untested, but I'm pretty confident that this would work.
Philipp
More information about the Zope-CMF
mailing list