[Checkins] SVN: zope.generic/trunk/src/zope/generic/ .configuration:

Dominik Huber dominik.huber at perse.ch
Mon May 22 08:31:02 EDT 2006


Log message for revision 68237:
  .configuration:
  - IConfigurations.update: (keyface, dict) or (configuration) or (keyfa, configuration)
  - IConfigurations.__setitem__: raise error if item already exists
  - api: deleteConfiguration and updateConfiguration
  
  .informationprovider:
  - cleanup and changes of .configuration

Changed:
  U   zope.generic/trunk/src/zope/generic/configuration/README.txt
  U   zope.generic/trunk/src/zope/generic/configuration/adapter.py
  U   zope.generic/trunk/src/zope/generic/configuration/api.py
  U   zope.generic/trunk/src/zope/generic/face/api.py
  U   zope.generic/trunk/src/zope/generic/factory/factory.py
  U   zope.generic/trunk/src/zope/generic/informationprovider/NEW_README.txt
  U   zope.generic/trunk/src/zope/generic/informationprovider/README.txt
  U   zope.generic/trunk/src/zope/generic/informationprovider/api.py

-=-
Modified: zope.generic/trunk/src/zope/generic/configuration/README.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/README.txt	2006-05-22 11:29:15 UTC (rev 68236)
+++ zope.generic/trunk/src/zope/generic/configuration/README.txt	2006-05-22 12:31:00 UTC (rev 68237)
@@ -96,44 +96,76 @@
     >>> configurations[IFooConfiguration] = object()
     Traceback (most recent call last):
     ...
-    ValueError: Value does not provide IFooConfiguration.
+    ValueError: Value does not provide IFooConfiguration or is not a dictionary.
 
-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:
+    >>> from zope.generic.configuration.api import createConfiguration
+    >>> data = createConfiguration(IFooConfiguration, {'foo': u'Foo!'})
 
-    >>> configurations.update(IFooConfiguration, {'foo': u'Foo!'})
+    >>> configurations[IFooConfiguration] = data
+
+You can set a configuraiton only once. Otherwise you should use the update method
+or delete the configuraiton before a new setting:
+
+    >>> configurations[IFooConfiguration] = data
     Traceback (most recent call last):
     ...
-    KeyError: <InterfaceClass example.IFooConfiguration>
+    ValueError: Configuration is already provided IFooConfiguration.
 
+    >>> del configurations[IFooConfiguration]
+
+You can also use only a dictionary as value instead of a configuration:
+
+    >>> configurations[IFooConfiguration] = {'foo': u'Foo!'}
+    >>> configurations[IFooConfiguration].foo
+    u'Foo!'
+
+    >>> del configurations[IFooConfiguration]
+
+Furthermore there is an update method that can be used to update a specific
+configuration. You can use the method to provide an initial configuration or
+to update parts of a configuration:
+
+    >>> configurations.update(IFooConfiguration, {'foo': u'Foo!'})
+    >>> configurations[IFooConfiguration].foo
+    u'Foo!'
+    
+    >>> configurations.update(IFooConfiguration, {'foo': u'Foo x!'})
+    >>> configurations[IFooConfiguration].foo
+    u'Foo x!'
+
+    >>> config = createConfiguration(IFooConfiguration, {'foo': u'Foo y!'})
+    >>> configurations.update(IFooConfiguration, config)
+    >>> configurations[IFooConfiguration].foo
+    u'Foo y!'
+
+    >>> config = createConfiguration(IFooConfiguration, {'foo': u'Foo z!'})
+    >>> configurations.update(config)
+    >>> configurations[IFooConfiguration].foo
+    u'Foo z!'
+
 You can create valid configuration data using the generic createConfiguration
 implementation and a configuration schema. 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:
 
     >>> from zope.component.eventtesting import getEvents, clearEvents
-    >>> from zope.generic.configuration.api import createConfiguration
     >>> from zope.generic.configuration.api import IObjectConfiguredEvent
 
     >>> clearEvents()
 
-    >>> data = createConfiguration(IFooConfiguration, {'foo': u'Foo!'})
+    >>> del configurations[IFooConfiguration]
 
-    >>> configurations[IFooConfiguration] = data
-
-    >>> events = getEvents()
-    >>> len(events)
-    0
-
     >>> from zope.location import Location
     >>> parent = Location()
     >>> configurations.__parent__ = parent
-    
+
     >>> configurations[IFooConfiguration] = data
     >>> events = getEvents()
     >>> len(events)
     0
 
+    >>> del configurations[IFooConfiguration]
+
     >>> parent.__parent__ = Location()
     >>> configurations[IFooConfiguration] = data
     >>> events = getEvents()
@@ -163,7 +195,8 @@
 
 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:
+configuration modified event is notify else not. This can be done by a dict
+or a configuration:
 
     >>> clearEvents()
     >>> configurations.update(IFooConfiguration, {'foo': u'Bar!'})
@@ -174,6 +207,16 @@
     >>> [(key.__name__, value) for key, value in event.items()]
     [('IFooConfiguration', {'foo': u'Bar!'})]
 
+    >>> clearEvents()
+    >>> foo_config = api.createConfiguration(IFooConfiguration, {'foo': u'Bar !'})
+    >>> configurations.update(foo_config)
+    >>> 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()

Modified: zope.generic/trunk/src/zope/generic/configuration/adapter.py
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/adapter.py	2006-05-22 11:29:15 UTC (rev 68236)
+++ zope.generic/trunk/src/zope/generic/configuration/adapter.py	2006-05-22 12:31:00 UTC (rev 68237)
@@ -28,12 +28,14 @@
 from zope.event import notify
 from zope.interface import implements
 
+from zope.generic.face.api import getKeyface
 from zope.generic.face.api import toDottedName
 from zope.generic.face.api import toInterface
 
 from zope.generic.configuration import IAttributeConfigurable
 from zope.generic.configuration import IConfigurationType
 from zope.generic.configuration import IConfigurations
+from zope.generic.configuration.base import createConfiguration
 from zope.generic.configuration.event import Configuration
 from zope.generic.configuration.event import ObjectConfiguredEvent
 from zope.generic.configuration.helper import configuratonToDict
@@ -77,23 +79,50 @@
 
         return [toInterface(iface) for iface in configurations.keys()]
 
-    def update(self, keyface, data):
-        current_config = self[keyface]
+    def update(self, keyfaced_or_keyface, data=None):
+        """Update a configuration."""
+        
+        keyface = getKeyface(keyfaced_or_keyface)
+        # feed by a configuration
+        isconfig = False
+        if keyface != keyfaced_or_keyface:
+            data = keyfaced_or_keyface
+            isconfig = True
 
+        elif keyface.providedBy(data):
+            isconfig = True
+
+        try:
+            current_config = self[keyface]
+        except KeyError:
+            # there is no existing configuration, try to set a new one
+            self[keyface] = data
+            return
+
         updated_data = {}
         errors = []
         
         savepoint = transaction.savepoint()
         try:
-            for name, value in data.items():
-                # raise attribute error
+            for name in keyface:
                 field = keyface[name]
+
+                # readonly attribute cannot be updated
                 if field.readonly:
                     raise ValueError(name, 'Data is readonly.')
+
+                if isconfig:
+                    value = getattr(data, name, field.missing_value)
+                # assume dict
                 else:
-                    if value != getattr(current_config, name, field.missing_value):
-                        setattr(current_config, name, value)
-                        updated_data[name] = value
+                    try:
+                        value = data[name]
+                    except KeyError:
+                        continue
+                    
+                if value != getattr(current_config, name, field.missing_value):
+                    setattr(current_config, name, value)
+                    updated_data[name] = value
 
             # notify update
             parent = self.__parent__
@@ -111,20 +140,30 @@
             raise KeyError('Interface key %s requires %s.' % 
                 (keyface.__name__, IConfigurationType.__name__))
 
-        if not keyface.providedBy(value):
-            raise ValueError('Value does not provide %s.' % keyface.__name__)
+        if not (keyface.providedBy(value) or isinstance(value, dict)):
+            raise ValueError('Value does not provide %s or is not a dictionary.' % keyface.__name__)
 
         # essentials
         try:
             configurations = self.context.__configurations__
         except AttributeError:
             configurations = self.context.__configurations__ = OOBTree()
+        
+        # avoid unintended overwrittings of a configuration
+        key = toDottedName(keyface)
+        if key in configurations:
+            raise ValueError('Configuration is already provided %s.' % keyface.__name__)
 
-        data = configuratonToDict(value, all=True)
-        configurations[toDottedName(keyface)] = value
+        # set configuration or dictionary
+        if keyface.providedBy(value):
+            configurations[key] = value
+        else:
+            configurations[key] = createConfiguration(keyface, value)
+
         # notify setting
         parent = self.__parent__
         if ILocation.providedBy(parent) and parent.__parent__ is not None:
+            data = configuratonToDict(value, all=True)
             notify(ObjectConfiguredEvent(parent, 
                 Configuration(keyface, data)))
 

Modified: zope.generic/trunk/src/zope/generic/configuration/api.py
===================================================================
--- zope.generic/trunk/src/zope/generic/configuration/api.py	2006-05-22 11:29:15 UTC (rev 68236)
+++ zope.generic/trunk/src/zope/generic/configuration/api.py	2006-05-22 12:31:00 UTC (rev 68237)
@@ -18,6 +18,8 @@
 
 __docformat__ = 'restructuredtext'
 
+from zope.generic.face.api import getKeyface
+
 from zope.generic.configuration import *
 from zope.generic.configuration.adapter import AttributeConfigurations
 from zope.generic.configuration.base import createConfiguration
@@ -27,22 +29,36 @@
 
 
 
-def getConfiguration(context, configuration):
+def getConfiguration(context, keyface):
     """Evaluate a configuration."""
-    return configuration(IConfigurations(context))
+    return keyface(IConfigurations(context))
 
 
 
-def queryConfiguration(context, configuration, default=None):
+def queryConfiguration(context, keyface, default=None):
     """Evaluate a configuration or return default."""
     try:
-        return getConfiguration(context, configuration)
+        return getConfiguration(context, keyface)
     
     except:
         return default
 
 
 
+def updateConfiguration(context, keyfaced_or_keyface, data=None):
+    """Set or update a configuration to/of a context."""
+
+    IConfigurations(context).update(keyfaced_or_keyface, data)
+
+
+
+def deleteConfiguration(context, keyface):
+    """Delete a configuration from a context."""
+
+    del IConfigurations(context)[keyface]
+
+
+
 def parameterToConfiguration(__keyface__, *pos, **kws):
     """Create configuration data
 

Modified: zope.generic/trunk/src/zope/generic/face/api.py
===================================================================
--- zope.generic/trunk/src/zope/generic/face/api.py	2006-05-22 11:29:15 UTC (rev 68236)
+++ zope.generic/trunk/src/zope/generic/face/api.py	2006-05-22 12:31:00 UTC (rev 68237)
@@ -34,12 +34,7 @@
     if object is None:
         return default
 
-    # todo replace IInterface by IKeyfaceType
-    if IInterface.providedBy(object):
-        if not IKeyfaceType.providedBy(object):
-            #print object
-            pass
-        
+    if IKeyfaceType.providedBy(object):
         return object
 
     if IAttributeFaced.providedBy(object):

Modified: zope.generic/trunk/src/zope/generic/factory/factory.py
===================================================================
--- zope.generic/trunk/src/zope/generic/factory/factory.py	2006-05-22 11:29:15 UTC (rev 68236)
+++ zope.generic/trunk/src/zope/generic/factory/factory.py	2006-05-22 12:31:00 UTC (rev 68237)
@@ -142,6 +142,10 @@
     If we like to provide parameter we have to declare them by an input
     configuration:
 
+        >>> from zope.generic.informationprovider.api import deleteInformation
+        >>> from zope.generic.operation import IOperationConfiguration
+        >>> deleteInformation(IOperationConfiguration, IMyInstance)
+
         >>> from zope.schema import TextLine
 
         >>> class SimpleKeyFacedWithParameter(object):

Modified: zope.generic/trunk/src/zope/generic/informationprovider/NEW_README.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/informationprovider/NEW_README.txt	2006-05-22 11:29:15 UTC (rev 68236)
+++ zope.generic/trunk/src/zope/generic/informationprovider/NEW_README.txt	2006-05-22 12:31:00 UTC (rev 68237)
@@ -222,6 +222,8 @@
 If we like to acquire from the default user context configuration, we have
 to derive our marker from IUndefinedKeyface.
 
+    >>> api.deleteInformation(ILogConfiguration, IMy, ISupplierContext)
+
     >>> class IMy(IUndefinedKeyface):
     ...     """My own key interface."""
 

Modified: zope.generic/trunk/src/zope/generic/informationprovider/README.txt
===================================================================
--- zope.generic/trunk/src/zope/generic/informationprovider/README.txt	2006-05-22 11:29:15 UTC (rev 68236)
+++ zope.generic/trunk/src/zope/generic/informationprovider/README.txt	2006-05-22 12:31:00 UTC (rev 68237)
@@ -264,9 +264,13 @@
 
 The other way round we can play with key interface inheritance:
 
+    >>> from zope.generic.face import IKeyfaceType
+
     >>> class IBar(interface.Interface):
     ...    pass
 
+    >>> interface.alsoProvides(IBar, IKeyfaceType)
+
     >>> api.acquireInformationProvider(IBar) 
     Traceback (most recent call last):
     ...
@@ -275,6 +279,8 @@
     >>> class IFooBar(IFoo, IBar):
     ...    pass
 
+    >>> interface.alsoProvides(IFooBar, IKeyfaceType)
+
     >>> api.acquireInformationProvider(IFooBar) 
     <GlobalInformationProvider IFoo at IUndefinedContext>
 
@@ -295,6 +301,8 @@
     >>> class IBarFoo(IBar, IFoo):
     ...    pass
 
+    >>> interface.alsoProvides(IBarFoo, IKeyfaceType)
+
     >>> api.acquireInformationProvider(IBarFoo) 
     <GlobalInformationProvider IBar at IUndefinedContext>
 

Modified: zope.generic/trunk/src/zope/generic/informationprovider/api.py
===================================================================
--- zope.generic/trunk/src/zope/generic/informationprovider/api.py	2006-05-22 11:29:15 UTC (rev 68236)
+++ zope.generic/trunk/src/zope/generic/informationprovider/api.py	2006-05-22 12:31:00 UTC (rev 68237)
@@ -24,7 +24,8 @@
 
 from zope.generic.configuration import IConfigurationType
 from zope.generic.configuration import IConfigurations
-from zope.generic.configuration.api import createConfiguration
+from zope.generic.configuration.api import deleteConfiguration
+from zope.generic.configuration.api import updateConfiguration
 from zope.generic.face import IConfaceType
 from zope.generic.face import IKeyfaceType
 from zope.generic.face import IUndefinedContext
@@ -143,10 +144,7 @@
         context = getInformationProvider(keyface, conface)
 
     if IConfigurationType.providedBy(informationkey):
-        if type(information) is dict:
-            information = createConfiguration(informationkey, information)
-    
-        IConfigurations(context)[informationkey] = information
+        updateConfiguration(context, informationkey, information)
 
     else:
         IAnnotations(context)[informationkey] = information
@@ -163,7 +161,7 @@
         context = getInformationProvider(keyface, conface)
 
     if IConfigurationType.providedBy(informationkey):
-        del IConfigurations(context)[informationkey]
+        deleteConfiguration(context, informationkey)
     
     else:
         del IAnnotations(context)[informationkey]



More information about the Checkins mailing list