[Zope3-dev] EventService, references, and subscription semantics
Shane Hathaway
shane@zope.com
Mon, 25 Feb 2002 17:38:05 -0500
Steve Alexander wrote:
> Casey Duncan wrote:
>
>>
>>
>>> Then, we still have the issue of what to use for references.
>>> We can use object references provided we're happy to only allow
>>> persistent objects to be passed to subscribe().
>>>
>>
>> This is the problem I tried to work on in my ExplicitObjectReferences
>> proposal. The problem with using regular object references is that the
>> subscriber looses its original context and the reference makes the
>> object persist even if it is deleted from its original location.
>>
>> So unless these two things aren't an issue, I don't think object
>> references will work for this. I will definitely not mind being wrong,
>> however.
>
>
> I thinnk you're wrong :-)
>
> The object references are only used in the EventService to keep a
> collection of subscribers.
In a current project here at ZC we've stumbled onto an idea that neatly
deals with the object reference problem: just encapsulate all references
as objects. When registering with the event service, register the
reference object. When the service fires the event, it first
dereferences the reference.
In fact, in practice, references seem to be easier to work with than
physical paths. Here is a prototype interface:
class IReference (Interface):
"""Provides a way to find an object without necessarily keeping a
strong reference."""
def dereference(context):
"""Returns the referenced object."""
Here is a simple path-based implementation for Zope2:
class DereferenceError (Exception):
"""Could not resolve a reference"""
class ReferenceByPath(Persistent):
"""Provides a path-based reference to an object."""
__implements__ = IReference
def __init__(self, object):
"""Retains a reference to the target object."""
self._path = object.getPhysicalPath()
def dereference(self, context):
"""Returns the original object, wrapped in the specified
context."""
path = self._path
try:
return self.restrictedTraverse(path).__of__(context)
except (AttributeError, KeyError):
raise DereferenceError, path
The nice thing is you can encapsulate both strong and weak references
this way. The reference could hold an absolute path, a relative path,
the object itself, a URL, a database query, etc.
Shane