[Zope-CVS] CVS: Packages/pypes/pypes - event.py:1.6 extent.py:1.8
identity.py:1.15 interfaces.py:1.14 serviceconfig.py:1.4
services.py:1.6
Casey Duncan
casey at zope.com
Sun Mar 7 05:09:44 EST 2004
Update of /cvs-repository/Packages/pypes/pypes
In directory cvs.zope.org:/tmp/cvs-serv26459/pypes
Modified Files:
event.py extent.py identity.py interfaces.py serviceconfig.py
services.py
Log Message:
* Create util module and tests for shared functions, refactor other modules to use new functions
* Add attach() function to services to replace connection.add() for cases where we want service access without adding to the database.
* Add accesspointFrom() function to abstract service access better, refactor other code to use it
=== Packages/pypes/pypes/event.py 1.5 => 1.6 ===
--- Packages/pypes/pypes/event.py:1.5 Wed Mar 3 23:29:45 2004
+++ Packages/pypes/pypes/event.py Sun Mar 7 05:09:12 2004
@@ -24,6 +24,7 @@
from zope.interface import implements
from pypes.interfaces import IEventService
from pypes.exceptions import EventRegistrationError
+from pypes.util import mro, classKey, classFromKey
class PypesMessage(object):
@@ -53,7 +54,7 @@
raise TypeError, 'Event listener method registered is not callable'
if not isinstance(message_type, (type, ClassType)):
raise TypeError, 'Event listener message_type must be type or class'
- type_key = _msgTypeKey(message_type)
+ type_key = classKey(message_type)
pair = (WeakRef(obj), method_name)
try:
reglist = self._listeners[type_key]
@@ -65,7 +66,7 @@
self._listeners[type_key] = reglist # trigger persistence
def unregisterListener(self, obj, method_name, message_type):
- type_key = _msgTypeKey(message_type)
+ type_key = classKey(message_type)
try:
listeners = self._listeners[type_key]
listeners.remove((WeakRef(obj), method_name))
@@ -79,7 +80,7 @@
def unregisterAllListeners(self, message_type):
try:
- del self._listeners[_msgTypeKey(message_type)]
+ del self._listeners[classKey(message_type)]
except KeyError:
pass
@@ -96,7 +97,7 @@
def isListener(self, obj, message_type):
try:
- reglist = self._listeners[_msgTypeKey(message_type)]
+ reglist = self._listeners[classKey(message_type)]
except KeyError:
return False
else:
@@ -106,9 +107,9 @@
return False
def wouldReceive(self, obj, message_type):
- for super_type in _mro(message_type):
+ for super_type in mro(message_type):
try:
- reglist = self._listeners[_msgTypeKey(super_type)]
+ reglist = self._listeners[classKey(super_type)]
except KeyError:
continue
for listener, name in self._iterRegistrations(reglist):
@@ -118,7 +119,7 @@
def iterListeners(self, message_type):
try:
- reglist = self._listeners[_msgTypeKey(message_type)]
+ reglist = self._listeners[classKey(message_type)]
except KeyError:
# Nothing is registered for this type
return iter(())
@@ -132,9 +133,9 @@
def iterReceivers(self, message_type):
rlists = []
- for super_type in _mro(message_type):
+ for super_type in mro(message_type):
try:
- rlists.append(self._listeners[_msgTypeKey(super_type)])
+ rlists.append(self._listeners[classKey(super_type)])
except KeyError:
continue
if len(rlists) == 1:
@@ -161,24 +162,9 @@
def iterMessageTypes(self):
for typekey in self._listeners.keys():
- yield _msgTypeFromKey(typekey)
+ yield classFromKey(typekey)
# XXX Need to add mechanism to clean stale listener references
# perhaps this should be opportunistic as part of registerListener
# or a separate method or both
-def _mro(typeobj):
- """Calculate and return the method resolution order. Works for
- both new style type/classes and classic classes
- """
- try:
- return typeobj.mro()
- except AttributeError:
- # Old style class
- # XXX need to find a better spelling
- class NewStyle(typeobj, object):
- pass
- return NewStyle.mro()[1:-1]
-
-_msgTypeKey = cPickle.dumps
-_msgTypeFromKey = cPickle.loads
=== Packages/pypes/pypes/extent.py 1.7 => 1.8 ===
--- Packages/pypes/pypes/extent.py:1.7 Sun Feb 29 00:44:48 2004
+++ Packages/pypes/pypes/extent.py Sun Mar 7 05:09:12 2004
@@ -29,6 +29,7 @@
from pypes.interfaces import IExtentService, IExtentMap
from pypes.interfaces import IExtent, ICanonicalExtent, IDerivedExtent
from pypes.exceptions import SetLookupError
+from pypes.util import mro, classKey, classFromKey
class Extent:
@@ -199,7 +200,7 @@
self._subclasses = OOBTree() # Map class key => set of subclass keys
self._instances = OOBTree() # Map class key => id set of instances
listenForIdEvents(self, dbconn)
- dbconn.add(self) # Allow service access before commit
+ services.attach(self, dbconn) # Allow service access before commit
#self.update(dbconn)
def __getitem__(self, key):
@@ -216,7 +217,7 @@
def __iter__(self):
for key in self._instances.keys():
# XXX May need to handle mutation
- yield self[keyClass(key)]
+ yield self[classFromKey(key)]
def update(self):
raise NotImplementedError
@@ -323,17 +324,3 @@
for extent_map in self._extent_maps:
for extent in extent_map:
yield extent
-
-
-# XXX These should go to a utils module
-from pypes.event import _mro as mro
-from cPickle import loads
-from cPickle import dumps
-def classKey(obj):
- if ( isinstance(obj, type) or isinstance(obj, ClassType)):
- cls = obj
- else:
- cls = getattr(obj, '__class__', type(obj))
- return dumps(cls)
-
-keyClass = loads
=== Packages/pypes/pypes/identity.py 1.14 => 1.15 ===
--- Packages/pypes/pypes/identity.py:1.14 Thu Mar 4 00:09:50 2004
+++ Packages/pypes/pypes/identity.py Sun Mar 7 05:09:12 2004
@@ -163,7 +163,7 @@
else:
set._idset = idset
if dbconn is not None:
- dbconn.add(set)
+ services.attach(set, dbconn)
set._length = Length(len(idset))
return set
fromIdSet = classmethod(fromIdSet)
@@ -171,8 +171,8 @@
def add(self, obj):
if self._p_jar is None and getattr(obj, '_p_jar', None) is not None:
# If we are not associated with a database connection
- # add us to one from the child object so we can access services
- obj._p_jar.add(self)
+ # attach us to one from the child object so we can access services
+ services.attach(self, obj._p_jar)
ident = pypesid(obj)
if ident is None:
raise IdentityError, obj
@@ -245,19 +245,22 @@
def union(self, other):
return self.__class__.fromIdSet(
- union(self._idset, other._idset), dbconn=self._p_jar)
+ union(self._idset, other._idset),
+ dbconn=services.accesspointFrom(self))
__or__ = union
def difference(self, other):
return self.__class__.fromIdSet(
- difference(self._idset, other._idset), dbconn=self._p_jar)
+ difference(self._idset, other._idset),
+ dbconn=services.accesspointFrom(self))
__sub__ = difference
def intersection(self, other):
return self.__class__.fromIdSet(
- intersection(self._idset, other._idset), dbconn=self._p_jar)
+ intersection(self._idset, other._idset),
+ dbconn=services.accesspointFrom(self))
__and__ = intersection
@@ -299,7 +302,7 @@
for set in identity_sets:
idsets.append(set._idset)
if dbconn is None:
- dbconn = getattr(set, '_p_jar', None)
+ dbconn = services.accesspointFrom(set)
idunion = IIBTree.multiunion(idsets)
return IdentitySet.fromIdSet(idunion, dbconn=dbconn)
@@ -312,7 +315,7 @@
idsect = None
for set in identity_sets:
if dbconn is None:
- dbconn = getattr(set, '_p_jar', None)
+ dbconn = services.accesspointFrom(set)
if not set:
# Short circuit on empty set
return IdentitySet()
=== Packages/pypes/pypes/interfaces.py 1.13 => 1.14 ===
--- Packages/pypes/pypes/interfaces.py:1.13 Mon Mar 1 01:36:15 2004
+++ Packages/pypes/pypes/interfaces.py Sun Mar 7 05:09:12 2004
@@ -666,13 +666,13 @@
execute queries and generate results"""
def inputs():
- """Return the query inputs and names as a sequence of
- (name, input) pairs
- """
+ """Return the query inputs as a dict keyed by input name"""
def rawResults():
- """Return the current results in raw form cooresponding to the inputs:
- a sequence of (input name, result collection) pairs
+ """Return the current results in raw form as a dict with
+ input name, result sequence as its respective key/value pairs.
+ These results should be suitable for use as inputs for another
+ query engine
"""
def results(projection):
=== Packages/pypes/pypes/serviceconfig.py 1.3 => 1.4 ===
--- Packages/pypes/pypes/serviceconfig.py:1.3 Mon Feb 9 16:14:57 2004
+++ Packages/pypes/pypes/serviceconfig.py Sun Mar 7 05:09:12 2004
@@ -53,6 +53,8 @@
registry = connection.root()[registry_name]
if registry.has_key(name):
raise PypesError, 'Service %s already exists' % name
+ if service._p_jar is None:
+ connection.add(service)
registry[name] = service
@@ -60,6 +62,8 @@
"""Like add service, but will also replace existing services. Use with
care, since services can contain user data."""
registry = connection.root()[registry_name]
+ if service._p_jar is None:
+ connection.add(service)
registry[name] = service
=== Packages/pypes/pypes/services.py 1.5 => 1.6 ===
--- Packages/pypes/pypes/services.py:1.5 Mon Feb 16 00:54:03 2004
+++ Packages/pypes/pypes/services.py Sun Mar 7 05:09:12 2004
@@ -33,17 +33,16 @@
Usage: services.get(someobj, 'identity')::
- accesspoint -- An IAppConnection or an IPersistent object. The database
- connection for the object must be open for the call to succeed.
+ accesspoint -- A zodb connection, and object in the database or an
+ object attached to the conection via the attach() function.
name -- String name of the service.
"""
- if isinstance(accesspoint, Persistent):
- accesspoint = accesspoint._p_jar
- root = accesspoint.root()
+ accesspoint = accesspointFrom(accesspoint)
try:
+ root = accesspoint.root()
return root[registry_name][name]
- except KeyError:
+ except (KeyError, AttributeError):
raise PypesLookupError, 'Service %s could not be accessed.' % name
@@ -75,8 +74,7 @@
Usage: svcs = services.all(someobj)
"""
- if isinstance(accesspoint, Persistent):
- accesspoint = accesspoint._p_jar
+ accesspoint = accesspointFrom(accesspoint)
try:
return dict(accesspoint.root()[registry_name])
except KeyError:
@@ -84,5 +82,39 @@
except (AttributeError, TypeError):
raise PypesLookupError, 'Invalid connection object.'
-
-
+def attach(obj, conn):
+ """Attaches obj to the pypes services for conn. obj can then be used as
+ an access point for other services.
+
+ You can also add the object to the connection to do this, but that
+ persists obj. attach() allows you to attach objects to services without
+ persisting them immediately. attached objects can still be persisted later
+ if desired.
+
+ If obj is already added to conn, do nothing. Raise PypeError if obj is
+ already attached or added to another connection. Raise TypeError if
+ obj is not persistent
+ """
+ if not isinstance(obj, Persistent):
+ raise TypeError, 'expected persistent instance first argument'
+ obj_conn = getattr(obj, '_p_jar', None)
+ if obj_conn is None:
+ # Object not added to any connection
+ obj._v_pypes_connection_ = conn
+ elif obj_conn is not conn:
+ raise PypesError, 'object already added to another connection'
+
+def accesspointFrom(obj):
+ """Return the service accesspoint (a zodb connection) for obj. obj can
+ be a zodb connection, an object in the database or an object attached to
+ the connection via the attach() function. Return None if
+ obj cannot be used as an accesspoint.
+ """
+ if isinstance(obj, Connection):
+ return obj
+ else:
+ try:
+ return obj._p_jar or obj._v_pypes_connection_
+ except AttributeError:
+ return None
+
More information about the Zope-CVS
mailing list