[Zope3-checkins] CVS: Zope3/src/zope/app/services - field.py:1.5
Steve Alexander
steve@cat-box.net
Fri, 10 Jan 2003 13:46:58 -0500
Update of /cvs-repository/Zope3/src/zope/app/services
In directory cvs.zope.org:/tmp/cvs-serv6406/src/zope/app/services
Modified Files:
field.py
Log Message:
Created a ComponentLocation field to specify a location by path or by
dotted module name.
=== Zope3/src/zope/app/services/field.py 1.4 => 1.5 ===
--- Zope3/src/zope/app/services/field.py:1.4 Thu Jan 9 14:13:49 2003
+++ Zope3/src/zope/app/services/field.py Fri Jan 10 13:46:26 2003
@@ -22,6 +22,9 @@
from zope.app.traversing import traverse
from zope.exceptions import NotFoundError
from zope.app.interfaces.services.field import IComponentPath
+from zope.app.interfaces.services.field import IComponentLocation
+from zope.component import getServiceManager, getAdapter
+from zope.app.interfaces.services.service import INameResolver
class ComponentPath(Field):
@@ -47,3 +50,50 @@
if not self.type.isImplementedBy(component):
raise ValidationError("Wrong component type", value)
+class ComponentLocation(Field):
+
+ __implements__ = IComponentLocation
+
+ _type = unicode
+
+ def __init__(self, type, *args, **kw):
+ self.type = type
+ super(ComponentLocation, self).__init__(*args, **kw)
+
+ def _validate(self, value):
+ super(ComponentLocation, self)._validate(value)
+ component = locateComponent(value, self.context, self.type)
+
+
+def locateComponent(location, context, interface=None):
+ '''Located a component by traversal, or by a dotted module name.
+
+ If 'interface' is given, check that the located componenent implements
+ the given interface.
+ '''
+ if location.startswith('/'):
+ try:
+ component = traverse(context, location)
+ except NotFoundError:
+ raise ValidationError('Path for non-existent object', location)
+ else:
+ # Assume location is a dotted module name
+ if location.startswith('.'):
+ # Catch the error of thinking that this is just like
+ # a leading dot in zcml.
+ raise ValidationError(
+ "Module name must not start with a '.'", location)
+ # XXX Need to be careful here. Jim was going to look
+ # at whether a checkedResolve method is needed.
+ servicemanager = getServiceManager(context)
+ resolver = getAdapter(servicemanager, INameResolver)
+ try:
+ component = resolver.resolve(location)
+ except ImportError:
+ raise ValidationError("Cannot resolve module name", location)
+
+ if interface is not None and not interface.isImplementedBy(component):
+ raise ValidationError(
+ 'Component must be %s' % interface, location)
+
+ return component