[Zope3-checkins] CVS: Zope3/src/zope/app/services - configuration.py:1.16
Jim Fulton
jim@zope.com
Fri, 21 Mar 2003 16:06:29 -0500
Update of /cvs-repository/Zope3/src/zope/app/services
In directory cvs.zope.org:/tmp/cvs-serv19800/src/zope/app/services
Modified Files:
configuration.py
Log Message:
Refactoried the class hierarchy to separate component
management from named registration.
Introducted a new simple componentPath field.
=== Zope3/src/zope/app/services/configuration.py 1.15 => 1.16 ===
--- Zope3/src/zope/app/services/configuration.py:1.15 Fri Mar 21 10:29:09 2003
+++ Zope3/src/zope/app/services/configuration.py Fri Mar 21 16:05:58 2003
@@ -18,34 +18,34 @@
__metaclass__ = type
from persistence import Persistent
-
-from zope.app.interfaces.annotation import IAttributeAnnotatable
-
-from zope.component \
- import getAdapter, getService, queryService, getServiceManager
-
-from zope.proxy.context import ContextMethod, ContextWrapper
-from zope.proxy.introspection import removeAllProxies
-
-from zope.security.checker import InterfaceChecker
-from zope.security.proxy import Proxy
-
from zope.app.interfaces.annotation import IAnnotations
+from zope.app.interfaces.annotation import IAttributeAnnotatable
from zope.app.interfaces.container import IAddNotifiable, IDeleteNotifiable
+from zope.app.interfaces.container import IZopeWriteContainer
from zope.app.interfaces.dependable import IDependable, DependencyError
-
+from zope.app.interfaces.services.configuration import IConfigurationManager
from zope.app.interfaces.services.configuration import IConfigurationRegistry
from zope.app.interfaces.services.configuration \
- import INameComponentConfigurable, INamedConfiguration, IConfiguration
+ import INameComponentConfigurable
+from zope.app.interfaces.services.configuration import INamedConfiguration
+from zope.app.interfaces.services.configuration import IConfiguration
from zope.app.interfaces.services.configuration \
- import INamedComponentConfiguration, INameConfigurable
-from zope.app.interfaces.services.configuration import IUseConfiguration
+ import INamedComponentConfiguration
+from zope.app.interfaces.services.configuration import INameConfigurable
from zope.app.interfaces.services.configuration \
- import Unregistered, Registered, Active
-
-from zope.app.traversing \
- import getRoot, getPath, traverse, canonicalPath
+ import INamedComponentConfiguration, IComponentConfiguration
+from zope.app.interfaces.services.configuration import IUseConfiguration
+from zope.app.interfaces.services.configuration import Unregistered
+from zope.app.interfaces.services.configuration import Registered, Active
+from zope.app.traversing import getRoot, getPath, traverse
+from zope.app.traversing import canonicalPath
+from zope.component import getAdapter
+from zope.component import getService, queryService, getServiceManager
+from zope.proxy.context import ContextMethod, ContextWrapper
+from zope.proxy.introspection import removeAllProxies
+from zope.security.checker import InterfaceChecker
+from zope.security.proxy import Proxy
class ConfigurationStatusProperty:
@@ -61,6 +61,9 @@
configuration = inst
service = queryService(configuration, self.service)
+ # XXX The following may fail; there's a subtle bug here when
+ # the returned service isn't in the same service manager as
+ # the one owning the configuration.
registry = service and service.queryConfigurationsFor(configuration)
if registry:
@@ -307,29 +310,28 @@
def __init__(self, name):
self.name = name
- super(NamedConfiguration, self).__init__()
def usageSummary(self):
return "%s %s" % (self.name, self.__class__.__name__)
-class NamedComponentConfiguration(NamedConfiguration):
- """Named component configuration
+class ComponentConfiguration(SimpleConfiguration):
+ """Component configuration.
Subclasses should define a getInterface() method returning the interface
of the component.
"""
- # NamedConfiguration.__implements__ includes IDeleteNotifiable
- __implements__ = (INamedComponentConfiguration,
- NamedConfiguration.__implements__, IAddNotifiable)
+ # SimpleConfiguration.__implements__ includes IDeleteNotifiable
+ __implements__ = (IComponentConfiguration,
+ SimpleConfiguration.__implements__,
+ IAddNotifiable)
- def __init__(self, name, component_path, permission=None):
+ def __init__(self, component_path, permission=None):
self.componentPath = component_path
if permission == 'zope.Public':
permission = CheckerPublic
self.permission = permission
- super(NamedComponentConfiguration, self).__init__(name)
def implementationSummary(self):
return canonicalPath(self.componentPath)
@@ -375,14 +377,29 @@
def beforeDeleteHook(self, configuration, container):
"See IDeleteNotifiable"
- super(NamedComponentConfiguration, self
- ).beforeDeleteHook(configuration, container)
+ super(ComponentConfiguration, self).beforeDeleteHook(configuration,
+ container)
component = configuration.getComponent()
dependents = getAdapter(component, IDependable)
objectpath = getPath(configuration)
dependents.removeDependent(objectpath)
+class NamedComponentConfiguration(NamedConfiguration, ComponentConfiguration):
+ """Configurations for named components.
+
+ This configures components that live in folders, by name.
+ """
+
+ __implements__ = (INamedComponentConfiguration,
+ NamedConfiguration.__implements__,
+ ComponentConfiguration.__implements__)
+
+ def __init__(self, name, component_path, permission=None):
+ NamedConfiguration.__init__(self, name)
+ ComponentConfiguration.__init__(self, component_path, permission)
+
+
class NameConfigurable:
"""Mixin for implementing INameConfigurable
"""
@@ -466,3 +483,133 @@
def usages(self):
annotations = getAdapter(self.context, IAnnotations)
return annotations.get(USE_CONFIG_KEY, ())
+
+class ConfigurationManager(Persistent):
+ """Configuration manager
+
+ Manages configurations within a package.
+ """
+
+ __implements__ = IConfigurationManager, IDeleteNotifiable
+
+ def __init__(self):
+ self._data = ()
+ self._next = 0
+
+ def __getitem__(self, key):
+ "See IItemContainer"
+ v = self.get(key)
+ if v is None:
+ raise KeyError, key
+ return v
+
+ def get(self, key, default=None):
+ "See Interface.Common.Mapping.IReadMapping"
+ for k, v in self._data:
+ if k == key:
+ return v
+ return default
+
+ def __contains__(self, key):
+ "See Interface.Common.Mapping.IReadMapping"
+ return self.get(key) is not None
+
+
+ def keys(self):
+ "See Interface.Common.Mapping.IEnumerableMapping"
+ return [k for k, v in self._data]
+
+ def __iter__(self):
+ return iter(self.keys())
+
+ def values(self):
+ "See Interface.Common.Mapping.IEnumerableMapping"
+ return [v for k, v in self._data]
+
+ def items(self):
+ "See Interface.Common.Mapping.IEnumerableMapping"
+ return self._data
+
+ def __len__(self):
+ "See Interface.Common.Mapping.IEnumerableMapping"
+ return len(self._data)
+
+ def setObject(self, key, object):
+ "See IWriteContainer"
+ self._next += 1
+ key = str(self._next)
+ self._data += ((key, object), )
+ return key
+
+ def __delitem__(self, key):
+ "See IWriteContainer"
+ if key not in self:
+ raise KeyError, key
+ self._data = tuple(
+ [item
+ for item in self._data
+ if item[0] != key]
+ )
+
+ def moveTop(self, names):
+ self._data = tuple(
+ [item for item in self._data if (item[0] in names)]
+ +
+ [item for item in self._data if (item[0] not in names)]
+ )
+
+ def moveBottom(self, names):
+ self._data = tuple(
+ [item for item in self._data if (item[0] not in names)]
+ +
+ [item for item in self._data if (item[0] in names)]
+ )
+
+ def _moveUpOrDown(self, names, direction):
+ # Move each named item by one position. Note that this
+ # might require moving some unnamed objects by more than
+ # one position.
+
+ indexes = {}
+
+ # Copy named items to positions one less than they currently have
+ i = -1
+ for item in self._data:
+ i += 1
+ if item[0] in names:
+ j = max(i + direction, 0)
+ while j in indexes:
+ j += 1
+
+ indexes[j] = item
+
+ # Fill in the rest where there's room.
+ i = 0
+ for item in self._data:
+ if item[0] not in names:
+ while i in indexes:
+ i += 1
+ indexes[i] = item
+
+ items = indexes.items()
+ items.sort()
+
+ self._data = tuple([item[1] for item in items])
+
+ def moveUp(self, names):
+ self._moveUpOrDown(names, -1)
+
+ def moveDown(self, names):
+ self._moveUpOrDown(names, 1)
+
+ def beforeDeleteHook(self, object, container):
+ assert object == self
+ container = getAdapter(object, IZopeWriteContainer)
+ for k, v in self._data:
+ del container[k]
+
+
+# XXX Backward Compatibility for pickles
+import sys
+sys.modules['zope.app.services.configurationmanager'
+ ] = sys.modules['zope.app.services.configuration']