[Checkins] SVN: zope.generic/trunk/src/zope/generic/ add new directive generic:configurationAdapter that allows to register adapters for configuration without the duty of implementing an own adapter factory.

Dominik Huber dominik.huber at perse.ch
Thu Apr 20 12:26:39 EDT 2006


Log message for revision 67179:
  add new directive generic:configurationAdapter that allows to register adapters for configuration without the duty of implementing an own adapter factory.

Changed:
  U   zope.generic/trunk/src/zope/generic/configuration/README.txt
  U   zope.generic/trunk/src/zope/generic/configuration/adapter.py
  U   zope.generic/trunk/src/zope/generic/configuration/api.py
  A   zope.generic/trunk/src/zope/generic/configuration/meta.zcml
  A   zope.generic/trunk/src/zope/generic/configuration/metaconfigure.py
  A   zope.generic/trunk/src/zope/generic/configuration/metadirectives.py
  U   zope.generic/trunk/src/zope/generic/configuration/testing.py
  U   zope.generic/trunk/src/zope/generic/configuration/tests.py
  D   zope.generic/trunk/src/zope/generic/configuration/zope.generic.component-configure.zcml
  A   zope.generic/trunk/src/zope/generic/configuration/zope.generic.configuration-meta.zcml
  U   zope.generic/trunk/src/zope/generic/informationprovider/api.py
  U   zope.generic/trunk/src/zope/generic/informationprovider/base.py
  U   zope.generic/trunk/src/zope/generic/keyface/README.txt
  U   zope.generic/trunk/src/zope/generic/keyface/api.py
  U   zope.generic/trunk/src/zope/generic/type/adapter.py
  U   zope.generic/trunk/src/zope/generic/type/helper.py
  U   zope.generic/trunk/src/zope/generic/type/metaconfigure.py
  U   zope.generic/trunk/src/zope/generic/type/tests.py

-=-
Modified: zope.generic/trunk/src/zope/generic/configuration/README.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/README.txt	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/README.txt	2006-04-20 16:26:37 UTC (rev 67179)
@@ -204,3 +204,74 @@
     >>> [(key.__name__, value) for key, value in event.items()]
     [('IFooConfiguration', {})]
 
+
+Configuration Adapter
+---------------------
+
+The directive generic:configurationAdapter allows to register trusted, locatable
+adapters to a configuration schema.
+
+First we declare a configuration schema that should adapted:
+
+    >>> from zope.schema import TextLine
+
+    >>> class IFooConfiguration(interface.Interface):
+    ...    foo = TextLine(title=u'Foo', required=False, default=u'Default config.')
+
+We register the configuration schema using generic:keyface directive:
+
+    >>> registerDirective('''
+    ... <generic:keyface
+    ...     keyface="example.IFooConfiguration"
+    ...     type="zope.generic.configuration.IConfigurationType"
+    ...     />
+    ... ''') 
+
+    >>> from zope.generic.configuration import IConfigurationType
+    >>> IConfigurationType.providedBy(IFooConfiguration)
+    True
+
+We implement a class which is providing the configuration mechanism:
+
+    >>> class IFoo(interface.Interface):
+    ...    pass
+
+    >>> registerDirective('''
+    ... <generic:keyface
+    ...     keyface="example.IFoo"
+    ...     />
+    ... ''')
+
+    >>> class Foo(object):
+    ...     interface.implements(IFoo, api.IAttributeConfigurable)
+
+    >>> foo = Foo()
+
+    >>> api.queryConfiguration(foo, IFooConfiguration) is None
+    True
+
+Now we can provide an configuration adapter by a corresponding registration:
+
+    >>> registerDirective('''
+    ... <generic:configurationAdapter
+    ...     keyface="example.IFoo"
+    ...     provides="example.IFooConfiguration"
+    ...     readPermission="zope.Public"
+    ...     writePermission="zope.Public"
+    ...     />
+    ... ''')
+
+We can adapt our foo to IFooConfiguration:
+
+    >>> adapted = IFooConfiguration(foo)
+    >>> IFooConfiguration.providedBy(adapted)
+    True
+    >>> adapted.foo
+    u'Default config.'
+
+    >>> adapted.foo = u'Foo config.'
+    >>> adapted.foo
+    u'Foo config.'
+
+    >>> api.queryConfiguration(foo, IFooConfiguration).foo
+    u'Foo config.'

Modified: zope.generic/trunk/src/zope/generic/configuration/adapter.py
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/adapter.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/adapter.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -26,14 +26,17 @@
 from zope.app.location.interfaces import ILocation
 from zope.component import adapts
 from zope.event import notify
+from zope.interface import classImplements
 from zope.interface import implements
 
+from zope.generic.keyface import IAttributeKeyfaced
 from zope.generic.keyface.api import toDottedName
 from zope.generic.keyface.api import toKeyface
 
 from zope.generic.configuration import IAttributeConfigurable
 from zope.generic.configuration import IConfigurationType
 from zope.generic.configuration import IConfigurations
+from zope.generic.configuration.base import ConfigurationData
 from zope.generic.configuration.event import Configuration
 from zope.generic.configuration.event import ObjectConfiguredEvent
 from zope.generic.configuration.helper import configuratonToDict
@@ -141,3 +144,171 @@
         if ILocation.providedBy(parent) and parent.__parent__ is not None:
             notify(ObjectConfiguredEvent(parent, 
                 Configuration(keyface, {})))
+
+
+
+_marker = object()
+
+class ConfigurationAdapterProperty(object):
+    """Compute configuration adapter attributes based on schema fields
+
+    Field properties provide default values, data validation and error messages
+    based on data found in field meta-data.
+
+    Note that ConfigurationAdapterProperty cannot be used with slots. 
+    They can only be used for attributes stored in instance configurations
+    dictionaries.
+    """
+
+    def __init__(self, field, name=None):
+        if name is None:
+            name = field.__name__
+
+        self._field = field
+        self._name = name
+
+    def __get__(self, inst, klass):
+        if inst is None:
+            return self
+
+        configurations = inst.__configurations__
+        keyface = inst.__keyface__
+        context = inst.__context__
+
+        # evaluate configuration
+        configuration = inst.__keyface__(configurations, None)
+        value = getattr(configuration, self._name, _marker)
+        if value is _marker:
+            field = self._field.bind(inst)
+            value = getattr(field, 'default', _marker)
+            if value is _marker:
+                raise AttributeError(self._name)
+
+        return value
+
+    def __set__(self, inst, value):
+        field = self._field.bind(inst)
+        field.validate(value)
+        if field.readonly:
+            raise ValueError(self._name, 'field is readonly')
+
+        configurations = inst.__configurations__
+        keyface = inst.__keyface__
+        # update existing configuration
+        if keyface in configurations:
+            configurations.update(keyface, {self.__name: value})
+            
+        # create a new configuration
+        else:
+            configurations[keyface] = ConfigurationData(keyface, {self._name: value})
+
+        inst.__dict__[self._name] = value
+
+    def __getattr__(self, name):
+        return getattr(self._field, name)
+
+
+
+class ConfigurationAdapterBase(Location):
+    """Base mixin for simple configuration adapter."""
+
+    __keyface__ = None
+
+    def __init__(self, context):
+        self.__context__ = context
+        self.__configurations__ = IConfigurations(context)
+
+
+
+def ConfigurationAdapterClass(keyface, bases=(), property=None):
+    """Generic configuration adapter class factory.
+
+    The generic configuration adapter is a generic adapter class for 
+    instances providing configurations. First we declare a configuration
+    schema:
+
+        >>> from zope.schema import TextLine
+
+        >>> class IFooConfiguration(interface.Interface):
+        ...    foo = TextLine(title=u'Foo', required=False, default=u'Default config.')
+
+    We register the configuration schema using generic:keyface directive:
+
+        >>> registerDirective('''
+        ... <generic:keyface
+        ...     keyface="example.IFooConfiguration"
+        ...     type="zope.generic.configuration.IConfigurationType"
+        ...     />
+        ... ''') 
+
+        >>> from zope.generic.configuration import IConfigurationType
+        >>> IConfigurationType.providedBy(IFooConfiguration)
+        True
+
+    We implement a class which is providing the configuration mechanism:
+    
+        >>> class IFoo(interface.Interface):
+        ...    pass
+
+        >>> registerDirective('''
+        ... <generic:keyface
+        ...     keyface="example.IFoo"
+        ...     />
+        ... ''')
+
+        >>> class Foo(object):
+        ...     interface.implements(IFoo, api.IAttributeConfigurable)
+
+        >>> foo = Foo()
+
+        >>> api.queryConfiguration(foo, IFooConfiguration) is None
+        True
+
+    The simple configuration adapter function will construct an adapter class
+    implementing the IFooConfiguration interface:
+
+        >>> from zope.generic.configuration.adapter import ConfigurationAdapterClass
+        
+        >>> FooConfigurationAdapter = ConfigurationAdapterClass(IFooConfiguration)
+        >>> IFooConfiguration.implementedBy(FooConfigurationAdapter)
+        True
+
+    We can adapt our foo to IFooConfiguration:
+
+        >>> adapted = FooConfigurationAdapter(foo)
+        >>> IFooConfiguration.providedBy(adapted)
+        True
+        >>> adapted.foo
+        u'Default config.'
+
+        >>> adapted.foo = u'Foo config.'
+        >>> adapted.foo
+        u'Foo config.'
+
+        >>> api.queryConfiguration(foo, IFooConfiguration).foo
+        u'Foo config.'
+
+    """
+
+    # preconditions
+    if not IConfigurationType.providedBy(keyface):
+        raise ValueError('Interface must provide %s.' % IConfigurationType.__name__)
+
+    # essentails
+    if not bases:
+        bases = (ConfigurationAdapterBase, )
+
+    class_ = type('ConfigurationAdapterClass from %s' % keyface, bases,
+                  {'__keyface__': keyface})
+
+    classImplements(class_, keyface)
+    
+    if property is None:
+        property = ConfigurationAdapterProperty
+
+    # add field properties for each object field
+    for name in keyface:
+        field = keyface[name]
+        setattr(class_, name, property(keyface[name]))
+
+    return class_

Modified: zope.generic/trunk/src/zope/generic/configuration/api.py
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/api.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/api.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -20,5 +20,23 @@
 
 from zope.generic.configuration import *
 from zope.generic.configuration.adapter import AttributeConfigurations
+from zope.generic.configuration.adapter import ConfigurationAdapterClass
+from zope.generic.configuration.adapter import ConfigurationAdapterProperty
 from zope.generic.configuration.base import ConfigurationData
 from zope.generic.configuration.helper import configuratonToDict
+
+
+
+def getConfiguration(context, configuration):
+    """Evaluate a configuration."""
+    return configuration(IConfigurations(context))
+
+
+
+def queryConfiguration(context, configuration, default=None):
+    """Evaluate a configuration or return default."""
+    try:
+        return getConfiguration(context, configuration)
+    
+    except:
+        return default

Added: zope.generic/trunk/src/zope/generic/configuration/meta.zcml
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/meta.zcml	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/meta.zcml	2006-04-20 16:26:37 UTC (rev 67179)
@@ -0,0 +1,15 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:meta="http://namespaces.zope.org/meta">
+
+  <meta:directives namespace="http://namespaces.zope.org/generic">
+
+    <meta:directive
+        name="configurationAdapter"
+        schema=".metadirectives.IConfigurationAdapterDirective"
+        handler=".metaconfigure.configurationAdapterDirective"
+        />
+
+  </meta:directives>
+
+</configure>


Property changes on: zope.generic/trunk/src/zope/generic/configuration/meta.zcml
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zope.generic/trunk/src/zope/generic/configuration/metaconfigure.py
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/metaconfigure.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/metaconfigure.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Copyright (c) 2005, 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+"""
+$Id$
+"""
+
+__docformat__ = 'restructuredtext'
+
+from zope.app.component.contentdirective import ClassDirective
+from zope.app.component.metaconfigure import adapter
+
+from zope.generic.configuration.adapter import ConfigurationAdapterClass
+
+
+
+def configurationAdapterDirective(_context, keyface, provides, class_=None, writePermission=None, readPermission=None):
+    """Provide a generic configuration adatper."""
+
+    # we will provide a generic adapter class
+    if class_ is None:
+        class_ = ConfigurationAdapterClass(provides)
+
+    # register class
+    class_directive = ClassDirective(_context, class_)
+    if writePermission:
+        class_directive.require(_context, permission=writePermission, set_schema=[keyface])
+
+    if readPermission:
+        class_directive.require(_context, permission=readPermission, interface=[keyface])
+
+    # register adapter
+    adapter(_context, factory=[class_], provides=provides, 
+            for_=[keyface], permission=None, name='', trusted=True, 
+            locate=False)


Property changes on: zope.generic/trunk/src/zope/generic/configuration/metaconfigure.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zope.generic/trunk/src/zope/generic/configuration/metadirectives.py
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/metadirectives.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/metadirectives.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# Copyright (c) 2005, 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+"""
+$Id$
+"""
+
+__docformat__ = 'restructuredtext'
+
+from zope.app.i18n import ZopeMessageFactory as _
+from zope.app.security.fields import Permission
+from zope.configuration.fields import GlobalInterface
+from zope.configuration.fields import GlobalObject
+from zope.interface import Interface
+
+
+
+class IConfigurationAdapterDirective(Interface):
+    """Provide an adapter to a certain configuration."""
+
+    keyface = GlobalInterface(
+        title=_('Key Interface3'),
+        description=_('Configuration interface defining adapter interface.'),
+        required=True
+        )
+
+    provides = GlobalInterface(
+        title=_('Configuration Key Interface3'),
+        description=_('Configuration interface defining adapter interface.'),
+        required=True
+        )
+
+    class_ = GlobalObject(
+        title=_('Adapter class'),
+        description=_('If not declared a generic implementation will be used.'),
+        required=False
+        )
+
+    writePermission = Permission(
+        title=_('Write Permission'),
+        description=_('Specifies the permission by id that will be required ' +
+            ' to mutate the attributes and methods specified.'),
+        required=False,
+        )
+
+    readPermission = Permission(
+        title=_('Read Permission'),
+        description=_('Specifies the permission by id that will be required ' +
+            ' to accessthe attributes and methods specified.'),
+        required=False,
+        )
+


Property changes on: zope.generic/trunk/src/zope/generic/configuration/metadirectives.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: zope.generic/trunk/src/zope/generic/configuration/testing.py
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/testing.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/testing.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -76,6 +76,10 @@
     provideAdapter(zope.generic.configuration.adapter.AttributeConfigurations,
         provides=IConfigurations)
 
+    # register the directive of this package
+    import zope.generic.configuration
+    XMLConfig('meta.zcml', zope.generic.configuration)()
+
 def tearDown(doctest=None):
     pass
 

Modified: zope.generic/trunk/src/zope/generic/configuration/tests.py
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/tests.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/tests.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -69,7 +69,14 @@
         doctest.DocTestSuite('zope.generic.configuration.helper'),
         doctest.DocTestSuite('zope.generic.configuration.base'),
         doctest.DocTestSuite('zope.generic.configuration.event'),
-        doctest.DocTestSuite('zope.generic.configuration.adapter'),
+        doctest.DocTestSuite('zope.generic.configuration.adapter',
+                             setUp=testing.placelesssetup.setUp,
+                             tearDown=testing.placelesssetup.tearDown,
+                             globs={'component': component, 'interface': interface,
+                             'registerDirective': registerDirective,
+                             'testing': testing, 'api': api},
+                             optionflags=doctest.NORMALIZE_WHITESPACE+
+                                            doctest.ELLIPSIS),
         doctest.DocFileSuite('README.txt',
                              setUp=testing.placelesssetup.setUp,
                              tearDown=testing.placelesssetup.tearDown,

Deleted: zope.generic/trunk/src/zope/generic/configuration/zope.generic.component-configure.zcml
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/zope.generic.component-configure.zcml	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/zope.generic.component-configure.zcml	2006-04-20 16:26:37 UTC (rev 67179)
@@ -1,5 +0,0 @@
-<configure xmlns="http://namespaces.zope.org/zope">
-
-  <include package="zope.generic.configuration" />
-
-</configure>

Added: zope.generic/trunk/src/zope/generic/configuration/zope.generic.configuration-meta.zcml
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/zope.generic.configuration-meta.zcml	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/configuration/zope.generic.configuration-meta.zcml	2006-04-20 16:26:37 UTC (rev 67179)
@@ -0,0 +1,5 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+  <include package="zope.generic.configuration" file="meta.zcml" />
+
+</configure>


Property changes on: zope.generic/trunk/src/zope/generic/configuration/zope.generic.configuration-meta.zcml
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: zope.generic/trunk/src/zope/generic/informationprovider/api.py
===================================================================
--- zope.generic/trunk/src/zope/generic/informationprovider/api.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/informationprovider/api.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -21,8 +21,8 @@
 from zope.app.annotation import IAnnotations
 from zope.component import getUtilitiesFor
 from zope.component import getUtility
-from zope.generic.keyface.api import getKey
-from zope.generic.keyface.api import queryKey
+from zope.generic.keyface.api import getKeyface
+from zope.generic.keyface.api import queryKeyface
 from zope.generic.keyface.api import toDottedName
 from zope.generic.keyface.api import toKeyface
 
@@ -38,7 +38,7 @@
 def getInformationProvider(object, provider=IInformationProviderInformation):
     """Evaluate an information provider for an object."""
 
-    return getUtility(provider, toDottedName(getKey(object)))
+    return getUtility(provider, toDottedName(getKeyface(object)))
 
 
 

Modified: zope.generic/trunk/src/zope/generic/informationprovider/base.py
===================================================================
--- zope.generic/trunk/src/zope/generic/informationprovider/base.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/informationprovider/base.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -18,12 +18,16 @@
 
 __docformat__ = 'restructuredtext'
 
-from zope.app.annotation.interfaces import IAttributeAnnotatable
+from zope.app.annotation import IAnnotations
+from zope.app.annotation import IAttributeAnnotatable
+from zope.app.annotation.attribute import AttributeAnnotations
 from zope.app.i18n import ZopeMessageFactory as _
 from zope.interface import alsoProvides
 from zope.interface import implements
 
 from zope.generic.configuration import IAttributeConfigurable
+from zope.generic.configuration import IConfigurations
+from zope.generic.configuration.api import AttributeConfigurations
 from zope.generic.keyface.api import KeyfaceDescription
 
 from zope.generic.informationprovider import IInformationProvider
@@ -76,4 +80,11 @@
 
     def __init__(self, keyface, provides, label=None, hint=None):
         super(InformationProvider, self).__init__(keyface, label, hint)
-        alsoProvides(self, provides)
\ No newline at end of file
+        alsoProvides(self, provides)
+
+    def __conform__(self, interface):
+        if interface is IConfigurations:
+            return AttributeConfigurations(self)
+
+        elif interface is IAnnotations:
+            return AttributeAnnotations(self)
\ No newline at end of file

Modified: zope.generic/trunk/src/zope/generic/keyface/README.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/keyface/README.txt	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/keyface/README.txt	2006-04-20 16:26:37 UTC (rev 67179)
@@ -61,24 +61,24 @@
 
 The api provides convenience functions to get the key interfaces of components:
 
-    >>> api.getKey(fookeyfaced) == IFooMarker
+    >>> api.getKeyface(fookeyfaced) == IFooMarker
     True
     
-    >>> api.getKey(fookeyface) == IFooMarker
+    >>> api.getKeyface(fookeyface) == IFooMarker
     True
 
-    >>> api.getKey(object())
+    >>> api.getKeyface(object())
     Traceback (most recent call last):
     ...
     TypeError: ('Could not adapt', ...)
 
-    >>> api.queryKey(fookeyfaced) == IFooMarker
+    >>> api.queryKeyface(fookeyfaced) == IFooMarker
     True
     
-    >>> api.queryKey(fookeyface) == IFooMarker
+    >>> api.queryKeyface(fookeyface) == IFooMarker
     True
 
-    >>> api.queryKey(object()) == None
+    >>> api.queryKeyface(object()) == None
     True
 
 

Modified: zope.generic/trunk/src/zope/generic/keyface/api.py
===================================================================
--- zope.generic/trunk/src/zope/generic/keyface/api.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/keyface/api.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -27,7 +27,7 @@
 
 
 
-def getKey(object):
+def getKeyface(object):
     """Evaluate the interface keyface from an object."""
 
     if IInterface.providedBy(object):
@@ -43,11 +43,11 @@
 
 
 
-def queryKey(object, default=None):
+def queryKeyface(object, default=None):
     """Evaluate the keyface keyface from an object."""
 
     try:
-        return getKey(object)
+        return getKeyface(object)
 
     except:
         return default

Modified: zope.generic/trunk/src/zope/generic/type/adapter.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/adapter.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/type/adapter.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -18,15 +18,9 @@
 
 __docformat__ = 'restructuredtext'
 
-from zope.app.location import Location
 from zope.component import adapts
-from zope.interface import classImplements
 from zope.interface import implements
 
-from zope.generic.configuration import IConfigurations
-from zope.generic.configuration import IConfigurationType
-from zope.generic.configuration.api import ConfigurationData
-from zope.generic.keyface import IAttributeKeyfaced
 from zope.generic.informationprovider.api import provideInformation
 
 from zope.generic.type import IInitializer
@@ -57,191 +51,3 @@
 
             if config.handler:
                 config.handler(self.context, *pos, **kws)
-
-
-_marker = object()
-
-class ConfigurationAdapterProperty(object):
-    """Compute configuration adapter attributes based on schema fields
-
-    Field properties provide default values, data validation and error messages
-    based on data found in field meta-data.
-
-    Note that ConfigurationAdapterProperty cannot be used with slots. 
-    They can only be used for attributes stored in instance configurations
-    dictionaries.
-    """
-
-    def __init__(self, field, name=None):
-        if name is None:
-            name = field.__name__
-
-        self.__field = field
-        self.__name = name
-
-    def __get__(self, inst, klass):
-        if inst is None:
-            return self
-
-        configurations = inst.__configurations__
-        keyface = inst.__keyface__
-        context = inst.__context__
-
-        configuration = inst.__keyface__(configurations, None)
-        if configuration is None:
-            # Try to evaluate a type configuration
-            configuration = queryTypeConfiguration(context, keyface)
-
-        value = getattr(configuration, self.__name, _marker)
-        if value is _marker:
-            field = self.__field.bind(inst)
-            value = getattr(field, 'default', _marker)
-            if value is _marker:
-                raise AttributeError(self.__name)
-
-        return value
-
-    def __set__(self, inst, value):
-        field = self.__field.bind(inst)
-        field.validate(value)
-        if field.readonly:
-            raise ValueError(self.__name, 'field is readonly')
-
-        configurations = inst.__configurations__
-        keyface = inst.__keyface__
-        # update existing configuration
-        if keyface in configurations:
-            configurations.update(keyface, {self.__name: value})
-            
-        # create a new configuration
-        else:
-            configurations[keyface] = ConfigurationData(keyface, {self.__name: value})
-
-        inst.__dict__[self.__name] = value
-
-    def __getattr__(self, name):
-        return getattr(self.__field, name)
-
-
-
-class ConfigurationAdapterBase(Location):
-    """Base mixin for simple configuration adapter."""
-
-    __keyface__ = None
-
-    def __init__(self, context):
-        self.__context__ = context
-        self.__configurations__ = IConfigurations(context)
-
-
-
-def ConfigurationAdapterClass(keyface, bases=()):
-    """Generic configuration adapter class factory.
-
-    The generic configuration adapter is a generic adapter class for 
-    configurations based instances. First we declare a configuration
-    schema:
-
-        >>> from zope.interface import Interface
-        >>> from zope.schema import TextLine
-
-        >>> class IFooConfiguration(Interface):
-        ...    foo = TextLine(title=u'Foo')
-
-    We register the configuration schema using generic:configuration directive:
-
-        >>> registerDirective('''
-        ... <generic:keyface
-        ...     keyface="example.IFooConfiguration"
-        ...     type="zope.generic.configuration.IConfigurationType"
-        ...     />
-        ... ''') 
-
-        >>> from zope.generic.configuration import IConfigurationType
-        >>> IConfigurationType.providedBy(IFooConfiguration)
-        True
-
-    We use a generic type including a default configuration for our example, too:
-
-        >>> class IFoo(Interface):
-        ...    pass
-
-        >>>
-
-        >>> from zope.generic.configuration.api import ConfigurationData
-
-        >>> foo_configuration = ConfigurationData(IFooConfiguration, {'foo': u'Type Foo'})
-
-        >>> registerDirective('''
-        ... <generic:type
-        ...     keyface="example.IFoo"
-        ...        class='zope.generic.type.api.Object'
-        ...     >
-        ...    <configuration
-        ...        keyface='example.IFooConfiguration'
-        ...        data='example.foo_configuration'
-        ...       />
-        ... </generic:type>
-        ... ''')
-
-        >>> foo = api.createObject(IFoo)
-        >>> IFoo.providedBy(foo)
-        True
-        >>> api.queryTypeConfiguration(foo, IFooConfiguration).foo
-        u'Type Foo'
-
-    At the moment the foo instance does not provide a foo configuration:
-
-        >>> api.queryObjectConfiguration(foo, IFooConfiguration) is None
-        True
-
-    The simple configuration adapter function will construct an adapter class
-    implementing the IFooConfiguration interface:
-
-        >>> from zope.generic.type.adapter import ConfigurationAdapterClass
-        
-        >>> FooConfigurationAdapter = ConfigurationAdapterClass(IFooConfiguration)
-        >>> IFooConfiguration.implementedBy(FooConfigurationAdapter)
-        True
-
-    We can adapt our foo to IFooConfiguration:
-
-        >>> adapted = FooConfigurationAdapter(foo)
-        >>> IFooConfiguration.providedBy(adapted)
-        True
-        >>> adapted.foo
-        u'Type Foo'
-
-        >>> adapted.foo = u'Object Foo.'
-        >>> adapted.foo
-        u'Object Foo.'
-
-        >>> api.queryObjectConfiguration(foo, IFooConfiguration).foo
-        u'Object Foo.'
-
-    """
-
-    # preconditions
-    if not IConfigurationType.providedBy(keyface):
-        raise ValueError('Interface must provide %s.' % IConfigurationType.__name__)
-
-    # essentails
-    if not bases:
-        bases = (ConfigurationAdapterBase, )
-
-    class_ = type('ConfigurationAdapterClass from %s' % keyface, bases,
-                  {'__keyface__': keyface})
-
-    classImplements(class_, keyface)
-
-    # add field properties for each object field
-    for name in keyface:
-        field = keyface[name]
-        setattr(class_, name, ConfigurationAdapterProperty(keyface[name]))
-
-        # security assertions
-        # protectName(class_, name, 'zope.ManageSite')
-        # protectSetAttribute(class_, name, 'zope.ManageSite')
-
-    return class_
-

Modified: zope.generic/trunk/src/zope/generic/type/helper.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/helper.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/type/helper.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -36,6 +36,7 @@
     return component.createObject(toDottedName(keyface), *pos, **kws)
 
 
+
 def createParameter(keyface):
     config = queryTypeConfiguration(keyface, IInitializerConfiguration)
     if config:
@@ -65,7 +66,7 @@
 def queryType(object, default=None):
     try:
         return getType(object)
-    
+
     except:
         return default
 
@@ -106,6 +107,7 @@
         return default
 
 
+
 def acquireObjectConfiguration(object, configuration, default=None):
     # first try to evaluate object configuration data
     data = queryObjectConfiguration(object, configuration, default)
@@ -116,4 +118,3 @@
     # return type configuration data
     else:
         return queryTypeConfiguration(object, configuration, default)
-

Modified: zope.generic/trunk/src/zope/generic/type/metaconfigure.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/metaconfigure.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/type/metaconfigure.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -41,8 +41,10 @@
 from zope.generic.type import ITypeInformation
 from zope.generic.type import ITypeType
 from zope.generic.type.adapter import Initializer
-from zope.generic.type.adapter import ConfigurationAdapterClass
+from zope.generic.configuration.api import ConfigurationAdapterClass
+from zope.generic.configuration.api import ConfigurationAdapterProperty
 from zope.generic.type.factory import TypeFactory
+from zope.generic.type.helper import queryTypeConfiguration
 from zope.generic.type.helper import queryTypeInformation
 
 
@@ -55,6 +57,35 @@
 
 
 
+_marker = object()
+
+class _TypeConfigurationAdapterProperty(ConfigurationAdapterProperty):
+    """Lookup type informations."""
+
+    def __get__(self, inst, klass):
+        if inst is None:
+            return self
+
+        configurations = inst.__configurations__
+        keyface = inst.__keyface__
+        context = inst.__context__
+
+        configuration = inst.__keyface__(configurations, None)
+        if configuration is None:
+            # Try to evaluate a type configuration
+            configuration = queryTypeConfiguration(context, keyface)
+
+        value = getattr(configuration, self._name, _marker)
+        if value is _marker:
+            field = self._field.bind(inst)
+            value = getattr(field, 'default', _marker)
+            if value is _marker:
+                raise AttributeError(self._name)
+
+        return value
+
+
+
 class InitializationHandler(object):
     """Initialization handler.
     
@@ -138,7 +169,7 @@
 
         # we will provide a generic adapter class
         if class_ is None:
-            class_ = ConfigurationAdapterClass(keyface)
+            class_ = ConfigurationAdapterClass(keyface, (), _TypeConfigurationAdapterProperty)
 
         # register class
         class_directive = ClassDirective(_context, class_)

Modified: zope.generic/trunk/src/zope/generic/type/tests.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/tests.py	2006-04-20 16:21:05 UTC (rev 67178)
+++ zope.generic/trunk/src/zope/generic/type/tests.py	2006-04-20 16:26:37 UTC (rev 67179)
@@ -32,14 +32,6 @@
 
 def test_suite():
     return unittest.TestSuite((
-        doctest.DocTestSuite('zope.generic.type.adapter',
-                             setUp=testing.placelesssetup.setUp,
-                             tearDown=testing.placelesssetup.tearDown,
-                             globs={'component': component, 'interface': interface,
-                             'registerDirective': registerDirective,
-                             'testing': testing, 'api': api},
-                             optionflags=doctest.NORMALIZE_WHITESPACE+
-                                            doctest.ELLIPSIS),
         doctest.DocTestSuite('zope.generic.type.factory'),
         doctest.DocTestSuite('zope.generic.type.metaconfigure'),
         doctest.DocFileSuite('README.txt',



More information about the Checkins mailing list