~certify-web-dev/twisted/certify-trunk

« back to all changes in this revision

Viewing changes to twisted/manhole/coil.py

  • Committer: Bazaar Package Importer
  • Author(s): Moshe Zadka
  • Date: 2002-03-08 07:14:16 UTC
  • Revision ID: james.westby@ubuntu.com-20020308071416-oxvuw76tpcpi5v1q
Tags: upstream-0.15.5
ImportĀ upstreamĀ versionĀ 0.15.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Twisted, the Framework of Your Internet
 
2
# Copyright (C) 2001 Matthew W. Lefkowitz
 
3
#
 
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.
 
7
#
 
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.
 
12
#
 
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
 
16
 
 
17
 
 
18
## THIS CODE IS NOT FINISHED YET. ##
 
19
 
 
20
# System Imports
 
21
import types
 
22
import string
 
23
import sys
 
24
import new
 
25
import os
 
26
 
 
27
# Twisted Imports
 
28
from twisted.python.util import uniquify, getPluginDirs
 
29
 
 
30
"""Twisted COIL: COnfiguration ILlumination.
 
31
 
 
32
An end-user direct-manipulation interface to Twisted, accessible through the
 
33
web.
 
34
"""
 
35
 
 
36
def getAllBases(inClass):
 
37
    """Get all super-classes of a given class.
 
38
 
 
39
    Recursively determine the entire hierarchy above a certain class, and
 
40
    return it as a list.
 
41
    """
 
42
    classes = list(inClass.__bases__)
 
43
    for base in inClass.__bases__:
 
44
        classes.extend(getAllBases(base))
 
45
    return uniquify(classes)
 
46
 
 
47
def getClass(name):
 
48
    """Turn a fully-qualified class name into a class.
 
49
 
 
50
    This assumes that the class has already been imported and will raise an
 
51
    undefined exception if it has not.
 
52
    """
 
53
    name = string.split(name, '.')
 
54
    obj = sys.modules[name[0]]
 
55
    for n in name[1:]:
 
56
        obj = getattr(obj, n)
 
57
    return obj
 
58
 
 
59
class ClassHierarchy:
 
60
    """A class which represents a hierarchy of classes.
 
61
 
 
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.
 
65
    """
 
66
    def __init__(self):
 
67
        self.classes = {}
 
68
 
 
69
    def getSubClasses(self, classOrString, asClasses=0):
 
70
        """Get a tuple of all registered subclasses of a given class.
 
71
 
 
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
 
75
        return strings.
 
76
        """
 
77
        if isinstance(classOrString, types.ClassType):
 
78
            className = str(classOrString)
 
79
        else:
 
80
            className = classOrString
 
81
        if not self.classes.has_key(className):
 
82
            print 'no class %s registered' % className
 
83
            return []
 
84
        superClasses, subClasses = self.classes[className]
 
85
        if asClasses:
 
86
            return tuple(map(getClass, subClasses))
 
87
        else:
 
88
            return tuple(subClasses)
 
89
 
 
90
    def getSuperClasses(self, classOrString, asClasses=0):
 
91
        """Get a tuple of all registered superclasses of a given class.
 
92
 
 
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
 
96
        return strings.
 
97
        """
 
98
        if isinstance(classOrString, types.ClassType):
 
99
            className = str(classOrString)
 
100
        else:
 
101
            className = classOrString
 
102
        superClasses, subClasses = self.classes[className]
 
103
        if asClasses:
 
104
            return tuple(map(getClass, superClasses))
 
105
        else:
 
106
            return tuple(superClasses)
 
107
 
 
108
    def registerClass(self, inClass):
 
109
        """Register a class.
 
110
        """
 
111
        className = str(inClass)
 
112
        if self.classes.has_key(className):
 
113
            superClasses, subClasses = self.classes[className]
 
114
        else:
 
115
            superClasses, subClasses = [], []
 
116
            self.classes[className] = superClasses, subClasses
 
117
        for base in getAllBases(inClass):
 
118
            baseName = str(base)
 
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)
 
124
 
 
125
theClassHierarchy = ClassHierarchy()
 
126
registerClass = theClassHierarchy.registerClass
 
127
 
 
128
 
 
129
class InvalidConfiguration(Exception):
 
130
    """I am is raised in the case of an invalid configuration.
 
131
    """
 
132
 
 
133
def createConfigurable(configClass, container, name):
 
134
    """Instantiate a configurable.
 
135
 
 
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.
 
140
    """
 
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)
 
146
    return instance
 
147
 
 
148
class Configurable:
 
149
    """A configurable object.
 
150
 
 
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.)
 
156
 
 
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), ...].
 
160
 
 
161
    Custom handling of configuration-item-setting can be had by adding
 
162
    configure_%s(self, value) methods to my subclass.
 
163
    """
 
164
 
 
165
    # Change this attribute in subclasses.
 
166
    configTypes = {}
 
167
 
 
168
    configName = None
 
169
 
 
170
    configDispensers = []
 
171
 
 
172
    configCreatable = 1
 
173
 
 
174
    def __init__(self):
 
175
        """Initialize me.
 
176
 
 
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.
 
180
        """
 
181
        self.configuration = {}
 
182
 
 
183
    def configInit(self, container, name):
 
184
        """Initialize me to a base state from which it may be configured.
 
185
 
 
186
        By default, I will run self.__init__ with no arguments.
 
187
        """
 
188
        self.__init__()
 
189
 
 
190
    def configure(self, dict):
 
191
        """Set a list of configuration variables.
 
192
        """
 
193
        items = dict.items()
 
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")
 
200
            elif t == 'boolean':
 
201
                try:
 
202
                    if value: pass
 
203
                except:
 
204
                    raise InvalidConfiguration("non-boolean for boolean type")
 
205
            else:
 
206
                raise InvalidConfiguration("Configuration item '%s' has "
 
207
                                           "unknown type '%s'" % (name, t))
 
208
 
 
209
        for name, value in items:
 
210
            func = getattr(self, "config_%s" % name, None)
 
211
            if func:
 
212
                func(value)
 
213
            else:
 
214
                self.configuration[name] = value
 
215
 
 
216
    def getConfiguration(self):
 
217
        """Return a mapping of key/value tuples describing my configuration.
 
218
        """
 
219
        return self.configuration
 
220