1
# Twisted, the Framework of Your Internet
2
# Copyright (C) 2001 Matthew W. Lefkowitz
4
# This library is free software; you can redistribute it and/or
5
# modify it under the terms of version 2.1 of the GNU Lesser General Public
6
# License as published by the Free Software Foundation.
8
# This library is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
# Lesser General Public License for more details.
13
# You should have received a copy of the GNU Lesser General Public
14
# License along with this library; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
## THIS CODE IS NOT FINISHED YET. ##
28
from twisted.python.util import uniquify, getPluginDirs
30
"""Twisted COIL: COnfiguration ILlumination.
32
An end-user direct-manipulation interface to Twisted, accessible through the
36
def getAllBases(inClass):
37
"""Get all super-classes of a given class.
39
Recursively determine the entire hierarchy above a certain class, and
42
classes = list(inClass.__bases__)
43
for base in inClass.__bases__:
44
classes.extend(getAllBases(base))
45
return uniquify(classes)
48
"""Turn a fully-qualified class name into a class.
50
This assumes that the class has already been imported and will raise an
51
undefined exception if it has not.
53
name = string.split(name, '.')
54
obj = sys.modules[name[0]]
60
"""A class which represents a hierarchy of classes.
62
It's possible in python to identify all base classes of a particular class
63
fairly easily, but not to identify all of its subclasses. This class
64
allows you to register and then query for sub-classes of a given class.
69
def getSubClasses(self, classOrString, asClasses=0):
70
"""Get a tuple of all registered subclasses of a given class.
72
The class may be specified either by the actual class or a descriptive
73
string. An optional flag, asClasses, specifies whether those classes
74
should be returned as class objects or as strings. By default, I will
77
if isinstance(classOrString, types.ClassType):
78
className = str(classOrString)
80
className = classOrString
81
if not self.classes.has_key(className):
82
print 'no class %s registered' % className
84
superClasses, subClasses = self.classes[className]
86
return tuple(map(getClass, subClasses))
88
return tuple(subClasses)
90
def getSuperClasses(self, classOrString, asClasses=0):
91
"""Get a tuple of all registered superclasses of a given class.
93
The class may be specified either by the actual class or a descriptive
94
string. An optional flag, asClasses, specifies whether those classes
95
should be returned as class objects or as strings. By default, I will
98
if isinstance(classOrString, types.ClassType):
99
className = str(classOrString)
101
className = classOrString
102
superClasses, subClasses = self.classes[className]
104
return tuple(map(getClass, superClasses))
106
return tuple(superClasses)
108
def registerClass(self, inClass):
111
className = str(inClass)
112
if self.classes.has_key(className):
113
superClasses, subClasses = self.classes[className]
115
superClasses, subClasses = [], []
116
self.classes[className] = superClasses, subClasses
117
for base in getAllBases(inClass):
119
if baseName not in superClasses:
120
self.registerClass(base)
121
baseSuper, baseSub = self.classes[str(base)]
122
baseSub.append(className)
123
superClasses.append(baseName)
125
theClassHierarchy = ClassHierarchy()
126
registerClass = theClassHierarchy.registerClass
129
class InvalidConfiguration(Exception):
130
"""I am is raised in the case of an invalid configuration.
133
def createConfigurable(configClass, container, name):
134
"""Instantiate a configurable.
136
First, I will create an instance object of class configClass.
137
Then I will call its configInit, with 'container' and 'name'
138
as arguments. If the class passed in is not a subclass of
139
Configurable, I will fail.
141
if not issubclass(configClass, Configurable):
142
raise TypeError("%s is not a subclass of %s" %
143
(configClass, Configurable))
144
instance = new.instance(configClass, {})
145
instance.configInit(container, name)
149
"""A configurable object.
151
I have a dictionary attribute, configTypes, that indicates what sort of
152
objects I will allow to be configured. It is a mapping of variable names
153
to variable types. Variable types may be either python type objects,
154
classes, or objects describing a desired 'hint' to the interface (such as
155
'boolean' or ['choice', 'a', 'b', 'c']). (XXX Still in flux.)
157
I have a list attribute, configDispensers, that indicates what methods on
158
me may be called with no arguments to create an instance of another
159
Configurable. It is a list of the form [(method name, class, descString), ...].
161
Custom handling of configuration-item-setting can be had by adding
162
configure_%s(self, value) methods to my subclass.
165
# Change this attribute in subclasses.
170
configDispensers = []
177
Note that I need to be initialized even if you're initializing directly
178
from configInit; if you subclass me, be sure to run
179
Configurable.__init__(self) inside configInit if you override it.
181
self.configuration = {}
183
def configInit(self, container, name):
184
"""Initialize me to a base state from which it may be configured.
186
By default, I will run self.__init__ with no arguments.
190
def configure(self, dict):
191
"""Set a list of configuration variables.
194
getType = self.configTypes.get
195
for name, value in items:
196
t = getType(name, None)
197
if isinstance(t, types.TypeType) or isinstance(t, types.ClassType):
198
if not isinstance(value, t) or (value is None):
199
raise InvalidConfiguration("type mismatch")
204
raise InvalidConfiguration("non-boolean for boolean type")
206
raise InvalidConfiguration("Configuration item '%s' has "
207
"unknown type '%s'" % (name, t))
209
for name, value in items:
210
func = getattr(self, "config_%s" % name, None)
214
self.configuration[name] = value
216
def getConfiguration(self):
217
"""Return a mapping of key/value tuples describing my configuration.
219
return self.configuration