[Checkins] SVN: zope.generic/trunk/src/zope/generic/ refactoring:
Dominik Huber
dominik.huber at perse.ch
Thu Apr 13 18:55:12 EDT 2006
Log message for revision 66938:
refactoring:
merge .information and .configuration into .component
rename information to information provider
Changed:
A zope.generic/trunk/src/zope/generic/component/DEPENDENCIES.cfg
A zope.generic/trunk/src/zope/generic/component/NEW_README.txt
A zope.generic/trunk/src/zope/generic/component/PUBLICATION.cfg
U zope.generic/trunk/src/zope/generic/component/README.txt
A zope.generic/trunk/src/zope/generic/component/README_2.txt
A zope.generic/trunk/src/zope/generic/component/adapter.py
U zope.generic/trunk/src/zope/generic/component/api.py
U zope.generic/trunk/src/zope/generic/component/base.py
U zope.generic/trunk/src/zope/generic/component/configure.zcml
A zope.generic/trunk/src/zope/generic/component/event.py
U zope.generic/trunk/src/zope/generic/component/helper.py
U zope.generic/trunk/src/zope/generic/component/interfaces.py
A zope.generic/trunk/src/zope/generic/component/meta.zcml
A zope.generic/trunk/src/zope/generic/component/metaconfigure.py
A zope.generic/trunk/src/zope/generic/component/metadirectives.py
U zope.generic/trunk/src/zope/generic/component/testing.py
U zope.generic/trunk/src/zope/generic/component/tests.py
A zope.generic/trunk/src/zope/generic/component/zope.generic.component-meta.zcml
D zope.generic/trunk/src/zope/generic/configuration/
D zope.generic/trunk/src/zope/generic/information/
U zope.generic/trunk/src/zope/generic/operation/README.txt
U zope.generic/trunk/src/zope/generic/operation/base.py
U zope.generic/trunk/src/zope/generic/operation/helper.py
U zope.generic/trunk/src/zope/generic/operation/interfaces.py
U zope.generic/trunk/src/zope/generic/operation/metaconfigure.py
U zope.generic/trunk/src/zope/generic/operation/metadirectives.py
U zope.generic/trunk/src/zope/generic/operation/testing.py
U zope.generic/trunk/src/zope/generic/type/DEPENDENCIES.cfg
U zope.generic/trunk/src/zope/generic/type/EXAMPLE.txt
U zope.generic/trunk/src/zope/generic/type/README.txt
U zope.generic/trunk/src/zope/generic/type/adapter.py
U zope.generic/trunk/src/zope/generic/type/base.py
U zope.generic/trunk/src/zope/generic/type/configure.zcml
U zope.generic/trunk/src/zope/generic/type/helper.py
U zope.generic/trunk/src/zope/generic/type/interfaces.py
U zope.generic/trunk/src/zope/generic/type/meta.zcml
U zope.generic/trunk/src/zope/generic/type/metaconfigure.py
U zope.generic/trunk/src/zope/generic/type/metadirectives.py
U zope.generic/trunk/src/zope/generic/type/testing.py
-=-
Added: zope.generic/trunk/src/zope/generic/component/DEPENDENCIES.cfg
===================================================================
--- zope.generic/trunk/src/zope/generic/component/DEPENDENCIES.cfg 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/DEPENDENCIES.cfg 2006-04-13 22:55:09 UTC (rev 66938)
@@ -0,0 +1,9 @@
+zope.generic.component
+zope.generic.testing
+zope.app.annotation
+zope.app.component
+zope.component
+zope.configuration
+zope.interface
+zope.schema
+zope.testing
Property changes on: zope.generic/trunk/src/zope/generic/component/DEPENDENCIES.cfg
___________________________________________________________________
Name: svn:keywords
+ Id
Added: zope.generic/trunk/src/zope/generic/component/NEW_README.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/component/NEW_README.txt 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/NEW_README.txt 2006-04-13 22:55:09 UTC (rev 66938)
@@ -0,0 +1,141 @@
+===================================
+How to use the information package?
+===================================
+
+We are developing a logger framework that can be used by user-application
+domains and supplier-application domains.
+
+Therefore we provide two public information registries for the members of our
+orthagonal application domain such as suppliers. The log-supplier-information
+registry is holding supplier-specific informations. The log-user-information
+registry is holding user-specific informations.
+
+In order to implement such an information registry we have to declare an
+*key-like* interface extending the IInformation interface:
+
+ >>> from zope.generic.component import IInformationProvider
+
+ >>> class ILogSupplierInformation(IInformationProvider):
+ ... """Store log supplier information."""
+
+ >>> class ILogUserInformation(IInformationProvider):
+ ... """Store log user information."""
+
+This specialized information interface has to be registered later by
+informationRegistry-directive.
+
+Such an extended information is logical container for configurations and
+annotations. In our framework example we have now to specify concrete
+configuration that are registered to the two registries by the corresponding
+member group.
+
+A supplier has to provide global log instance (dotted name) and an optional
+time formatter. We capture this configuration information within a configuration
+that can be attached to a dedicated supplier information.
+
+ >>> from zope.interface import Interface
+ >>> from zope.configuration.fields import GlobalObject
+ >>> from zope.schema import BytesLine
+
+ >>> class ILogConfiguration(Interface):
+ ... """Define the log output."""
+ ... log = GlobalObject(title=u'Log')
+ ... timeFormat = BytesLine(title=u'Time Format', required=False, default='%d.%m.%y')
+
+This configuration should be registered by using the configuration directive:
+
+ >>> registerDirective('''
+ ... <generic:configuration
+ ... interface="example.ILogConfiguration"
+ ... />
+ ... ''')
+
+A user has to provide logger configuration. This configuration defines the
+selected logger and a user-specific source tag:
+
+ >>> from zope.configuration.fields import GlobalInterface
+
+ >>> class ILoggerConfiguration(Interface):
+ ... """Define the log output."""
+ ... logger = GlobalInterface(title=u'Logger')
+ ... sourceTag = BytesLine(title=u'Source Tag', required=False, default=' ')
+
+ >>> registerDirective('''
+ ... <generic:configuration
+ ... interface="example.ILoggerConfiguration"
+ ... />
+ ... ''')
+
+TODO: Should be a dependency between informationRegistry and its configuration?
+
+ >>> registerDirective('''
+ ... <generic:informationRegistry
+ ... interface='example.ILogSupplierInformation'
+ ... />
+ ... ''')
+
+ >>> registerDirective('''
+ ... <generic:informationRegistry
+ ... interface='example.ILogUserInformation'
+ ... />
+ ... ''')
+
+The third part of our framework is the logger itself. The logger will be
+implmented as an adapter. We have to declare the logger interface:
+
+ >>> class ILogger(Interface):
+ ... """Log."""
+ ... def log(message):
+ ... """Log the message."""
+
+ >>> from zope.interface import implements
+ >>> from zope.component import adapts
+ >>> from zope.generic.component import IKeyInterface
+
+ >>> class Logger(object):
+ ... """Generic logger adapter."""
+ ... implements(ILogger)
+ ... adapts(IKeyInterface)
+ ... def __init__(self, context):
+ ... self.context = context
+ ... def log(self, message):
+ ... id = IKeyInterface(self.context())
+ ... info = queryInformationProvider(id.interface, ILogUserInformation)
+ >>> class Logger(object):
+ ... """Generic logger adapter."""
+ ... implements(ILogger)
+ ... adapts(IKeyInterface)
+ ... def __init__(self, context):
+ ... self.context = context
+ ... def log(self, message):
+ ... id = IKeyInterface(self.context())
+ ... info = queryInformationProvider(id.interface, ILogUserInformation)
+ >>> class Logger(object):
+ ... """Generic logger adapter."""
+ ... implements(ILogger)
+ ... adapts(IKeyInterface)
+ ... def __init__(self, context):
+ ... self.context = context
+ ... def log(self, message):
+ ... id = IKeyInterface(self.context())
+ ... info = queryInformationProvider(id.interface, ILogUserInformation)
+
+
+
+After the registration we can retrieve the registries using the
+queryInformationProvider function:
+
+ >>> from zope.generic.component.api import queryInformationProvider
+
+ >>> supplier_registry = queryInformationProvider(ILogSupplierInformation)
+ >>> supplier_registry.label
+ u'ILogSupplierInformation'
+ >>> supplier_registry.hint
+ u'Store log supplier information.'
+
+ >>> user_registry = queryInformationProvider(ILogUserInformation)
+ >>> user_registry.label
+ u'ILogUserInformation'
+ >>> user_registry.hint
+ u'Store log user information.'
+
Property changes on: zope.generic/trunk/src/zope/generic/component/NEW_README.txt
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zope.generic/trunk/src/zope/generic/component/PUBLICATION.cfg
===================================================================
--- zope.generic/trunk/src/zope/generic/component/PUBLICATION.cfg 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/PUBLICATION.cfg 2006-04-13 22:55:09 UTC (rev 66938)
@@ -0,0 +1,11 @@
+Metadata-Version: 1.0
+Name: zope.generic.component
+Summary: Information about interface based registrations
+Author: Dominik Huber, Perse Engineering GmbH, Switzerland
+Author-email: dominik.huber at perse.ch
+License: ZPL 2.1
+Description:
+ Provide facility for reusable information registry. The information
+ registries are implemented as utility providing IInformationRegistry.
+ The name of the registry is given by the dotted name of the interface
+ of the deciated information collected by the information registry.
Property changes on: zope.generic/trunk/src/zope/generic/component/PUBLICATION.cfg
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: zope.generic/trunk/src/zope/generic/component/README.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/component/README.txt 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/README.txt 2006-04-13 22:55:09 UTC (rev 66938)
@@ -1,9 +1,435 @@
-=========
-Component
-=========
+=================
+Generic Component
+=================
-The generic package relies heavily on interfaces. Often we have relation between
-different interfaces. One component does provide serveral interfaces so
-Informations provides dedicated data about an certain
-marker interface. Informations are implemented as utility. The package provides
-some convenience functions and directives.
\ No newline at end of file
+The behavior of components within the ca-framework depends heavily on their
+provided interfaces. A component, except most of the adapters and utilities,
+regularly provides more than one interface. The adaption and subscriber
+mechanism of the ca-framework invokes the provided interfaces by a
+lookup-algorithmus similar to the method resolution order by class inherintance.
+
+Most of the time this behavior satisfies our requirements. Additionally this
+package offers a mechanism to declare a single key interface (IKeyInterface).
+This key interface can be used to lookup corresponding information providers
+more explicitly.
+
+You can register different information providers to the same key interface. An
+information provider encapsulates a certain information aspect of the key
+interface. The relation between information providers of a key interface to
+components providing the same key interface is similar to the object class
+relation except that each informatio aspect follows its own information
+acquisition.
+
+You can attache generic informations such as annotations or configurations
+to an certain information provider.
+
+The annotations mechanism is well-known and documented (zope.annotations).
+
+The configurations mechansim works similar to the annotations mechansim, but
+references a single configuration (annotation) by its corresponding
+configuration schema (regular interfac-based schema see zope.schema).
+Such a configuration associates data and its corresponding schema. That means
+the configuration data provides the related schema and you can allways lookup
+dedicated configuration data by its configuration schema.
+
+Similar atomic informations defined by an annotation key or a
+configuration schemas can be reused by different information providers. So
+the identical information types will receive a contextual meaning that is related
+to information provider type.
+
+Information Provider
+--------------------
+
+You can use the information provider directive to register an information
+provider as utiliy with an interface extending IInformationProvider and a
+dotted name of an corresponding key interface as utility name:
+
+ >>> from zope.generic.component.api import IInformationProvider
+
+ >>> class ISpecialInformation(IInformationProvider):
+ ... pass
+
+ >>> from zope.interface import Interface
+ >>> class IFooMarker(Interface):
+ ... pass
+
+ >>> registerDirective('''
+ ... <generic:information
+ ... interface="example.IFooMarker"
+ ... registry="example.ISpecialInformation"
+ ... label='Foo Specials' hint='Bla bla foo.'
+ ... />
+ ... ''')
+
+After a registration the information provider can be looked up.
+All information provider with the same interface can be gotten by the
+getInformationProvidersFor function:
+
+ >>> from zope.generic.component.api import getInformationProvidersFor
+
+ >>> listing = list(getInformationProvidersFor(ISpecialInformation))
+ >>> len(listing) is 1
+ True
+ >>> [(key.__name__, value) for key, value in listing]
+ [('IFooMarker', {})]
+
+A single information provider can be retrieved by the get- or
+queryInformationProvider function:
+
+ >>> from zope.generic.component.api import getInformationProvider
+ >>> from zope.generic.component.api import queryInformationProvider
+
+ >>> info = getInformationProvider(IFooMarker, ISpecialInformation)
+ >>> info = queryInformationProvider(IFooMarker, ISpecialInformation)
+
+ >>> listing[0][1] == info
+ True
+ >>> listing[0][0] == IFooMarker
+ True
+
+ >>> info.key == IFooMarker
+ True
+ >>> ISpecialInformation.providedBy(info)
+ True
+ >>> info.label = u'Foo Specials'
+ >>> info.hint = u'Bla bla foo.'
+
+
+
+
+If no information provider is available for a certain interface the default
+value is returned. If no default is defined None is returned:
+
+ >>> class IBarMarker(Interface):
+ ... pass
+
+ >>> default = object()
+ >>> info = queryInformationProvider(IBarMarker, ISpecialInformation, default)
+ >>> info is default
+ True
+
+ >>> info = queryInformationProvider(IBarMarker, ISpecialInformation)
+ >>> info is None
+ True
+
+Information providers are annotable
+-----------------------------------
+
+Information providers are annotable. The annotations mechanism is used to provide
+additional informations in a generic manner:
+
+ >>> from zope.app.annotation.interfaces import IAnnotations
+
+ >>> info = queryInformationProvider(IFooMarker, ISpecialInformation)
+
+ >>> annotations = IAnnotations(info)
+ >>> annotations.get('test.annotation')
+ >>> annotations['test.annotation']
+ Traceback (most recent call last):
+ ...
+ KeyError: 'test.annotation'
+ >>> list(annotations.keys())
+ []
+ >>> del annotations['test.annotation']
+ Traceback (most recent call last):
+ ...
+ KeyError: 'test.annotation'
+ >>> annotations['test.annotation'] = 'a'
+ >>> annotations.get('test.annotation')
+ 'a'
+ >>> annotations['test.annotation']
+ 'a'
+ >>> list(annotations.keys())
+ ['test.annotation']
+ >>> del annotations['test.annotation']
+
+
+Information providers are configurable
+--------------------------------------
+
+Information providers are configurable. The configurations mechanism is used
+to provide additional configurations in a generic manner. A configuration
+is declared by a configuration schema providing IConfigurationType:
+
+ >>> from zope.schema import TextLine
+
+ >>> class IMyConfiguration(interface.Interface):
+ ... my = TextLine(title=u'My')
+
+ >>> registerDirective('''
+ ... <generic:configuration
+ ... interface="example.IMyConfiguration"
+ ... label='My' hint='My bla.'
+ ... />
+ ... ''')
+
+ >>> from zope.generic.component.api import IConfigurationType
+
+ >>> IConfigurationType.providedBy(IMyConfiguration)
+ True
+
+For the further exploration we query this information provider:
+
+ >>> from zope.generic.component.api import IConfigurationInformation
+
+ >>> my_config_ip = queryInformationProvider(IMyConfiguration, IConfigurationInformation)
+ >>> my_config_ip.key == IMyConfiguration
+ True
+ >>> IConfigurationInformation.providedBy(my_config_ip)
+ True
+
+We now can use this configuration to extend our information provider of the
+key interface IFooMarker. At the moment there are no configurations:
+
+ >>> from zope.generic.component.api import queryInformation
+
+ >>> queryInformation(info, IMyConfiguration) is None
+ True
+
+The configuration subdirective of the information provider directive provides a mechanism
+to register further configurations to an information provider:
+
+ >>> from zope.generic.component.api import ConfigurationData
+ >>> my_information_config = ConfigurationData(IMyConfiguration, {'my': u'My!'})
+
+ >>> registerDirective('''
+ ... <generic:information
+ ... interface="example.IFooMarker"
+ ... registry="example.ISpecialInformation"
+ ... label='Foo Specials' hint='Bla bla foo.'
+ ... >
+ ... <configuration
+ ... interface="example.IMyConfiguration"
+ ... data="example.my_information_config"
+ ... />
+ ... </generic:information>
+ ... ''')
+
+ >>> from zope.generic.component.api import queryInformationProvider
+
+ >>> info = queryInformationProvider(IFooMarker, ISpecialInformation)
+ >>> queryInformation(info, IMyConfiguration) is my_information_config
+ True
+
+
+Global Configurations
+---------------------
+
+Configurations is a container of configuration data. Configuration data are
+defined by an schema which is providing IConfigurationType. The configuration
+data itself has to provide the schema that is used to reference it.
+
+ >>> from zope.schema import TextLine
+
+ >>> class IMyConfiguration(interface.Interface):
+ ... my = TextLine(title=u'My')
+
+ >>> registerDirective('''
+ ... <generic:configuration
+ ... interface="example.IMyConfiguration"
+ ... label='My' hint='My bla.'
+ ... />
+ ... ''')
+
+ >>> from zope.generic.component.api import IConfigurationType
+ >>> IConfigurationType.providedBy(IMyConfiguration)
+ True
+
+The registered configuration itself is an information provider which
+is registered as utility providing IConfigurationInformation and is named
+by the dotted configuration schema name (key interface). A configuration
+is an information which can be looked up later using the get- or
+queryInformationProvider function too:
+
+ >>> from zope.generic.component.api import IConfigurationInformation
+ >>> from zope.generic.component.api import getInformationProvider
+
+ >>> config_info = getInformationProvider(IMyConfiguration,
+ ... IConfigurationInformation)
+ >>> config_info.label == u'My'
+ True
+ >>> config_info.hint == u'My bla.'
+ True
+
+The modification of configuration might cause object configured event.
+Those event extend the regular object event. This event regularly implies
+a location of the referenced object. Therefore only locatable objects will get
+notified. In our example we registered a transient global information which does
+not satify the condition:
+
+ >>> from zope.app.event.tests.placelesssetup import getEvents, clearEvents
+ >>> from zope.generic.component.api import IObjectConfiguredEvent
+
+ >>> events = getEvents()
+ >>> len(events)
+ 0
+
+Local Configurations
+--------------------
+
+Regularly local configurations are provided by objects marked with
+IAttributeConfigurations automatically:
+
+ >>> from zope.interface import implements
+ >>> from zope.generic.component.api import IAttributeConfigurable
+
+ >>> class Foo(object):
+ ... implements(IAttributeConfigurable)
+
+ >>> foo = Foo()
+ >>> IAttributeConfigurable.providedBy(foo)
+ True
+
+Now you can adapt you to IConfigurations:
+
+ >>> from zope.generic.component.api import IConfigurations
+
+ >>> configurations = IConfigurations(foo)
+ >>> IConfigurations.providedBy(configurations)
+ True
+
+At the beginning the IConfigurations storage does not exists:
+
+ >>> configurations.__nonzero__()
+ False
+
+Configuration data will be stored under an key interface within the
+configurations. Such a configuration schema defines its configuration
+data:
+
+ >>> from zope.interface import Interface
+ >>> from zope.schema import TextLine
+
+ >>> class IFooConfiguration(Interface):
+ ... foo = TextLine(title=u'Foo')
+ ... optional = TextLine(title=u'Optional', required=False, default=u'Bla')
+
+The configuration schema is a regular schema, but it has to be typed
+by IConfigurationType (Regularly done by the configuration directive):
+
+ >>> from zope.interface import directlyProvides
+
+ >>> directlyProvides(IFooConfiguration, IConfigurationType)
+ >>> IConfigurationType.providedBy(IFooConfiguration)
+ True
+
+The configurations provides a regular dictionary api by the UserDictMixin
+(like AttributeAnnotations). This mixin bases on the following methods:
+
+ >>> configurations[IFooConfiguration]
+ Traceback (most recent call last):
+ ...
+ KeyError: <InterfaceClass example.IFooConfiguration>
+
+ >>> del configurations[IFooConfiguration]
+ Traceback (most recent call last):
+ ...
+ KeyError: <InterfaceClass example.IFooConfiguration>
+
+ >>> configurations.keys()
+ []
+
+... if a value might be set to the configurations it must provide the
+configuration schema itself. This key interface must provide IConfigurationType:
+
+ >>> class IBarConfiguration(Interface):
+ ... bar = TextLine(title=u'Bar')
+
+ >>> configurations[IBarConfiguration] = object()
+ Traceback (most recent call last):
+ ...
+ KeyError: 'Interface key IBarConfiguration does not provide IConfigurationType.'
+
+ >>> configurations[IFooConfiguration] = object()
+ Traceback (most recent call last):
+ ...
+ ValueError: Value does not provide IFooConfiguration.
+
+Furthermore there is an update method that can be used to update a specific
+configuration. This method can be only used if a configuration already exists:
+
+ >>> configurations.update(IFooConfiguration, {'foo': u'Foo!'})
+ Traceback (most recent call last):
+ ...
+ KeyError: <InterfaceClass example.IFooConfiguration>
+
+You can create valid configuration data using the generic ConfigurationData
+implementation and a configuration schema:
+
+ >>> from zope.generic.component.api import ConfigurationData
+
+ >>> data = ConfigurationData(IFooConfiguration, {'foo': u'Foo!'})
+
+ >>> configurations[IFooConfiguration] = data
+
+The setting of the configuration is notified by a object configured event if
+the parent has a location an the parent's parent is not None:
+
+ >>> events = getEvents()
+ >>> len(events)
+ 0
+
+ >>> from zope.app.location import Location
+ >>> parent = Location()
+ >>> configurations.__parent__ = parent
+
+ >>> configurations[IFooConfiguration] = data
+ >>> events = getEvents()
+ >>> len(events)
+ 0
+
+ >>> parent.__parent__ = Location()
+ >>> configurations[IFooConfiguration] = data
+ >>> events = getEvents()
+ >>> len(events)
+ 1
+
+ >>> event = events.pop()
+ >>> IObjectConfiguredEvent.providedBy(event)
+ True
+ >>> [(key.__name__, value) for key, value in event.items()]
+ [('IFooConfiguration', {'foo': u'Foo!', 'optional': u'Bla'})]
+
+If the configuration data is set the first time an oobtree storage is set
+to the __configurations__ attribute of the context:
+
+ >>> configurations.__nonzero__()
+ True
+
+ >>> IFooConfiguration in configurations
+ True
+
+ >>> configurations[IFooConfiguration] == data
+ True
+
+ >>> [iface.__name__ for iface in configurations.keys()]
+ ['IFooConfiguration']
+
+You should update a configuration using the update method instead of setting
+new configuration data. If the change differs from the configuration an object
+configuration modified event is notify else not:
+
+ >>> clearEvents()
+ >>> configurations.update(IFooConfiguration, {'foo': u'Bar!'})
+ >>> events = getEvents()
+ >>> len(events)
+ 1
+ >>> event = events.pop()
+ >>> [(key.__name__, value) for key, value in event.items()]
+ [('IFooConfiguration', {'foo': u'Bar!'})]
+
+Also the deletion is notified by an empty dict:
+
+ >>> clearEvents()
+
+ >>> del configurations[IFooConfiguration]
+ >>> IFooConfiguration in configurations
+ False
+
+ >>> events = getEvents()
+ >>> len(events)
+ 1
+ >>> event = events.pop()
+ >>> [(key.__name__, value) for key, value in event.items()]
+ [('IFooConfiguration', {})]
+
Added: zope.generic/trunk/src/zope/generic/component/README_2.txt
===================================================================
Property changes on: zope.generic/trunk/src/zope/generic/component/README_2.txt
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zope.generic/trunk/src/zope/generic/component/adapter.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/adapter.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/adapter.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -0,0 +1,174 @@
+##############################################################################
+#
+# 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 BTrees.OOBTree import OOBTree
+import transaction
+from UserDict import DictMixin
+
+from zope.app.location import Location
+from zope.app.location.interfaces import ILocation
+from zope.component import adapts
+from zope.event import notify
+from zope.interface import implements
+
+from zope.generic.component import IAttributeConfigurable
+from zope.generic.component import IConfigurationType
+from zope.generic.component import IConfigurations
+from zope.generic.component import IKeyInterface
+from zope.generic.component import IAttributeKeyInterface
+from zope.generic.component.event import Configuration
+from zope.generic.component.event import ObjectConfiguredEvent
+from zope.generic.component.helper import configuratonToDict
+from zope.generic.component.helper import toDottedName
+from zope.generic.component.helper import toKeyInterface
+
+
+class KeyInterface(object):
+ """Adapts IAttributeKeyInterface to IKeyInterface.
+
+ You can adapt IKeyInterface if you provide IAttributeKeyInterface:
+
+ >>> class AnyAttributeKeyInterface(KeyInterface):
+ ... def __init__(self, key):
+ ... self.__key_interface__ = key
+
+ >>> fake_key_interface = object()
+ >>> any = AnyAttributeKeyInterface(fake_key_interface)
+
+ >>> KeyInterface(any).key == fake_key_interface
+ True
+ >>> IKeyInterface.providedBy(KeyInterface(any))
+ True
+
+"""
+
+ implements(IKeyInterface)
+ adapts(IAttributeKeyInterface)
+
+ def __init__(self, context):
+ self.context = context
+
+ @property
+ def key(self):
+ return self.context.__key_interface__
+
+
+
+class AttributeConfigurations(DictMixin, Location):
+ """Store configurations on an object within the __configurations__ attribute.
+
+ """
+
+ implements(IConfigurations)
+
+ adapts(IAttributeConfigurable)
+
+ def __init__(self, context):
+ self.context = context
+
+ def __nonzero__(self):
+ return bool(getattr(self.context, '__configurations__', 0))
+
+ def __conform__(self, interface):
+ configurations = getattr(self.context, '__configurations__', None)
+ if configurations is None:
+ return None
+
+ else:
+ return configurations.get(toDottedName(interface), None)
+
+ def __getitem__(self, interface):
+ configurations = getattr(self.context, '__configurations__', None)
+ if configurations is None:
+ raise KeyError(interface)
+
+ return configurations[toDottedName(interface)]
+
+ def keys(self):
+ configurations = getattr(self.context, '__configurations__', None)
+ if configurations is None:
+ return []
+
+ return [toKeyInterface(iface) for iface in configurations.keys()]
+
+ def update(self, interface, data):
+ current_config = self[interface]
+
+ updated_data = {}
+ errors = []
+
+ savepoint = transaction.savepoint()
+ try:
+ for name, value in data.items():
+ # raise attribute error
+ field = interface[name]
+ if field.readonly:
+ raise ValueError(name, 'Data is readonly.')
+ else:
+ if value != getattr(current_config, name, field.missing_value):
+ setattr(current_config, name, value)
+ updated_data[name] = value
+
+ # notify update
+ parent = self.__parent__
+ if updated_data and ILocation.providedBy(parent) and parent.__parent__ is not None:
+ notify(ObjectConfiguredEvent(parent,
+ Configuration(interface, updated_data)))
+
+ except:
+ savepoint.rollback()
+ raise
+
+ def __setitem__(self, interface, value):
+ # preconditions
+ if not IConfigurationType.providedBy(interface):
+ raise KeyError('Interface key %s does not provide %s.' %
+ (interface.__name__, IConfigurationType.__name__))
+
+ if not interface.providedBy(value):
+ raise ValueError('Value does not provide %s.' % interface.__name__)
+
+ # essentials
+ try:
+ configurations = self.context.__configurations__
+ except AttributeError:
+ configurations = self.context.__configurations__ = OOBTree()
+
+ data = configuratonToDict(interface, value, all=True)
+ configurations[toDottedName(interface)] = value
+ # notify setting
+ parent = self.__parent__
+ if ILocation.providedBy(parent) and parent.__parent__ is not None:
+ notify(ObjectConfiguredEvent(parent,
+ Configuration(interface, data)))
+
+ def __delitem__(self, interface):
+ try:
+ configurations = self.context.__configurations__
+ except AttributeError:
+ raise KeyError(interface)
+
+ del configurations[toDottedName(interface)]
+ # notify deletion
+ # notify setting
+ parent = self.__parent__
+ if ILocation.providedBy(parent) and parent.__parent__ is not None:
+ notify(ObjectConfiguredEvent(parent,
+ Configuration(interface, {})))
Property changes on: zope.generic/trunk/src/zope/generic/component/adapter.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: zope.generic/trunk/src/zope/generic/component/api.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/api.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/api.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -18,8 +18,113 @@
__docformat__ = 'restructuredtext'
+from zope.app.annotation import IAnnotations
+from zope.component import getUtilitiesFor
+from zope.component import getUtility
+from zope.interface.interfaces import IInterface
+
+from zope.generic.component import *
+from zope.generic.component.base import ConfigurationData
+from zope.generic.component.base import InformationProvider
+from zope.generic.component.base import KeyInterface
from zope.generic.component.base import KeyInterfaceDescription
-from zope.generic.component.helper import getKey
-from zope.generic.component.helper import queryKey
-from zope.generic.component.helper import toComponent
+from zope.generic.component.helper import configuratonToDict
from zope.generic.component.helper import toDottedName
+from zope.generic.component.helper import toKeyInterface
+
+
+
+def getKey(object):
+ """Evaluate the interface key from an object."""
+
+ if IInterface.providedBy(object):
+ interface = object
+
+ elif IKeyInterface.providedBy(object):
+ interface = object.interface
+
+ else:
+ interface = IKeyInterface(object).interface
+
+ return interface
+
+
+
+def queryKey(object, default=None):
+ """Evaluate the interface key from an object."""
+
+ try:
+ return getKey(object)
+
+ except:
+ return default
+
+
+
+def getInformationProvider(object, provider=IInformationProviderInformation):
+ """Evaluate an information provider for an object."""
+
+ return getUtility(provider, toDottedName(getKey(object)))
+
+
+
+def queryInformationProvider(object, provider=IInformationProviderInformation, default=None):
+ """Evalute an information provider or return default."""
+ try:
+ return getInformationProvider(object, provider)
+
+ except:
+ return default
+
+
+
+def getInformationProvidersFor(provider, default=None):
+ """Evaluate all information providers of a certain information aspect."""
+
+ for name, information in getUtilitiesFor(provider):
+ yield (toKeyInterface(name), information)
+
+
+
+def getInformation(context, key):
+ """Evaluate an information by a key (string or key interface)."""
+ if IConfigurationType.providedBy(key):
+ return key(IConfigurations(context))
+
+ else:
+ return IAnnotations(context)[key]
+
+
+
+def queryInformation(context, key, default=None):
+ """Evaluate an information by a key (string or key interface)."""
+ try:
+ return getInformation(context, key)
+
+ except:
+ return default
+
+
+
+def provideInformation(context, key, information):
+ """Set an information to a context using a key (string or key interface)."""
+
+ if IConfigurationType.providedBy(key):
+ if type(information) is dict:
+ information = ConfigurationData(key, information)
+
+ IConfigurations(context)[key] = information
+
+ else:
+ IAnnotations(context)[key] = information
+
+
+
+def deleteInformation(context, key):
+ """Delete an information of a context using a key (string or key interface)."""
+
+ if IConfigurationType.providedBy(key):
+ del IConfigurations(context)[key]
+
+ else:
+ del IAnnotations(context)[key]
Modified: zope.generic/trunk/src/zope/generic/component/base.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/base.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/base.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -18,27 +18,266 @@
__docformat__ = 'restructuredtext'
+from persistent import Persistent
+from persistent.dict import PersistentDict
+
+from zope.app.annotation.interfaces import IAttributeAnnotatable
from zope.app.i18n import ZopeMessageFactory as _
+from zope.interface import alsoProvides
+from zope.interface import directlyProvides
from zope.interface import implements
+from zope.interface.interfaces import IMethod
+from zope.schema.interfaces import IField
+from zope.generic.component import IAttributeConfigurable
+from zope.generic.component import IConfigurationData
+from zope.generic.component import IConfigurations
+from zope.generic.component import IInformationProvider
+from zope.generic.component import IKeyInterface
+from zope.generic.component import IAttributeKeyInterface
from zope.generic.component import IKeyInterfaceDescription
+from zope.generic.component import adapter
+from zope.generic.component.helper import toDottedName
-class KeyInterfaceDescription(object):
- """Information description."""
+class KeyInterface(object):
+ """Key interface mixin for key interface attribute implementations.
+
+ You can mixin this class if you like to provide IKeyInterface for
+ IAttributeKeyInterface implementations:
+ >>> class AnyAttributeKeyInterface(KeyInterface):
+ ... def __init__(self, key):
+ ... self.__key_interface__ = key
+
+ >>> fake_key_interface = object()
+ >>> any = AnyAttributeKeyInterface(fake_key_interface)
+ >>> any.__key_interface__ == fake_key_interface
+ True
+
+ You get only the following method decorator for free :):
+
+ >>> any.key == fake_key_interface
+ True
+
+ """
+
+ implements(IKeyInterface)
+
+ @property
+ def key(self):
+ return self.__key_interface__
+
+
+
+class KeyInterfaceDescription(KeyInterface):
+ """Key interface description mixin."""
+
implements(IKeyInterfaceDescription)
- def __init__(self, interface, label=None, hint=None):
- self.interface = interface
+ def __init__(self, key, label=None, hint=None):
+ self.__key_interface__ = key
if label is None:
- self.label = _(interface.__name__)
+ self.label = _(key.__name__)
else:
self.label = label
if hint is None:
- self.hint = _(interface.__doc__)
+ self.hint = _(key.__doc__)
else:
self.hint = hint
+
+
+
+_marker = object()
+
+class ConfigurationData(Persistent):
+ """Generic configuration data.
+
+ The generic configuration data implementation can be used to create
+ instances providing a certain configuration schema on the fly. This is done
+ only by a __getattr__ and a __setattr__ method that asserts the configuration
+ schema constraint.
+
+ We first have to define an example configuration schema:
+
+ >>> from zope.interface import Interface
+ >>> from zope.schema import TextLine
+
+ >>> class IExampleConfiugrationSchema(Interface):
+ ... foo = TextLine(title=u'Foo')
+ ... fuu = TextLine(title=u'Fuu', required=False)
+ ... fii = TextLine(title=u'Fii', required=False, readonly=True)
+
+ Create a corresponding configuration data:
+
+ >>> config_data = ConfigurationData(IExampleConfiugrationSchema, {'foo': u'Foo!'})
+ >>> IExampleConfiugrationSchema.providedBy(config_data)
+ True
+ >>> config_data.foo
+ u'Foo!'
+ >>> config_data.fuu
+
+ >>> config_data.bar
+ Traceback (most recent call last):
+ ...
+ AttributeError: bar
+
+ >>> config_data.fii = u'Bla bla'
+ Traceback (most recent call last):
+ ...
+ ValueError: ('fii', 'Data is readonly.')
+
+ If a relevant key is missed within the data a key error is raised:
+
+ >>> config_data = ConfigurationData(IExampleConfiugrationSchema, {})
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'IExampleConfiugrationSchema' object has no attribute 'foo'.
+
+ The schema should not contain methods:
+
+ >>> class IBarConfiguration(Interface):
+ ... bar = TextLine(title=u'Bar')
+ ... def method(self):
+ ... pass
+
+ >>> config_data = ConfigurationData(IBarConfiguration, {'bar': u'Bar!', 'method': u'Method!'})
+ >>> config_data.bar
+ u'Bar!'
+ >>> config_data.method
+ Traceback (most recent call last):
+ ...
+ RuntimeError: ('Data value is not a schema field', 'method')
+
+ The implementation provide an adapter to IKeyInterface by its __conform__
+ method:
+
+ >>> adapted = IKeyInterface(config_data)
+ >>> IKeyInterface.providedBy(adapted)
+ True
+
+ >>> adapted.key is IBarConfiguration
+ True
+
+
+ """
+
+ implements(IAttributeKeyInterface, IConfigurationData)
+
+ def __init__(self, schema, data):
+ # preconditions
+ missedArguments = []
+ for name in schema:
+ if name not in data:
+ field = schema[name]
+ if field.required is True:
+ missedArguments.append(name)
+
+ if missedArguments:
+ raise AttributeError("'%s' object has no attribute '%s'." % (schema.__name__, ', '.join(missedArguments)))
+
+ # essentials
+ self.__dict__['_ConfigurationData__data'] = PersistentDict(data)
+ self.__dict__['__key_interface__'] = schema
+ directlyProvides(self, schema)
+
+ def __conform__(self, interface):
+ if interface is IKeyInterface:
+ return adapter.KeyInterface(self)
+
+ def __getattr__(self, name):
+ # assert IAttributeKeyInterface
+ if name == '__key_interface__':
+ return self.__dict__['__key_interface__']
+
+ schema = self.__dict__['__key_interface__']
+ data = self.__dict__['_ConfigurationData__data']
+ try:
+ field = schema[name]
+ except KeyError:
+ raise AttributeError(name)
+ else:
+ value = data.get(name, _marker)
+ if value is _marker:
+ value = getattr(field, 'default', _marker)
+ if value is _marker:
+ raise RuntimeError('Data is missing', name)
+
+ if IMethod.providedBy(field):
+ if not IField.providedBy(field):
+ raise RuntimeError('Data value is not a schema field', name)
+ v = lambda: value
+ else:
+ v = value
+ #setattr(self, name, v)
+ return v
+ raise AttributeError(name)
+
+ def __setattr__(self, name, value):
+ schema = self.__dict__['__key_interface__']
+ data = self.__dict__['_ConfigurationData__data']
+
+ if name != '__provides__':
+ try:
+ field = schema[name]
+ except KeyError:
+ raise AttributeError(name)
+ else:
+ if field.readonly is True:
+ raise ValueError(name, 'Data is readonly.')
+ data[name] = value
+ else:
+ super(ConfigurationData, self).__setattr__(name, value)
+
+
+
+class InformationProvider(KeyInterfaceDescription, dict):
+ """Generic information provider.
+
+ Information do relate a dedicated type of information marked as an interface
+ extending IInformationProvider and another marker interface:
+
+ >>> class ISpecialInformation(IInformationProvider):
+ ... pass
+
+ >>> from zope.interface import Interface
+ >>> class IFooMarker(Interface):
+ ... '''Foo is member of the example domain.'''
+
+ >>> info = InformationProvider(IFooMarker, ISpecialInformation)
+
+ The information will provide the interface of the dedicated information:
+
+ >>> ISpecialInformation.providedBy(info)
+ True
+
+ The information is related to the interface declared by the interface
+ attribute:
+
+ >>> info.key == IFooMarker
+ True
+ >>> info.label
+ u'IFooMarker'
+
+ >>> info.hint
+ u'Foo is member of the example domain.'
+
+
+ Often you will provide a specific label and hint for the end-user:
+
+ >>> info = InformationProvider(IFooMarker, ISpecialInformation, u'Foo', u'Bla bla.')
+ >>> info.label
+ u'Foo'
+
+ >>> info.hint
+ u'Bla bla.'
+ """
+
+ implements(IInformationProvider, IAttributeConfigurable, IAttributeAnnotatable)
+
+ def __init__(self, key, provides, label=None, hint=None):
+ super(InformationProvider, self).__init__(key, label, hint)
+ alsoProvides(self, provides)
\ No newline at end of file
Modified: zope.generic/trunk/src/zope/generic/component/configure.zcml
===================================================================
--- zope.generic/trunk/src/zope/generic/component/configure.zcml 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/configure.zcml 2006-04-13 22:55:09 UTC (rev 66938)
@@ -3,4 +3,38 @@
xmlns:generic="http://namespaces.zope.org/generic"
i18n_domain="zope">
+ <generic:information
+ interface=".IConfigurationInformation"
+ label="Configuration Information"
+ registry="zope.generic.component.IInformationProviderInformation"
+ />
+
+ <generic:information
+ interface=".IInformationProviderInformation"
+ label="Information Provider Information"
+ registry=".IInformationProviderInformation"
+ />
+
+ <!-- attribute configurations -->
+ <class class=".adapter.AttributeConfigurations">
+ <require
+ permission="zope.Public"
+ interface=".IReadConfigurations"
+ />
+ <require
+ permission="zope.ManageContent"
+ interface=".IUpdateConfigurations"
+ />
+ <require
+ permission="zope.ManageSite"
+ interface=".IWriteConfigurations"
+ />
+ </class>
+
+ <adapter
+ factory=".adapter.AttributeConfigurations"
+ provides="zope.generic.component.IConfigurations"
+ trusted="True"
+ />
+
</configure>
Added: zope.generic/trunk/src/zope/generic/component/event.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/event.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/event.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -0,0 +1,145 @@
+##############################################################################
+#
+# 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.event.objectevent import ObjectEvent
+from zope.interface import implements
+
+from zope.generic.component import IObjectConfiguredEvent
+from zope.generic.component import IConfigurationModificationDescription
+
+
+
+class Configuration(object) :
+ """Describes a single modified configuration.
+
+ A possible configuration schema:
+
+ >>> from zope.interface import Interface
+ >>> from zope.schema import TextLine
+
+ >>> class IMyConfiguration(Interface):
+ ... my = TextLine(title=u'My')
+
+ Check interface implementation:
+
+ >>> description = Configuration(IMyConfiguration, {'my': u'Bla'})
+
+ >>> IConfigurationModificationDescription.providedBy(description)
+ True
+
+ >>> description.interface == IMyConfiguration
+ True
+
+ >>> 'my' in description.data
+ True
+ >>> description.data.get('my')
+ u'Bla'
+
+ If no data argument is set, the data attribute will be set to an empty
+ dict, which implies that the configuration was deleted:
+
+ >>> description = Configuration(IMyConfiguration)
+ >>> description.interface == IMyConfiguration
+ True
+
+ >>> description.data
+ {}
+
+ """
+
+ implements(IConfigurationModificationDescription)
+
+ def __init__(self, interface, data=None) :
+ self.interface = interface
+ if data is not None:
+ self.data = data
+
+ else:
+ self.data = {}
+
+
+
+class ObjectConfiguredEvent(ObjectEvent):
+ """An object's configurations has been modified.
+
+ A possible configuration schema:
+
+ >>> from zope.interface import Interface
+ >>> from zope.schema import TextLine
+
+ >>> class IMyConfiguration(Interface):
+ ... my = TextLine(title=u'My')
+
+ >>> class IYourConfiguration(Interface):
+ ... your = TextLine(title=u'Your')
+
+ >>> class IRegularInterface(Interface):
+ ... pass
+
+ A possible event:
+
+ >>> descriptions = []
+ >>> descriptions.append(Configuration(IMyConfiguration, {'my': u'Bla'}))
+ >>> descriptions.append(Configuration(IYourConfiguration))
+ >>> from zope.app.event.objectevent import Attributes
+ >>> descriptions.append(Attributes(IRegularInterface))
+ >>> context = object()
+ >>> event = ObjectConfiguredEvent(context, *descriptions)
+
+ There are two convenience function to introspect configuration modifications
+ specifically:
+
+ >>> len(event.descriptions) is 3
+ True
+
+ >>> items = event.items()
+ >>> len(items) is 2
+ True
+ >>> [(interface.__name__, data) for interface, data in items]
+ [('IMyConfiguration', {'my': u'Bla'}), ('IYourConfiguration', {})]
+
+ >>> event.get(IMyConfiguration)
+ {'my': u'Bla'}
+
+ >>> event.get(IYourConfiguration)
+ {}
+
+ >>> event.get(IRegularInterface, 'default')
+ 'default'
+ """
+
+ implements(IObjectConfiguredEvent)
+
+ def __init__(self, object, *descriptions):
+ super(ObjectConfiguredEvent, self).__init__(object)
+ self.descriptions = descriptions
+
+ def items(self):
+ return [(d.interface, d.data) for d in self.descriptions
+ if IConfigurationModificationDescription.providedBy(d)]
+
+ def get(self, interface, default=None):
+ result = [d.data for d in self.descriptions
+ if IConfigurationModificationDescription.providedBy(d) and d.interface is interface]
+ if result:
+ return result[0]
+
+ else:
+ return default
Property changes on: zope.generic/trunk/src/zope/generic/component/event.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: zope.generic/trunk/src/zope/generic/component/helper.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/helper.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/helper.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -19,12 +19,9 @@
__docformat__ = 'restructuredtext'
from zope.dottedname.resolve import resolve
-from zope.interface.interfaces import IInterface
-from zope.generic.component import IKeyInterface
-
def toDottedName(component):
if component is None:
return 'None'
@@ -34,7 +31,7 @@
# cache
__name_to_component = {}
-def toComponent(name):
+def toKeyInterface(name):
try:
return __name_to_component[name]
except KeyError:
@@ -42,27 +39,54 @@
-def getKey(component):
- """Evaluate the interface key from a component."""
+_marker = object()
- if IInterface.providedBy(component):
- interface = component
+def configuratonToDict(interface, configuration, all=False):
+ """Extract values from configuration to a dictionary.
- elif IKeyInterface.providedBy(component):
- interface = component.interface
+ First we have to specify a test configurtion interface:
- else:
- interface = IKeyInterface(component).interface
+ >>> from zope.interface import Interface
+ >>> from zope.schema import TextLine
+
+ >>> class IFooConfiguration(Interface):
+ ... fo = TextLine(title=u'Fo')
+ ... foo = TextLine(title=u'Foo', required=False)
+ ... fooo = TextLine(title=u'Fooo', required=False, readonly=True, default=u'fooo bla')
- return interface
+ Minimal data without defaults:
+ >>> from zope.generic.component.base import ConfigurationData
+ >>> configuration = ConfigurationData(IFooConfiguration, {'fo': 'fo bla'})
+ >>> configuratonToDict(IFooConfiguration, configuration)
+ {'fo': 'fo bla'}
+ Including defaults:
+ >>> configuratonToDict(IFooConfiguration, configuration, all=True)
+ {'fooo': u'fooo bla', 'foo': None, 'fo': 'fo bla'}
-def queryKey(component, default=None):
- """Evaluate the interface key from a component."""
+ """
+ data = {}
+ for name in interface:
+ value = getattr(configuration, name, _marker)
+ field = interface[name]
- try:
- return getKey(component)
+ if field.required is False:
+ if value is not _marker and value != field.default:
+ data[name] = value
- except:
- return default
+ elif value == field.default:
+ if all:
+ data[name] = value
+
+ else:
+ if all:
+ data[name] = field.default
+
+ elif value is not _marker:
+ data[name] = value
+
+ else:
+ raise RuntimeError('Data is missing', name)
+
+ return data
Modified: zope.generic/trunk/src/zope/generic/component/interfaces.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/interfaces.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/interfaces.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -18,14 +18,27 @@
__docformat__ = 'restructuredtext'
+from zope.app.event.interfaces import IModificationDescription
+from zope.app.event.interfaces import IObjectEvent
from zope.app.i18n import ZopeMessageFactory as _
+from zope.app.location import ILocation
from zope.interface import Interface
+from zope.interface import alsoProvides
+from zope.interface import Attribute
from zope.interface.interfaces import IInterface
+from zope.schema import Bool
+from zope.schema import Dict
from zope.schema import Object
from zope.schema import Text
from zope.schema import TextLine
+from zope.schema import Tuple
+###############################################################################
+#
+# Base key interface related interfaces
+#
+###############################################################################
class IKeyInterfaceProvider(Interface):
"""Assert that a key interface can be looked up.
@@ -34,11 +47,17 @@
-class IKeyInterfaceAttributeProvider(IKeyInterfaceProvider):
- """Provide the key interface within an attribute.
+class IAttributeKeyInterface(IKeyInterfaceProvider):
+ """Provide the key interface within the __key_interface__ attribute."""
- The key interface is stored within the __key_interface__ attribute.
- """
+ __key_interface__ = Object(
+ title=_('Key interface'),
+ description=_('Key interface that allows to lookup ' +
+ 'key-interface-specific informations such as ' +
+ 'configurations providers.'),
+ required=True,
+ readonly=True,
+ schema=IInterface)
@@ -48,10 +67,9 @@
You can use this key to lookup component-specific informations.
"""
- interface = Object(
- title=_('Interface'),
- description=_('Interface marker that can be used as' +
- 'interface-specific-key to lookup informations.'),
+ key = Object(
+ title=_('Key interface'),
+ description=_('Key interface of the adapted context.'),
required=True,
readonly=True,
schema=IInterface)
@@ -59,14 +77,215 @@
class IKeyInterfaceDescription(IKeyInterface):
- """Describe the associated interface key."""
+ """User description about the associated key interface."""
label = TextLine(title=_('Label'),
- description=_('Label for associated interface marker.'),
+ description=_('Label for associated key interface.'),
required=True
)
hint = Text(title=_('Hint'),
- description=_('Hint explaning the properties of the associated interface marker.'),
+ description=_('Hint explaning the properties of the associated key interface.'),
required=True
)
+
+
+###############################################################################
+#
+# base configurations related interfaces
+#
+###############################################################################
+
+class IConfigurable(Interface):
+ """Provides an adapter to IConfigurations."""
+
+
+
+class IConfigurationType(IInterface):
+ """Mark a schema that is used for configuration."""
+
+
+
+class IConfigurationData(IKeyInterfaceProvider):
+ """Marker for configuration data implementations."""
+
+
+
+class IReadConfigurations(Interface):
+ """Read configuration data or looku for a certain configuration shema."""
+
+ def __conform__(key_interface):
+ """Invoke configuration data that are stored under the key interface.
+
+ Regularly the interface-key should provide configuration type.
+ If no value could be found None is returned.
+ """
+
+ def __nonzero__():
+ """Test whether there are any configurations at all."""
+
+ def __getitem__(key_interface):
+ """Return the configuration data stored under key interface.
+
+ Raises a KeyError if the key interface is not found.
+ """
+
+ def keys(self):
+ """Return stored key interfaces."""
+
+
+
+class IUpdateConfigurations(Interface):
+ """Update configuration data."""
+
+ def update(key_interface, data):
+ """Update the configuration data partially if nessecary.
+
+ data - dict providing keys and values corresponding to key interface.
+
+ The data object itself will not be saved, only the values that
+ differs from the existing configuration data.
+
+ A ValueError is raised if an read-only attribute/value should be set.
+
+ A AttributeError is raised if a not declared name should be set.
+
+ A KeyError is raise if there is no corresponding configuration available.
+
+ A successfull update is notified by a ObjectConfiguredEvent if
+ any value of the configuration data got changed and the surrounding
+ context (parent of the configurations) is providing ILocation.
+ """
+
+
+
+class IWriteConfigurations(Interface):
+ """Set or delete a configuration data."""
+
+ def __setitem__(key_interface, configuration_data):
+ """Store a certain configuration data under the interface-key.
+
+ The interface key should provide IConfigurationType.
+
+ The configuration data has to provide the declared key interface.
+
+ Configuration data will be invoked by the __conform__ mechanism if
+ somebody try to adapt the configurations to corresponding key interface.
+
+ A successfull setting is notified by a ObjectConfiguredEvent if
+ any value of the configuration data got changed and the surrounding
+ context (parent of the configurations) is providing ILocation.
+ """
+
+ def __delitem__(key_interface):
+ """Removes the configuration data stored under interface-key.
+
+ Raises a KeyError if the key interface is not found.
+
+ A successfull deletion is notified by a ObjectConfiguredEvent if
+ any value of the configuration data got changed and the surrounding
+ context (parent of the configurations) is providing ILocation.
+ """
+
+
+
+class IConfigurations(IReadConfigurations, IUpdateConfigurations,
+ IWriteConfigurations, IConfigurable, ILocation):
+ """United configurations interfaces."""
+
+
+###############################################################################
+#
+# base configurations related interfaces
+#
+###############################################################################
+
+
+
+class IInformationProviderType(IInterface):
+ """Mark information interface as information type."""
+
+
+
+class IInformationProvider(IKeyInterfaceDescription):
+ """Provide information about a dedicated key interfaces.
+
+ A configuration related to the key interface can be stored within the
+ provider's configurations.
+
+ Dedicated information providers has to extend this interface.
+ """
+
+
+
+class IInformationProviderInformation(IInformationProvider):
+ """Provide information about information providers."""
+
+
+
+alsoProvides(IInformationProviderInformation, IInformationProviderType)
+
+
+
+###############################################################################
+#
+# Extended key interface related interfaces
+#
+###############################################################################
+
+
+
+
+
+###############################################################################
+#
+# Extended configurations related interfaces
+#
+###############################################################################
+
+class IAttributeConfigurable(IConfigurable):
+ """Marker indicating that configurations can be stored on an attribute.
+
+ This is a marker interface giving permission for an `IConfigurations`
+ adapter to store data in an attribute named `__configurations__`.
+
+ """
+
+
+AnnotationKey = 'zope.generic.component.IConfigurations'
+
+class IAnnotationsConfigurable(IConfigurable):
+ """Marker indicating that configurations can be stored on annotations.
+
+ """
+
+
+class IConfigurationModificationDescription(IModificationDescription):
+ """Declares the modified configuration by its interface and
+ the corresponding data that got modified.
+
+ An empty data dictionary implies that the configuration was deleted."""
+
+ interface = Attribute("The involved configuratoin interface.")
+ data = Attribute("A dict of modified configuration data.")
+
+
+
+class IObjectConfiguredEvent(IObjectEvent):
+ """An object's configurations has been modified.
+
+ The corresponding modifications will be attached on the description attribute
+ """
+
+ descriptions = Attribute("Sequence of modifiaction descriptions.")
+
+ def items():
+ """List affected configuration interfaces and corresponding data from the descriptions."""
+
+ def get(interface, default=None):
+ """Return affected configuration data from the description or default."""
+
+
+
+class IConfigurationInformation(IInformationProvider):
+ """Information about a configuration."""
Added: zope.generic/trunk/src/zope/generic/component/meta.zcml
===================================================================
--- zope.generic/trunk/src/zope/generic/component/meta.zcml 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/meta.zcml 2006-04-13 22:55:09 UTC (rev 66938)
@@ -0,0 +1,41 @@
+<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="configuration"
+ schema=".metadirectives.IConfigurationDirective"
+ handler=".metaconfigure.configurationDirective"
+ />
+
+ <meta:complexDirective
+ name="information"
+ schema=".metadirectives.IInformationDirective"
+ handler=".metaconfigure.InformationDirective"
+ >
+
+ <meta:subdirective
+ name="configuration"
+ schema=".metadirectives.IConfigurationSubdirective"
+ />
+
+ </meta:complexDirective>
+
+ <meta:complexDirective
+ name="informationRegistry"
+ schema=".metadirectives.IInformationRegistryDirective"
+ handler=".metaconfigure.InformationRegistryDirective"
+ >
+
+ <meta:subdirective
+ name="configuration"
+ schema=".metadirectives.IConfigurationSubdirective"
+ />
+
+ </meta:complexDirective>
+
+ </meta:directives>
+
+</configure>
Property changes on: zope.generic/trunk/src/zope/generic/component/meta.zcml
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zope.generic/trunk/src/zope/generic/component/metaconfigure.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/metaconfigure.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/metaconfigure.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -0,0 +1,170 @@
+##############################################################################
+#
+# Copyright (c) 2005, 2006 Projekt01 GmbH 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.interface import provideInterface
+from zope.component import provideUtility
+from zope.configuration.exceptions import ConfigurationError
+from zope.interface import alsoProvides
+
+from zope.generic.component import IConfigurationInformation
+from zope.generic.component import IConfigurationType
+from zope.generic.component import IConfigurations
+from zope.generic.component import IInformationProvider
+from zope.generic.component import IInformationProviderInformation
+from zope.generic.component import IInformationProviderType
+from zope.generic.component.api import queryInformationProvider
+from zope.generic.component.base import ConfigurationData
+from zope.generic.component.base import InformationProvider
+from zope.generic.component.helper import toDottedName
+
+
+def provideInformationProvider(interface, registry=IInformationProviderInformation, label=None, hint=None, factory=None):
+ """Provide new information for the given registry-interface.
+
+ Register an information as utiliy under registry-interface using
+ the dotted name of the interface as utility name:
+
+ >>> class ISpecialInformation(IInformationProvider):
+ ... pass
+
+ >>> from zope.interface import Interface
+ >>> class IFooMarker(Interface):
+ ... pass
+
+ >>> provideInformationProvider(IFooMarker, ISpecialInformation)
+
+ The information can be queried using the following method:
+
+ >>> from zope.generic.component.helper import queryInformationProvider
+ >>> info = queryInformationProvider(IFooMarker, ISpecialInformation)
+ >>> info.interface == IFooMarker
+ True
+ >>> ISpecialInformation.providedBy(info)
+ True
+
+ """
+
+ # precondition
+ if not registry.extends(IInformationProvider):
+ raise ValueError('Registry must extend %s.' % IInformationProvider.__name__)
+
+ if factory is None:
+ factory = InformationProvider
+
+ component = factory(interface, registry, label, hint)
+
+ if not registry.providedBy(component):
+ raise ValueError('Factory must implement %s.' % registry.__name__)
+
+ provideUtility(component, provides=registry, name=toDottedName(interface))
+
+
+
+def provideConfiguration(interface, registry, configuration, data):
+ """Provide configuration for a certain type marker."""
+
+ info = queryInformationProvider(interface, registry)
+
+ configurations = IConfigurations(info)
+ configurations[configuration] = data
+
+
+
+class InformationDirective(object):
+ """Provide a new information of a certain information registry."""
+
+ _information_type = None
+
+ def __init__(self, _context, interface, registry, label=None, hint=None):
+ self._interface = interface
+ self._context = _context
+ self._registry = registry
+
+ # assert type as soon as possible
+ if self._information_type is not None:
+ alsoProvides(interface, self._information_type)
+
+ _context.action(
+ discriminator = ('provideInformationProvider', self._interface, self._registry),
+ callable = provideInformationProvider,
+ args = (self._interface, self._registry, label, hint),
+ )
+
+ _context.action(
+ discriminator = None,
+ callable = provideInterface,
+ args = (None, self._interface),
+ )
+
+ _context.action(
+ discriminator = None,
+ callable = provideInterface,
+ args = (None, self._registry),
+ )
+
+ def __call__(self):
+ "Handle empty/simple declaration."
+ return ()
+
+ def configuration(self, _context, interface, data):
+ # preconditions
+ if not interface.providedBy(data):
+ raise ConfigurationError('Data attribute must provide %s.' % interface.__name__)
+
+ _context.action(
+ discriminator = (
+ 'InformationConfiguration', self._interface, self._registry, interface),
+ callable = provideConfiguration,
+ args = (self._interface, self._registry, interface, data),
+ )
+
+
+
+def configurationDirective(_context, interface, label=None, hint=None):
+ """Provide new configuration information."""
+
+ registry = IConfigurationInformation
+ iface_type = IConfigurationType
+
+ # assert type as soon as possible
+ if not iface_type.providedBy(interface):
+ alsoProvides(interface, iface_type)
+
+ _context.action(
+ discriminator = ('provideInformationProvider', interface, registry),
+ callable = provideInformationProvider,
+ args = (interface, registry, label, hint),
+ )
+
+ _context.action(
+ discriminator = None,
+ callable = provideInterface,
+ args = (None, interface, iface_type),
+ )
+
+
+
+class InformationRegistryDirective(InformationDirective):
+ """Provide a new information registry."""
+
+ _information_type = IInformationProviderType
+
+ def __init__(self, _context, interface, label=None, hint=None):
+ super(InformationRegistryDirective, self).__init__(_context, interface, IInformationProviderInformation, label, hint)
Property changes on: zope.generic/trunk/src/zope/generic/component/metaconfigure.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zope.generic/trunk/src/zope/generic/component/metadirectives.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/metadirectives.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/metadirectives.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -0,0 +1,96 @@
+##############################################################################
+#
+# 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.configuration.fields import GlobalInterface
+from zope.configuration.fields import GlobalObject
+from zope.configuration.fields import MessageID
+from zope.interface import Interface
+
+from zope.generic.component import IInformationProvider
+
+
+
+class IBaseInformationDirective(Interface):
+ """Base information attributes."""
+
+ interface = GlobalInterface(
+ title=_('Interface'),
+ description=_('Interface that represents an information.'),
+ required=True
+ )
+
+ label = MessageID(
+ title=_('Label'),
+ description=_('Label of the information.'),
+ required=False
+ )
+
+ hint = MessageID(
+ title=_('Hint'),
+ description=_('Hint of the informtion.'),
+ required=False
+ )
+
+
+
+class IConfigurationDirective(IBaseInformationDirective):
+ """Declare configuration schema.
+
+ Register configuration schema as interface utility typed by
+ IConfigurationType within the configuration registry utility.
+ """
+
+
+
+class IInformationDirective(IBaseInformationDirective):
+ """Directive to register an information to corresponding information
+ registry."""
+
+ registry = GlobalInterface(
+ title=_('Information Registry Key'),
+ description=_('A registry key is a dedicated interface which should extend' +
+ 'IInformationProvider.'),
+ required=True,
+ constraint=lambda v: v.extends(IInformationProvider)
+ )
+
+
+
+class IInformationRegistryDirective(IBaseInformationDirective):
+ """Directive to register an information registry."""
+
+
+
+class IConfigurationSubdirective(Interface):
+ """Declare a certain configuration of a type."""
+
+ interface = GlobalInterface(
+ title=_('Interface'),
+ description=_('Interface referencing a configuraiton.'),
+ required=True
+ )
+
+ data = GlobalObject(
+ title=_('Data'),
+ description=_('Configuration data component providing the configuraiton interface.'),
+ required=True
+ )
+
Property changes on: zope.generic/trunk/src/zope/generic/component/metadirectives.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: zope.generic/trunk/src/zope/generic/component/testing.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/testing.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/testing.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -18,9 +18,13 @@
__docformat__ = 'restructuredtext'
+import zope.app.testing.placelesssetup
+from zope.component import provideAdapter
from zope.configuration.xmlconfig import XMLConfig
+from zope.interface import Interface
+from zope.schema import TextLine
-import zope.app.testing.placelesssetup
+import zope.generic.component.testing
import zope.generic.directlyprovides.testing
import zope.generic.testing.testing
@@ -30,20 +34,51 @@
#
################################################################################
+class IMarker(Interface):
+ """Demo marker."""
+class IBarConfiguration(Interface):
+
+ bar = TextLine(title=u'Bar')
+
+
+class IInputConfiguration(Interface):
+
+ foo = TextLine(title=u'Foo')
+
+ bar = TextLine(title=u'Bar')
+
+
+class IFooConfiguration(Interface):
+
+ foo = TextLine(title=u'Foo')
+
+ fo = TextLine(title=u'Fo', required=False, readonly=True, default=u'fo default')
+
+
+class TestKeyInterfaceAttriute(object):
+ __key__interface__ = IFooConfiguration
+
+
################################################################################
#
# Placeless setup
#
################################################################################
-
-
# specific tests
def setUp(doctest=None):
- pass
+ # register attribute configurations adapter
+ import zope.generic.component.adapter
+ from zope.generic.component import IConfigurations
+ provideAdapter(zope.generic.component.adapter.AttributeConfigurations,
+ provides=IConfigurations)
+ # register the directive of this package
+ import zope.generic.component
+ XMLConfig('meta.zcml', zope.generic.component)()
+
def tearDown(doctest=None):
pass
@@ -56,14 +91,16 @@
# external setup
zope.generic.testing.testing.setUp(doctest)
zope.generic.directlyprovides.testing.setUp(doctest)
+ zope.generic.component.testing.setUp(doctest)
# internal setup
setUp(doctest)
def tearDown(self, doctest=None):
super(PlacelessSetup, self).tearDown()
# external teardown
+ zope.generic.component.testing.tearDown(doctest)
+ zope.generic.directlyprovides.testing.tearDown(doctest)
zope.generic.testing.testing.tearDown(doctest)
- zope.generic.directlyprovides.testing.tearDown(doctest)
# internal teardown
tearDown(doctest)
Modified: zope.generic/trunk/src/zope/generic/component/tests.py
===================================================================
--- zope.generic/trunk/src/zope/generic/component/tests.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/tests.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -22,23 +22,87 @@
from zope import interface
from zope.testing import doctest
-from zope.generic.configuration.testing import placelesssetup
+
+from zope.generic.testing.testing import InterfaceBaseTest
from zope.generic.testing.testing import registerDirective
+from zope.generic.component import api
from zope.generic.component import testing
+###############################################################################
+#
+# Unit tests
+#
+###############################################################################
+class ConfigurationDataTest(InterfaceBaseTest):
+
+ _verify_class = False
+ _test_interface = testing.IFooConfiguration
+ _test_pos = (testing.IFooConfiguration, {'foo': u'Bla bla'})
+
+ @property
+ def _test_class(self):
+ from zope.generic.component.base import ConfigurationData
+ return ConfigurationData
+
+ def test_readonly_attributes(self):
+ interface = self._test_interface
+ test_obj = self.makeTestObject()
+ for name in interface:
+ field = interface[name]
+ if field.readonly is True:
+ self.assertRaises(ValueError, setattr, test_obj, name, object())
+
+ def test_default_value(self):
+ interface = self._test_interface
+ test_obj = self.makeTestObject()
+ fo_field = interface['fo']
+ self.assertEqual(getattr(test_obj, 'fo'), fo_field.default)
+
+
+class KeyInterfaceAdapterTest(InterfaceBaseTest):
+
+ @property
+ def _test_interface(self):
+ from zope.generic.component import IKeyInterface
+ return IKeyInterface
+
+ @property
+ def _test_class(self):
+ from zope.generic.component.adapter import KeyInterface
+ return KeyInterface
+
+ @property
+ def _test_pos(self):
+ return (testing.TestKeyInterfaceAttriute(),)
+
+
def test_suite():
return unittest.TestSuite((
+ unittest.makeSuite(ConfigurationDataTest),
+ #TODO: Why does it fail? unittest.makeSuite(KeyInterfaceAdapterTest),
+ doctest.DocTestSuite('zope.generic.component.helper'),
+ doctest.DocTestSuite('zope.generic.component.base'),
+ doctest.DocTestSuite('zope.generic.component.event'),
+ doctest.DocTestSuite('zope.generic.component.adapter'),
doctest.DocFileSuite('README.txt',
- setUp=placelesssetup.setUp,
- tearDown=placelesssetup.tearDown,
+ setUp=testing.placelesssetup.setUp,
+ tearDown=testing.placelesssetup.tearDown,
globs={'component': component, 'interface': interface,
'registerDirective': registerDirective,
- 'testing': testing},
+ 'testing': testing, 'api': api},
optionflags=doctest.NORMALIZE_WHITESPACE+
doctest.ELLIPSIS),
+ doctest.DocFileSuite('NEW_README.txt',
+ 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),
))
if __name__ == '__main__': unittest.main()
Added: zope.generic/trunk/src/zope/generic/component/zope.generic.component-meta.zcml
===================================================================
--- zope.generic/trunk/src/zope/generic/component/zope.generic.component-meta.zcml 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/component/zope.generic.component-meta.zcml 2006-04-13 22:55:09 UTC (rev 66938)
@@ -0,0 +1,5 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <include package="zope.generic.component" file="meta.zcml" />
+
+</configure>
Property changes on: zope.generic/trunk/src/zope/generic/component/zope.generic.component-meta.zcml
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: zope.generic/trunk/src/zope/generic/operation/README.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/operation/README.txt 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/operation/README.txt 2006-04-13 22:55:09 UTC (rev 66938)
@@ -147,9 +147,9 @@
For each operation directive we registered an operation information. This
operation information can be retrieved:
- >>> from zope.generic.information.api import registeredInformations
+ >>> from zope.generic.component.api import getInformationProvidersFor
- >>> listing = list(registeredInformations(api.IOperationInformation))
+ >>> listing = list(getInformationProvidersFor(api.IOperationInformation))
>>> len(listing)
4
Modified: zope.generic/trunk/src/zope/generic/operation/base.py
===================================================================
--- zope.generic/trunk/src/zope/generic/operation/base.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/operation/base.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -21,26 +21,29 @@
from zope.interface import implements
from zope.schema.fieldproperty import FieldProperty
+from zope.generic.component import IAttributeKeyInterface
+from zope.generic.component.api import KeyInterface
+
from zope.generic.operation import IOperation
from zope.generic.operation import IPrivateOperation
-class Operation(object):
+class Operation(KeyInterface):
"""Generic operation wrapper."""
implements(IOperation)
- interface = FieldProperty(IOperation['interface'])
+ interface = FieldProperty(IAttributeKeyInterface['__key_interface__'])
def __init__(self, callable=None, interface=None):
self.__callable = callable
# otherwise use IPrivatConfigurationHandler
if interface is not None:
- self.interface = interface
+ self.__key_interface__ = interface
else:
- self.interface = IPrivateOperation
+ self.__key_interface__ = IPrivateOperation
def __call__(self, context, *pos, **kws):
self._proceed(context)
Modified: zope.generic/trunk/src/zope/generic/operation/helper.py
===================================================================
--- zope.generic/trunk/src/zope/generic/operation/helper.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/operation/helper.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -18,8 +18,8 @@
__docformat__ = 'restructuredtext'
-from zope.generic.information.api import getInformation
-from zope.generic.configuration.api import getConfigurationData
+from zope.generic.component.api import getInformationProvider
+from zope.generic.component.api import getInformation
from zope.generic.operation import IOperationInformation
from zope.generic.operation import IOperationConfiguration
@@ -28,7 +28,7 @@
def getOperationInformation(object):
"""Evaluate an operation information from an object."""
- return getInformation(object, IOperationInformation)
+ return getInformationProvider(object, IOperationInformation)
@@ -45,7 +45,7 @@
def getOperationConfiguration(object):
"""Evaluate an operation configuration."""
- return getConfigurationData(getOperationInformation(object), IOperationConfiguration)
+ return getInformation(getOperationInformation(object), IOperationConfiguration)
Modified: zope.generic/trunk/src/zope/generic/operation/interfaces.py
===================================================================
--- zope.generic/trunk/src/zope/generic/operation/interfaces.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/operation/interfaces.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -27,9 +27,10 @@
from zope.schema import Tuple
from zope.generic.component import IKeyInterface
-from zope.generic.configuration import IConfigurationType
-from zope.generic.information import IInformation
-from zope.generic.information import IInformationRegistryType
+from zope.generic.component import IConfigurationType
+from zope.generic.component import IInformationProvider
+from zope.generic.component import IInformationProviderType
+
from zope.generic.type import ITypeType
@@ -65,10 +66,10 @@
-class IOperationInformation(IInformation):
+class IOperationInformation(IInformationProvider):
"""Registration about an global operation."""
-alsoProvides(IOperationInformation, IInformationRegistryType)
+alsoProvides(IOperationInformation, IInformationProviderType)
Modified: zope.generic/trunk/src/zope/generic/operation/metaconfigure.py
===================================================================
--- zope.generic/trunk/src/zope/generic/operation/metaconfigure.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/operation/metaconfigure.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -22,14 +22,14 @@
from zope.configuration.exceptions import ConfigurationError
from zope.interface import alsoProvides
-from zope.generic.information.api import queryInformation
-from zope.generic.information.metaconfigure import provideInformation
+from zope.generic.component.api import queryInformationProvider
+from zope.generic.component.metaconfigure import provideInformationProvider
-from zope.generic.configuration import IConfigurationType
-from zope.generic.configuration import IConfigurations
-from zope.generic.configuration.api import ConfigurationData
-from zope.generic.configuration.api import provideConfigurationData
-from zope.generic.configuration.api import queryConfigurationData
+from zope.generic.component import IConfigurationType
+from zope.generic.component import IConfigurations
+from zope.generic.component.api import ConfigurationData
+from zope.generic.component.api import provideInformation
+from zope.generic.component.api import queryInformation
from zope.generic.operation import IOperation
from zope.generic.operation import IOperationConfiguration
@@ -47,12 +47,12 @@
if IOperationType.providedBy(handler):
registry = IOperationInformation
- info = queryInformation(handler, IOperationInformation)
+ info = queryInformationProvider(handler, IOperationInformation)
if info is None:
ConfigurationError('Operation %s does not exist.' % handler.__name__)
- config = queryConfigurationData(info, IOperationConfiguration)
+ config = queryInformation(info, IOperationConfiguration)
if config is None:
ConfigurationError('OperationConfiguration for Operation %s does not exist.' % handler.__name__)
@@ -68,7 +68,7 @@
"""Provide the handler to an configuration information."""
registry = IOperationInformation
- info = queryInformation(interface, IOperationInformation)
+ info = queryInformationProvider(interface, IOperationInformation)
# this should never happen...
if info is None:
@@ -87,7 +87,7 @@
configurations = IConfigurations(info)
# create and set configuration data
- provideConfigurationData(info, IOperationConfiguration,
+ provideInformation(info, IOperationConfiguration,
{'operation': operation, 'input': tuple(input), 'output': tuple(output)})
@@ -102,8 +102,8 @@
registry = IOperationInformation
_context.action(
- discriminator = ('provideInformation', interface, registry),
- callable = provideInformation,
+ discriminator = ('provideInformationProvider', interface, registry),
+ callable = provideInformationProvider,
args = (interface, registry, label, hint),
)
Modified: zope.generic/trunk/src/zope/generic/operation/metadirectives.py
===================================================================
--- zope.generic/trunk/src/zope/generic/operation/metadirectives.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/operation/metadirectives.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -23,8 +23,8 @@
from zope.configuration.fields import GlobalObject
from zope.configuration.fields import Tokens
-from zope.generic.configuration import IConfigurationType
-from zope.generic.information.metadirectives import IBaseInformationDirective
+from zope.generic.component import IConfigurationType
+from zope.generic.component.metadirectives import IBaseInformationDirective
Modified: zope.generic/trunk/src/zope/generic/operation/testing.py
===================================================================
--- zope.generic/trunk/src/zope/generic/operation/testing.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/operation/testing.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -22,13 +22,13 @@
import zope.app.testing.placelesssetup
import zope.generic.component.testing
-import zope.generic.configuration.testing
+import zope.generic.component.testing
import zope.generic.directlyprovides.testing
-import zope.generic.information.testing
+import zope.generic.component.testing
import zope.generic.operation
import zope.generic.testing.testing
-from zope.generic.information.api import provideInformation
+from zope.generic.component.metaconfigure import provideInformationProvider
from zope.generic.operation import IOperationInformation
@@ -49,7 +49,7 @@
# specific tests
def setUp(doctest=None):
# register operation information registry
- provideInformation(IOperationInformation)
+ provideInformationProvider(IOperationInformation)
# register the directive of this package
XMLConfig('meta.zcml', zope.generic.operation)()
@@ -67,8 +67,8 @@
zope.generic.testing.testing.setUp(doctest)
zope.generic.directlyprovides.testing.setUp(doctest)
zope.generic.component.testing.setUp(doctest)
- zope.generic.information.testing.setUp(doctest)
- zope.generic.configuration.testing.setUp(doctest)
+ zope.generic.component.testing.setUp(doctest)
+ zope.generic.component.testing.setUp(doctest)
# internal setup
setUp(doctest)
@@ -78,8 +78,8 @@
zope.generic.testing.testing.tearDown(doctest)
zope.generic.directlyprovides.testing.tearDown(doctest)
zope.generic.component.testing.tearDown(doctest)
- zope.generic.information.testing.tearDown(doctest)
- zope.generic.configuration.testing.tearDown(doctest)
+ zope.generic.component.testing.tearDown(doctest)
+ zope.generic.component.testing.tearDown(doctest)
# internal teardown
tearDown(doctest)
Modified: zope.generic/trunk/src/zope/generic/type/DEPENDENCIES.cfg
===================================================================
--- zope.generic/trunk/src/zope/generic/type/DEPENDENCIES.cfg 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/DEPENDENCIES.cfg 2006-04-13 22:55:09 UTC (rev 66938)
@@ -1,7 +1,7 @@
persistent
-zope.generic.configuration
+zope.generic.component
zope.generic.directlyprovides
-zope.generic.information
+zope.generic.component
zope.generic.testing
zope.app.annotation
zope.app.component
Modified: zope.generic/trunk/src/zope/generic/type/EXAMPLE.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/type/EXAMPLE.txt 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/EXAMPLE.txt 2006-04-13 22:55:09 UTC (rev 66938)
@@ -61,9 +61,9 @@
Step 3: Implement Specific Handlers and the type-specific default data
----------------------------------------------------------------------
- >>> from zope.generic.configuration.api import queryConfigurationData
- >>> from zope.generic.configuration.api import provideConfigurationData
- >>> from zope.generic.configuration.api import deleteConfigurationData
+ >>> from zope.generic.component.api import queryInformation
+ >>> from zope.generic.component.api import provideInformation
+ >>> from zope.generic.component.api import deleteInformation
>>> from zope.generic.type.api import queryTypeConfiguration
Let's implement the initializer of the article. Initializers are called from
@@ -77,7 +77,7 @@
... - raises an exception if no configurationis defined
... """
... # looks up the allready configured data on the object
- ... article_config = queryConfigurationData(context,
+ ... article_config = queryInformation(context,
... IArticleInitializationConfiguration)
... if article_config is None:
... text_config = queryTypeConfiguration(context, ITextConfig)
@@ -86,11 +86,11 @@
... else:
... text, note = article_config.text, article_config.note
...
- ... provideConfigurationData(context, ITextConfig, {'body': text})
- ... provideConfigurationData(context, INoteConfig, {'body': note})
- ... deleteConfigurationData(context, IArticleInitializationConfiguration)
+ ... provideInformation(context, ITextConfig, {'body': text})
+ ... provideInformation(context, INoteConfig, {'body': note})
+ ... deleteInformation(context, IArticleInitializationConfiguration)
- >>> from zope.generic.configuration.api import ConfigurationData
+ >>> from zope.generic.component.api import ConfigurationData
>>> textDefaults = ConfigurationData(ITextConfig,
... {'body': u"This is the default text."})
@@ -167,10 +167,10 @@
>>> IArticle.providedBy(article)
True
- >>> queryConfigurationData(article, ITextConfig).body
+ >>> queryInformation(article, ITextConfig).body
'First version of article.'
- >>> queryConfigurationData(article, IArticleInitializationConfiguration).text
+ >>> queryInformation(article, IArticleInitializationConfiguration).text
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'text'
Modified: zope.generic/trunk/src/zope/generic/type/README.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/type/README.txt 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/README.txt 2006-04-13 22:55:09 UTC (rev 66938)
@@ -18,7 +18,7 @@
of instances marked by a certain type marker interface.
The type directive does extend the information directive
-(see zope.generic.information).
+(see zope.generic.component).
Base type directive
@@ -81,7 +81,7 @@
>>> info = queryUtility(api.ITypeInformation, toDottedName(IFooMarker))
- >>> info.interface == IFooMarker
+ >>> info.key == IFooMarker
True
>>> info.label
u'Foo Type'
@@ -104,7 +104,7 @@
There are serveral subdirectives like:
-- configurations (see zope.generic.information)
+- configurations (see zope.generic.component)
- initializer
You can extend type informations by the annotations and configurations mechanism
@@ -139,7 +139,7 @@
... />
... ''')
- >>> from zope.generic.configuration.api import ConfigurationData
+ >>> from zope.generic.component.api import ConfigurationData
>>> typedata = ConfigurationData(IAnyConfiguration, {'any': u'Guguseli from Type!'})
>>> IAnyConfiguration.providedBy(typedata)
True
@@ -212,7 +212,7 @@
>>> api.acquireObjectConfiguration(bar, IOtherConfiguration).other
u'Specific initialization data.'
- >>> from zope.generic.configuration.api import IConfigurations
+ >>> from zope.generic.component.api import IConfigurations
>>> objectdata = ConfigurationData(IAnyConfiguration, {'any': u'Guguseli from Object!'})
>>> IConfigurations(bar)[IAnyConfiguration] = objectdata
Modified: zope.generic/trunk/src/zope/generic/type/adapter.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/adapter.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/adapter.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -28,7 +28,7 @@
from zope.event import notify
from zope.interface import implements
-from zope.generic.configuration.api import provideConfigurationData
+from zope.generic.component.api import provideInformation
from zope.generic.type import IInitializer
from zope.generic.type import IInitializerConfiguration
@@ -52,7 +52,7 @@
if config:
# store initialization data
if config.interface:
- provideConfigurationData(self.context, config.interface, kws)
+ provideInformation(self.context, config.interface, kws)
# invoke initialization handler
Modified: zope.generic/trunk/src/zope/generic/type/base.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/base.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/base.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -27,7 +27,7 @@
from zope.app.container import btree
from zope.app import folder
-from zope.generic.configuration.api import IAttributeConfigurable
+from zope.generic.component.api import IAttributeConfigurable
from zope.generic.directlyprovides.api import provides
from zope.generic.directlyprovides.api import UpdateProvides
from zope.generic.directlyprovides.api import updateDirectlyProvided
Modified: zope.generic/trunk/src/zope/generic/type/configure.zcml
===================================================================
--- zope.generic/trunk/src/zope/generic/type/configure.zcml 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/configure.zcml 2006-04-13 22:55:09 UTC (rev 66938)
@@ -4,7 +4,7 @@
i18n_domain="zope">
<generic:information
- interface="zope.generic.information.IInformationRegistryInformation"
+ interface="zope.generic.component.IInformationProviderInformation"
label="Type Information Registry"
registry=".ITypeInformation"
/>
Modified: zope.generic/trunk/src/zope/generic/type/helper.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/helper.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/helper.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -21,8 +21,8 @@
from zope import component
from zope.generic.component.api import toDottedName
-from zope.generic.configuration.api import queryConfigurationData
-from zope.generic.information.api import queryInformation
+from zope.generic.component.api import queryInformation
+from zope.generic.component.api import queryInformationProvider
from zope.generic.type import IInitializerConfiguration
from zope.generic.type import ITypeInformation
@@ -72,7 +72,7 @@
def getTypeInformation(object):
- return queryInformation(getType(object), ITypeInformation)
+ return queryInformationProvider(getType(object), ITypeInformation)
@@ -88,13 +88,13 @@
def queryObjectConfiguration(object, configuration, default=None):
- return queryConfigurationData(object, configuration, default)
+ return queryInformation(object, configuration, default)
def queryTypeConfiguration(object, configuration, default=None):
info = queryTypeInformation(object)
- return queryConfigurationData(info, configuration, default)
+ return queryInformation(info, configuration, default)
Modified: zope.generic/trunk/src/zope/generic/type/interfaces.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/interfaces.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/interfaces.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -26,9 +26,9 @@
from zope.schema import Object
from zope.generic.component import IKeyInterface
-from zope.generic.configuration import IConfigurationType
+from zope.generic.component import IConfigurationType
from zope.generic.directlyprovides import IProvides
-from zope.generic.information import IInformation
+from zope.generic.component import IInformationProvider
__all__ = ['ITypeType', 'ITypeable', 'ITyped', 'IDirectlyTyped',
@@ -77,7 +77,7 @@
-class ITypeInformation(IInformation):
+class ITypeInformation(IInformationProvider):
"""Provide information for the declared type interface."""
Modified: zope.generic/trunk/src/zope/generic/type/meta.zcml
===================================================================
--- zope.generic/trunk/src/zope/generic/type/meta.zcml 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/meta.zcml 2006-04-13 22:55:09 UTC (rev 66938)
@@ -12,7 +12,7 @@
<meta:subdirective
name="configuration"
- schema="zope.generic.information.metadirectives.IConfigurationSubdirective"
+ schema="zope.generic.component.metadirectives.IConfigurationSubdirective"
/>
<meta:subdirective
Modified: zope.generic/trunk/src/zope/generic/type/metaconfigure.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/metaconfigure.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/metaconfigure.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -31,9 +31,9 @@
from zope.security.checker import InterfaceChecker
from zope.generic.component.api import toDottedName
-from zope.generic.configuration.api import ConfigurationData
-from zope.generic.configuration.api import provideConfigurationData
-from zope.generic.information.metaconfigure import InformationDirective
+from zope.generic.component.api import ConfigurationData
+from zope.generic.component.api import provideInformation
+from zope.generic.component.metaconfigure import InformationDirective
from zope.generic.type import IInitializationHandler
from zope.generic.type import IInitializerConfiguration
@@ -49,7 +49,7 @@
"""Set configuration data into the context."""
info = queryTypeInformation(interface)
- provideConfigurationData(info, configuration, data)
+ provideInformation(info, configuration, data)
Modified: zope.generic/trunk/src/zope/generic/type/metadirectives.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/metadirectives.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/metadirectives.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -24,7 +24,7 @@
from zope.configuration.fields import GlobalObject
from zope.interface import Interface
-from zope.generic.information.metadirectives import IBaseInformationDirective
+from zope.generic.component.metadirectives import IBaseInformationDirective
Modified: zope.generic/trunk/src/zope/generic/type/testing.py
===================================================================
--- zope.generic/trunk/src/zope/generic/type/testing.py 2006-04-13 17:52:04 UTC (rev 66937)
+++ zope.generic/trunk/src/zope/generic/type/testing.py 2006-04-13 22:55:09 UTC (rev 66938)
@@ -22,9 +22,9 @@
import zope.app.testing.placelesssetup
import zope.generic.component.testing
-import zope.generic.configuration.testing
+import zope.generic.component.testing
import zope.generic.directlyprovides.testing
-import zope.generic.information.testing
+import zope.generic.component.testing
import zope.generic.testing.testing
################################################################################
@@ -63,8 +63,8 @@
zope.generic.testing.testing.setUp(doctest)
zope.generic.directlyprovides.testing.setUp(doctest)
zope.generic.component.testing.setUp(doctest)
- zope.generic.information.testing.setUp(doctest)
- zope.generic.configuration.testing.setUp(doctest)
+ zope.generic.component.testing.setUp(doctest)
+ zope.generic.component.testing.setUp(doctest)
# internal setup
setUp(doctest)
@@ -74,8 +74,8 @@
zope.generic.testing.testing.tearDown(doctest)
zope.generic.directlyprovides.testing.tearDown(doctest)
zope.generic.component.testing.tearDown(doctest)
- zope.generic.information.testing.tearDown(doctest)
- zope.generic.configuration.testing.tearDown(doctest)
+ zope.generic.component.testing.tearDown(doctest)
+ zope.generic.component.testing.tearDown(doctest)
# internal teardown
tearDown(doctest)
More information about the Checkins
mailing list