Rev 751 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed
| Rev 751 | Rev 752 | ||
|---|---|---|---|
| 1 | ########################################################### |
1 | ########################################################### |
| 2 | # |
2 | # |
| 3 | # Daemon configuration |
3 | # Daemon configuration |
| 4 | # |
4 | # |
| 5 | ########################################################### |
5 | ########################################################### |
| 6 | import logging as log |
6 | import logging as log |
| 7 | import pickle |
7 | import pickle |
| 8 | import hashlib |
8 | import hashlib |
| 9 | import os |
9 | import os |
| 10 | import imp |
10 | import imp |
| 11 | import re |
11 | import re |
| 12 | from ConfigParser import ConfigParser |
12 | from ConfigParser import ConfigParser |
| 13 | import filters |
13 | import filters |
| 14 | import statespaces |
14 | import statespaces |
| 15 | from CanPktHandlerBase import CanPktHandlerBase |
15 | from CanPktHandlerBase import CanPktHandlerBase |
| 16 | from CanPktHandler1 import CanPktHandler1 |
16 | from CanPktHandler1 import CanPktHandler1 |
| 17 | 17 | ||
| 18 | from NodeIfSerial import NodeIfSerial |
18 | from NodeIfSerial import NodeIfSerial |
| 19 | from NodeIfTCP import NodeIfTCP |
19 | from NodeIfTCP import NodeIfTCP |
| 20 | from NodeIfUDP import NodeIfUDP |
20 | from NodeIfUDP import NodeIfUDP |
| 21 | from NodeIfTCPTLS import NodeIfTCPTLS |
21 | from NodeIfTCPTLS import NodeIfTCPTLS |
| 22 | from NodeIfCanStim import NodeIfCanStim |
22 | from NodeIfCanStim import NodeIfCanStim |
| 23 | 23 | ||
| 24 | from TCPServer1 import TCPServer1 |
24 | from TCPServer1 import TCPServer1 |
| 25 | from TCPTLSServer import TCPTLSServer |
25 | from TCPTLSServer import TCPTLSServer |
| 26 | from CanCtldServer import CanCtldServer |
26 | from CanCtldServer import CanCtldServer |
| 27 | 27 | ||
| 28 | class DynamicModuleCfg: |
28 | class DynamicModuleCfg: |
| 29 | """Dynamic module manager""" |
29 | """Dynamic module manager""" |
| 30 | 30 | ||
| 31 | modSubDir = None |
31 | modSubDir = None |
| 32 | CHECKSUM_FILE = 'checksums' |
32 | CHECKSUM_FILE = 'checksums' |
| 33 | CHECKSUM_SECTION = 'SHA-1_CHECKSUMS' |
33 | CHECKSUM_SECTION = 'SHA-1_CHECKSUMS' |
| 34 | 34 | ||
| 35 | def __init__(self, modSubDir): |
35 | def __init__(self, modSubDir): |
| 36 | self.modSubDir = modSubDir |
36 | self.modSubDir = modSubDir |
| 37 | self.checkSumFile = modSubDir + '/' + self.CHECKSUM_FILE |
37 | self.checkSumFile = modSubDir + '/' + self.CHECKSUM_FILE |
| 38 | if not os.path.exists(self.checkSumFile): |
38 | if not os.path.exists(self.checkSumFile): |
| 39 | self.__createCsumsFile() |
39 | self.__createCsumsFile() |
| 40 | 40 | ||
| 41 | def loadModule(self, className): |
41 | def loadModule(self, className): |
| 42 | pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p' |
42 | pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p' |
| 43 | log.debug('Reading from ' + pFileName) |
43 | log.debug('Reading from ' + pFileName) |
| 44 | fp = open(pFileName, 'r') |
44 | fp = open(pFileName, 'r') |
| 45 | p = pickle.Unpickler(fp) |
45 | p = pickle.Unpickler(fp) |
| 46 | loadedMod = p.load() |
46 | loadedMod = p.load() |
| 47 | fp.close() |
47 | fp.close() |
| 48 | if not self.__verifyCheckSum(className, pFileName): |
48 | if not self.__verifyCheckSum(className, pFileName): |
| 49 | print 'Invalid checksum' |
49 | print 'Invalid checksum' |
| 50 | return None |
50 | return None |
| 51 | else: |
51 | else: |
| 52 | return loadedMod |
52 | return loadedMod |
| 53 | 53 | ||
| 54 | 54 | ||
| 55 | def loadModules(self, config = None): |
55 | def loadModules(self, config = None): |
| 56 | subDirFiles = os.listdir(os.getcwd() + '/' + self.modSubDir) |
56 | subDirFiles = os.listdir(os.getcwd() + '/' + self.modSubDir) |
| 57 | p = re.compile('.p$', re.IGNORECASE) |
57 | p = re.compile('.p$', re.IGNORECASE) |
| 58 | modFiles = [elem for elem in subDirFiles if p.search(elem) is not None] |
58 | modFiles = [elem for elem in subDirFiles if p.search(elem) is not None] |
| 59 | modNames = [] |
59 | modNames = [] |
| 60 | for mfName in modFiles: |
60 | for mfName in modFiles: |
| 61 | modNames.append(mfName.split('.')[0]) |
61 | modNames.append(mfName.split('.')[0]) |
| 62 | log.debug('Found modules: ' + str(modNames)) |
62 | log.debug('Found modules: ' + str(modNames)) |
| 63 | myMods = {} |
63 | myMods = {} |
| 64 | for mName in modNames: |
64 | for mName in modNames: |
| 65 | classObj = self.loadModule(mName) |
65 | classObj = self.loadModule(mName) |
| 66 | if classObj is not None: |
66 | if classObj is not None: |
| 67 | myMods[mName] = classObj |
67 | myMods[mName] = classObj |
| 68 | return myMods |
68 | return myMods |
| 69 | 69 | ||
| 70 | 70 | ||
| 71 | def saveModule(self, className, classObj): |
71 | def saveModule(self, className, classObj): |
| 72 | pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p' |
72 | pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p' |
| 73 | log.debug('Writing to ' + pFileName) |
73 | log.debug('Writing to ' + pFileName) |
| 74 | fp = open(pFileName, 'w') |
74 | fp = open(pFileName, 'w') |
| 75 | p = pickle.Pickler(fp) |
75 | p = pickle.Pickler(fp) |
| 76 | p.dump(classObj) |
76 | p.dump(classObj) |
| 77 | fp.close() |
77 | fp.close() |
| 78 | self.__writeCheckSum(className, pFileName) |
78 | self.__writeCheckSum(className, pFileName) |
| 79 | 79 | ||
| 80 | 80 | ||
| 81 | def __doCheckSum(self, filename): |
81 | def __doCheckSum(self, filename): |
| 82 | f = open(filename, 'r') |
82 | f = open(filename, 'r') |
| 83 | data = f.read() |
83 | data = f.read() |
| 84 | f.close() |
84 | f.close() |
| 85 | hasher = hashlib.sha1() |
85 | hasher = hashlib.sha1() |
| 86 | hasher.update(data) |
86 | hasher.update(data) |
| 87 | digest = hasher.hexdigest() |
87 | digest = hasher.hexdigest() |
| 88 | return digest |
88 | return digest |
| 89 | 89 | ||
| 90 | 90 | ||
| 91 | def __createCsumsFile(self): |
91 | def __createCsumsFile(self): |
| 92 | csumsfile = open(self.checkSumFile, 'w') |
92 | csumsfile = open(self.checkSumFile, 'w') |
| 93 | csumsfile.write('[' + self.CHECKSUM_SECTION + ']\n') |
93 | csumsfile.write('[' + self.CHECKSUM_SECTION + ']\n') |
| 94 | csumsfile.close() |
94 | csumsfile.close() |
| 95 | 95 | ||
| 96 | 96 | ||
| 97 | def __writeCheckSum(self, entryname, filename): |
97 | def __writeCheckSum(self, entryname, filename): |
| 98 | csumsfile = open(self.checkSumFile, 'r+') |
98 | csumsfile = open(self.checkSumFile, 'r+') |
| 99 | csumcfg = ConfigParser() |
99 | csumcfg = ConfigParser() |
| 100 | csumcfg.readfp(csumsfile) |
100 | csumcfg.readfp(csumsfile) |
| 101 | digest = self.__doCheckSum(filename) |
101 | digest = self.__doCheckSum(filename) |
| 102 | csumcfg.set(self.CHECKSUM_SECTION, entryname, digest) |
102 | csumcfg.set(self.CHECKSUM_SECTION, entryname, digest) |
| 103 | csumsfile.seek(0) |
103 | csumsfile.seek(0) |
| 104 | csumcfg.write(csumsfile) |
104 | csumcfg.write(csumsfile) |
| 105 | 105 | ||
| 106 | 106 | ||
| 107 | def __verifyCheckSum(self, entryname, filename): |
107 | def __verifyCheckSum(self, entryname, filename): |
| 108 | csumsfile = open(self.checkSumFile, 'r') |
108 | csumsfile = open(self.checkSumFile, 'r') |
| 109 | csumcfg = ConfigParser() |
109 | csumcfg = ConfigParser() |
| 110 | csumcfg.readfp(csumsfile) |
110 | csumcfg.readfp(csumsfile) |
| 111 | digest = csumcfg.get(self.CHECKSUM_SECTION, entryname) |
111 | digest = csumcfg.get(self.CHECKSUM_SECTION, entryname) |
| 112 | cur_digest = self.__doCheckSum(filename) |
112 | cur_digest = self.__doCheckSum(filename) |
| 113 | log.debug('Old checksum ' + digest + '\nNew checksum: ' + cur_digest) |
113 | log.debug('Old checksum ' + digest + '\nNew checksum: ' + cur_digest) |
| 114 | if cur_digest == digest: |
114 | if cur_digest == digest: |
| 115 | return True |
115 | return True |
| 116 | return False |
116 | return False |
| 117 | 117 | ||
| 118 | 118 | ||
| 119 | def importModule(self, className, requiredAttributes): |
119 | def importModule(self, className, requiredAttributes): |
| 120 | """Imports a given class from the module with the same name """ |
120 | """Imports a given class from the module with the same name """ |
| 121 | 121 | ||
| 122 | codeFile = os.getcwd() + '/' + self.modSubDir + '/' + className + '.py' |
122 | codeFile = os.getcwd() + '/' + self.modSubDir + '/' + className + '.py' |
| 123 | mod = imp.load_source(self.modSubDir + '.' + className, codeFile) |
123 | mod = imp.load_source(self.modSubDir + '.' + className, codeFile) |
| 124 | newClass = eval('mod.' + className)() |
124 | newClass = eval('mod.' + className)() |
| 125 | 125 | ||
| 126 | for ra in requiredAttributes: |
126 | for ra in requiredAttributes: |
| 127 | if not hasattr(newClass, ra): |
127 | if not hasattr(newClass, ra): |
| 128 | print className, ': missing required symbol \"' + ra + '\"' |
128 | print className, ': missing required symbol \"' + ra + '\"' |
| 129 | return None |
129 | return None |
| 130 | 130 | ||
| 131 | self.saveModule(className, newClass) |
131 | self.saveModule(className, newClass) |
| 132 | return newClass |
132 | return newClass |
| 133 | 133 | ||
| 134 | 134 | ||
| 135 | class FilterCfg: |
135 | class FilterCfg: |
| 136 | """Filter resource manager""" |
136 | """Filter resource manager""" |
| 137 | 137 | ||
| 138 | REQUIRED_ATTRIBUTES = ['ASSOCIATED_SPACES', 'DESCRIPTIVE_NAME', |
138 | REQUIRED_ATTRIBUTES = ['ASSOCIATED_SPACES', 'DESCRIPTIVE_NAME', |
| 139 | 'attach', 'detach', 'filter'] |
139 | 'attach', 'detach', 'filter'] |
| 140 | 140 | ||
| 141 | dynamicModuleCfg = None |
141 | dynamicModuleCfg = None |
| 142 | FILTER_SUBDIR = 'filters' |
142 | FILTER_SUBDIR = 'filters' |
| 143 | filterModules = {} |
143 | filterModules = {} |
| 144 | 144 | ||
| 145 | def __init__(self): |
145 | def __init__(self): |
| 146 | self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR) |
146 | self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR) |
| 147 | 147 | ||
| 148 | def loadFilter(self, name): |
148 | def loadFilter(self, name): |
| 149 | newFilt = self.dynamicModuleCfg.loadModule(name) |
149 | newFilt = self.dynamicModuleCfg.loadModule(name) |
| 150 | if newFilt is not None: |
150 | if newFilt is not None: |
| 151 | self.filterModules[name] = newFilt |
151 | self.filterModules[name] = newFilt |
| 152 | return True |
152 | return True |
| 153 | else: |
153 | else: |
| 154 | return False |
154 | return False |
| 155 | 155 | ||
| 156 | def loadFilters(self, config = None): |
156 | def loadFilters(self, config = None): |
| 157 | self.filterModules = self.dynamicModuleCfg.loadModules() |
157 | self.filterModules = self.dynamicModuleCfg.loadModules() |
| 158 | for fM in self.filterModules: |
158 | for fM in self.filterModules: |
| 159 | log.debug(fM) |
159 | log.debug(fM) |
| 160 | 160 | ||
| 161 | def __saveFilter(self, className, classObj): |
161 | def __saveFilter(self, className, classObj): |
| 162 | self.dynamicModuleCfg.saveModule(className, classObj) |
162 | self.dynamicModuleCfg.saveModule(className, classObj) |
| 163 | 163 | ||
| 164 | def saveFilters(self): |
164 | def saveFilters(self): |
| 165 | for className in self.filterModules: |
165 | for className in self.filterModules: |
| 166 | self.__saveFilter(className, self.filterModules[className]) |
166 | self.__saveFilter(className, self.filterModules[className]) |
| 167 | 167 | ||
| 168 | def importFilter(self, className): |
168 | def importFilter(self, className): |
| 169 | """Imports a given filter definition """ |
169 | """Imports a given filter definition """ |
| 170 | classObj = self.dynamicModuleCfg.importModule(className, self.REQUIRED_ATTRIBUTES) |
170 | classObj = self.dynamicModuleCfg.importModule(className, self.REQUIRED_ATTRIBUTES) |
| 171 | if classObj is not None: |
171 | if classObj is not None: |
| 172 | print 'Imported: ' + classObj.DESCRIPTIVE_NAME |
172 | print 'Imported: ' + classObj.DESCRIPTIVE_NAME |
| 173 | return True |
173 | return True |
| 174 | else: |
174 | else: |
| 175 | return False |
175 | return False |
| 176 | 176 | ||
| 177 | 177 | ||
| 178 | class StateSpaceCfg: |
178 | class StateSpaceCfg: |
| 179 | """State space resource manager""" |
179 | """State space resource manager""" |
| 180 | 180 | ||
| 181 | REQUIRED_ATTRIBUTES = ['DESCRIPTIVE_NAME', 'RELATED_SPACES' |
181 | REQUIRED_ATTRIBUTES = ['DESCRIPTIVE_NAME', 'RELATED_SPACES' |
| 182 | 'load', 'reset', 'run', 'unload'] |
182 | 'load', 'reset', 'run', 'unload'] |
| 183 | 183 | ||
| 184 | dynamicModuleCfg = None |
184 | dynamicModuleCfg = None |
| 185 | FILTER_SUBDIR = 'statespaces' |
185 | FILTER_SUBDIR = 'statespaces' |
| 186 | spaceModules = {} |
186 | spaceModules = {} |
| 187 | 187 | ||
| 188 | def __init__(self): |
188 | def __init__(self): |
| 189 | self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR) |
189 | self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR) |
| 190 | 190 | ||
| 191 | def loadSpace(self, name): |
191 | def loadSpace(self, name): |
| 192 | newSpace = self.dynamicModuleCfg.loadModule(name) |
192 | newSpace = self.dynamicModuleCfg.loadModule(name) |
| 193 | if newSpace is not None: |
193 | if newSpace is not None: |
| 194 | self.spaceModules[name] = newFilt |
194 | self.spaceModules[name] = newFilt |
| 195 | return True |
195 | return True |
| 196 | else: |
196 | else: |
| 197 | return False |
197 | return False |
| 198 | 198 | ||
| 199 | def loadSpaces(self, config = None): |
199 | def loadSpaces(self, config = None): |
| 200 | self.spaceModules = self.dynamicModuleCfg.loadModules() |
200 | self.spaceModules = self.dynamicModuleCfg.loadModules() |
| 201 | for sM in self.spaceModules: |
201 | for sM in self.spaceModules: |
| 202 | log.debug(sM) |
202 | log.debug(sM) |
| 203 | 203 | ||
| 204 | def __saveSpace(self, className, classObj): |
204 | def __saveSpace(self, className, classObj): |
| 205 | self.dynamicModuleCfg.saveModule(className, classObj) |
205 | self.dynamicModuleCfg.saveModule(className, classObj) |
| 206 | 206 | ||
| 207 | def saveSpaces(self): |
207 | def saveSpaces(self): |
| 208 | for className in self.spaceModules: |
208 | for className in self.spaceModules: |
| 209 | self.__saveSpace(className, self.spaceModules[className]) |
209 | self.__saveSpace(className, self.spaceModules[className]) |
| 210 | 210 | ||
| 211 | def importSpace(self, name): |
211 | def importSpace(self, name): |
| 212 | """Imports a given state space definition file """ |
212 | """Imports a given state space definition file """ |
| 213 | classObj = self.dynamicModuleCfg.importModule(name, self.REQUIRED_ATTRIBUTES) |
213 | classObj = self.dynamicModuleCfg.importModule(name, self.REQUIRED_ATTRIBUTES) |
| 214 | if classObj is not None: |
214 | if classObj is not None: |
| 215 | print 'Imported: ' + classObj.DESCRIPTIVE_NAME |
215 | print 'Imported: ' + classObj.DESCRIPTIVE_NAME |
| 216 | return True |
216 | return True |
| 217 | else: |
217 | else: |
| 218 | return False |
218 | return False |
| 219 | 219 | ||
| 220 | class DaemonConfig: |
220 | class DaemonConfig: |
| 221 | 221 | ||
| 222 | stateSpaceCfg = None |
222 | stateSpaceCfg = None |
| 223 | filterCfg = None |
223 | filterCfg = None |
| 224 | pktHandler = None |
224 | pktHandler = None |
| 225 | 225 | ||
| 226 | filterChain = [] |
226 | filterChain = [] |
| 227 | nodeInterfaces = [] |
227 | nodeInterfaces = [] |
| 228 | nodeInterfaceMap = {} |
228 | nodeInterfaceMap = {} |
| 229 | 229 | ||
| 230 | serverDaemons = [] |
230 | serverDaemons = [] |
| 231 | 231 | ||
| 232 | INTERFACE_TYPES = {'serial' : NodeIfSerial, 'tcp' : NodeIfTCP, |
232 | INTERFACE_TYPES = {'serial' : NodeIfSerial, 'tcp' : NodeIfTCP, |
| 233 | 'udp' : NodeIfUDP, 'sim' : NodeIfCanStim, |
233 | 'udp' : NodeIfUDP, 'sim' : NodeIfCanStim, |
| 234 | 'tcptls' : NodeIfTCPTLS} |
234 | 'tcptls' : NodeIfTCPTLS} |
| 235 | 235 | ||
| 236 | SERVER_TYPES = {'tcpd' : TCPServer1, 'tcptlsd' : TCPTLSServer, |
236 | SERVER_TYPES = {'tcpd' : TCPServer1, 'tcptlsd' : TCPTLSServer, |
| 237 | 'canctld' : CanCtldServer} |
237 | 'canctld' : CanCtldServer} |
| 238 | 238 | ||
| 239 | def __init__ (self): |
239 | def __init__ (self): |
| 240 | self.filterCfg = FilterCfg() |
240 | self.filterCfg = FilterCfg() |
| 241 | self.stateSpaceCfg = StateSpaceCfg() |
241 | self.stateSpaceCfg = StateSpaceCfg() |
| 242 | self.pktHandler = CanPktHandler1(self) |
242 | self.pktHandler = CanPktHandler1(self) |
| 243 | 243 | ||
| 244 | def load(self): |
244 | def load(self): |
| 245 | self.stateSpaceCfg.loadSpaces() |
245 | self.stateSpaceCfg.loadSpaces() |
| 246 | self.filterCfg.loadFilters() |
246 | self.filterCfg.loadFilters() |
| 247 | self.__setupFilterBindings() |
247 | self.__setupFilterBindings() |
| 248 | self.__setupStateSpaceRelations() |
248 | self.__setupStateSpaceRelations() |
| 249 | self.__setupFilterChain() |
249 | self.__setupFilterChain() |
| 250 | 250 | ||
| 251 | def save(self): |
251 | def save(self): |
| 252 | self.stateSpaceCfg.saveSpaces() |
252 | self.stateSpaceCfg.saveSpaces() |
| 253 | self.filterCfg.saveFilters() |
253 | self.filterCfg.saveFilters() |
| 254 | 254 | ||
| 255 | def addInterface(self, type, cfg = None): |
255 | def addInterface(self, type, cfg = None): |
| 256 | """ addInterface |
256 | """ addInterface |
| 257 | type - a valid interface type name |
257 | type - a valid interface type name |
| 258 | cfg - interface configuration |
258 | cfg - interface configuration |
| 259 | returns: True on success, False otherwise """ |
259 | returns: True on success, False otherwise """ |
| 260 | 260 | ||
| 261 | if not self.INTERFACE_TYPES.has_key(type): |
261 | if not self.INTERFACE_TYPES.has_key(type): |
| 262 | log.debug('addInterface called with invalid interface type') |
262 | log.debug('addInterface called with invalid interface type') |
| 263 | return False |
263 | return False |
| 264 | 264 | ||
| - | 265 | if cfg is None: |
|
| 265 | cfg = self.INTERFACE_TYPES[type].DEFAULT_CONFIG |
266 | cfg = self.INTERFACE_TYPES[type].DEFAULT_CONFIG |
| - | 267 | ||
| 266 | nodeIf = self.INTERFACE_TYPES[type](self.pktHandler, cfg) |
268 | nodeIf = self.INTERFACE_TYPES[type](self.pktHandler, cfg) |
| 267 | self.nodeInterfaces.append(nodeIf) |
269 | self.nodeInterfaces.append(nodeIf) |
| 268 | return True |
270 | return True |
| 269 | 271 | ||
| 270 | def remInterface(self, name): |
272 | def remInterface(self, name): |
| 271 | pass |
273 | pass |
| 272 | 274 | ||
| 273 | def addServerDaemon(self, type, cfg = None): |
275 | def addServerDaemon(self, type, cfg = None): |
| 274 | 276 | ||
| 275 | if not self.SERVER_TYPES.has_key(type): |
277 | if not self.SERVER_TYPES.has_key(type): |
| 276 | log.debug('addServerDaemon called with invalid daemon type') |
278 | log.debug('addServerDaemon called with invalid daemon type') |
| 277 | return False |
279 | return False |
| 278 | 280 | ||
| - | 281 | if cfg is None: |
|
| - | 282 | cfg = self.SERVER_TYPES[type].DEFAULT_CONFIG |
|
| - | 283 | ||
| 279 | serverd = self.SERVER_TYPES[type]() # actung! |
284 | serverd = self.SERVER_TYPES[type](self.pktHandler, cfg) # actung! |
| - | 285 | self.serverDaemons.append(serverd) |
|
| 280 | return True |
286 | return True |
| 281 | 287 | ||
| 282 | def remServerDaemon(self, name): |
288 | def remServerDaemon(self, name): |
| 283 | pass |
289 | pass |
| 284 | 290 | ||
| 285 | def __setupFilterChain(self): |
291 | def __setupFilterChain(self): |
| 286 | self.filterChain = ['DefaultFilter'] |
292 | self.filterChain = ['DefaultFilter'] |
| 287 | 293 | ||
| 288 | def __setupFilterBindings(self): |
294 | def __setupFilterBindings(self): |
| 289 | for f in self.filterCfg.filterModules.values(): |
295 | for f in self.filterCfg.filterModules.values(): |
| 290 | assocSpaces = [] |
296 | assocSpaces = [] |
| 291 | for s in f.ASSOCIATED_SPACES: |
297 | for s in f.ASSOCIATED_SPACES: |
| 292 | if self.stateSpaceCfg.spaceModules.has_key(s): |
298 | if self.stateSpaceCfg.spaceModules.has_key(s): |
| 293 | assocSpaces.append(self.stateSpaceCfg.spaceModules[s]) |
299 | assocSpaces.append(self.stateSpaceCfg.spaceModules[s]) |
| 294 | else: |
300 | else: |
| 295 | print 'WARNING: Reference to undefined state space: ' + s |
301 | print 'WARNING: Reference to undefined state space: ' + s |
| 296 | setattr(f, '__ASSOCIATED_SPACES__', assocSpaces) |
302 | setattr(f, '__ASSOCIATED_SPACES__', assocSpaces) |
| 297 | 303 | ||
| 298 | def __setupStateSpaceRelations(self): |
304 | def __setupStateSpaceRelations(self): |
| 299 | for sm in self.stateSpaceCfg.spaceModules: |
305 | for sm in self.stateSpaceCfg.spaceModules: |
| 300 | relatedSpaceNames = self.stateSpaceCfg.spaceModules[sm].RELATED_SPACES |
306 | relatedSpaceNames = self.stateSpaceCfg.spaceModules[sm].RELATED_SPACES |
| 301 | relatedSpaces = {} |
307 | relatedSpaces = {} |
| 302 | for rsname in relatedSpaceNames: |
308 | for rsname in relatedSpaceNames: |
| 303 | relatedSpaces[rsname] = self.stateSpaceCfg.spaceModules[rsname] |
309 | relatedSpaces[rsname] = self.stateSpaceCfg.spaceModules[rsname] |
| 304 | setattr(self.stateSpaceCfg.spaceModules[sm], '__RELATED_SPACES__', relatedSpaces) |
310 | setattr(self.stateSpaceCfg.spaceModules[sm], '__RELATED_SPACES__', relatedSpaces) |
| 305 | 311 | ||
| 306 | 312 | ||