[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