16 |
# write to the Free Software Foundation, Inc., 59 Temple Place |
# write to the Free Software Foundation, Inc., 59 Temple Place |
17 |
# - Suite 330, Boston, MA 02111-1307, USA. |
# - Suite 330, Boston, MA 02111-1307, USA. |
18 |
# |
# |
19 |
# Copyright 2000-2002 Free Software Foundation |
# Copyright 2000-2003 Free Software Foundation |
20 |
# |
# |
21 |
# FILE: |
# FILE: |
22 |
# GObjects.py |
# GObjects.py |
32 |
import GDebug |
import GDebug |
33 |
import string |
import string |
34 |
import types |
import types |
35 |
from GParserHelpers import GContent |
from GParserHelpers import GContent, ParserObj |
36 |
import GTypecast |
import GTypecast |
37 |
from GTriggerCore import GTriggerCore |
from GTriggerCore import GTriggerCore |
38 |
|
import types |
39 |
|
|
40 |
# |
# |
41 |
# Class GObj |
# Class GObj |
42 |
# |
# |
43 |
# Base class for GNUe objects which can be represented as XML |
# Base class for GNUe objects which |
44 |
|
# can be represented by XML tags |
45 |
# |
# |
46 |
class GObj(GTriggerCore): |
class GObj(GTriggerCore, ParserObj): |
47 |
def __init__(self, parent=None, type='GObj'): |
def __init__(self, *args, **parms): |
48 |
GTriggerCore.__init__(self) |
GTriggerCore.__init__(self) |
49 |
self._type = type |
ParserObj.__init__(self, *args, **parms) |
|
self._parent = parent # The object that contains this object |
|
|
self._children = [] # The objects contained by this object |
|
|
self._attributes = {} |
|
|
self._inits = [] # functions called during phaseInit stage |
|
|
self._xmlnamespace = None |
|
|
if parent : |
|
|
parent.addChild(self) |
|
|
|
|
50 |
|
|
51 |
|
|
52 |
# This is a convenience function for applications |
# This is a convenience function for applications |
53 |
# NOT using GParser to load an object tree. |
# NOT using GParser to load an object tree. |
54 |
def buildObject(self, **params): |
def buildObject(self, **params): |
68 |
# |
# |
69 |
# phaseInit |
# phaseInit |
70 |
# |
# |
71 |
def phaseInit(self, iterations=5): |
def phaseInit(self, iterations=0): |
72 |
|
if iterations == 0: |
73 |
|
iterations = self.maxInits() |
74 |
for phase in range(iterations): |
for phase in range(iterations): |
75 |
self._phaseInit(phase) |
self._phaseInit(phase) |
76 |
|
|
78 |
|
|
79 |
## TODO: Below is a call-less recursive version of |
## TODO: Below is a call-less recursive version of |
80 |
## TODO: phaseInit. Needs to be profiled both ways. |
## TODO: phaseInit. Needs to be profiled both ways. |
|
## object = self |
|
81 |
## stack = [self] |
## stack = [self] |
82 |
## while stack: |
## while stack: |
83 |
## object = stack.pop() |
## object = stack.pop() |
86 |
## try: |
## try: |
87 |
## init = object._inits[phase] |
## init = object._inits[phase] |
88 |
## except IndexError: |
## except IndexError: |
89 |
## init = None |
## continue |
90 |
## if init: |
## init() |
|
## init() |
|
91 |
|
|
92 |
if (len(self._inits) > phase) and self._inits[phase]: |
inits = self._inits |
93 |
|
if (len(inits) > phase) and inits[phase]: |
94 |
GDebug.printMesg(6,"%s: Init Phase %s" % (self._type, phase+1)) |
GDebug.printMesg(6,"%s: Init Phase %s" % (self._type, phase+1)) |
95 |
self._inits[phase]() |
inits[phase]() |
96 |
|
|
97 |
for child in self._children: |
for child in self._children: |
98 |
if isinstance(child, GObj): |
try: |
99 |
child._phaseInit(phase) |
initter = child._phaseInit |
100 |
|
except AttributeError: |
101 |
|
continue |
102 |
|
initter(phase) |
103 |
|
|
104 |
|
|
105 |
# This function is called after the parsers have completely |
# This function is called after the parsers have completely |
106 |
# constructed. All children should be in place and |
# constructed. All children should be in place and |
107 |
# attributes and content should be set at this point. |
# attributes and content should be set at this point. |
115 |
def _buildObject(self): |
def _buildObject(self): |
116 |
return len(self._inits) |
return len(self._inits) |
117 |
|
|
118 |
|
# |
119 |
|
# maxInits functions |
120 |
|
# |
121 |
|
# maxInits returns the maximum size of all the _inits |
122 |
|
# list from this object or it's children |
123 |
|
# |
124 |
|
def maxInits(self): |
125 |
|
self._initCount = 0 |
126 |
|
self.walk(self._maxInitsWalker) |
127 |
|
return self._initCount |
128 |
|
|
129 |
|
def _maxInitsWalker(self, object): |
130 |
|
if hasattr(object,'_inits'): |
131 |
|
self._initCount = max(self._initCount,len(object._inits)) |
132 |
|
|
133 |
|
|
134 |
def getChildrenAsContent(self): |
def getChildrenAsContent(self): |
135 |
content = "" |
content = "" |
136 |
for child in self._children: |
for child in self._children: |
139 |
return content |
return content |
140 |
|
|
141 |
def showTree(self, indent=0): |
def showTree(self, indent=0): |
142 |
print ' ' * indent + `self._type` |
print ' ' * indent + `self._type`,self |
143 |
|
|
144 |
for child in self._children: |
for child in self._children: |
145 |
child.showTree(indent + 2) |
child.showTree(indent + 2) |
146 |
|
|
152 |
def addChild(self, child): |
def addChild(self, child): |
153 |
self._children.append(child) |
self._children.append(child) |
154 |
|
|
|
def toXML(self): |
|
|
xml_outer = string.lower(self._type[2:]) |
|
|
r = "<" + xml_outer + ">\n <options>\n" |
|
|
for k in self.__dict__.keys(): |
|
|
# skip keys beginning with _ |
|
|
if k[0] == "_": |
|
|
continue |
|
|
val = self.__dict__[k] |
|
|
if isinstance(val, _types.StringType): |
|
|
str = val |
|
|
elif isinstance(val, _types.IntType) or isinstance(val, _types.FloatType): |
|
|
str = repr(val) |
|
|
else: |
|
|
continue |
|
|
r += " <" + k + ">" + str + "</" + k + ">\n" |
|
|
r += " </options>\n</" + xml_outer + ">\n" |
|
|
return r |
|
|
|
|
155 |
# |
# |
156 |
# dumpXML |
# dumpXML |
157 |
# |
# |
180 |
except AttributeError: |
except AttributeError: |
181 |
try: |
try: |
182 |
if self._xmlchildnamespace: |
if self._xmlchildnamespace: |
183 |
if not xmlnamespaces.hasattr(self._xmlchildnamespace): |
if not xmlnamespaces.has_key(self._xmlchildnamespace): |
184 |
i = 0 |
i = 0 |
185 |
ns = "out" |
ns = "out" |
186 |
while ns in xmlnamespaces.values(): |
while ns in xmlnamespaces.values(): |
191 |
except AttributeError: |
except AttributeError: |
192 |
pass |
pass |
193 |
|
|
194 |
|
|
195 |
|
try: |
196 |
|
if self._xmlchildnamespaces: |
197 |
|
for abbrev in self._xmlchildnamespaces: |
198 |
|
xmlnsdef += ' xmlns:%s="%s"' % (abbrev,self._xmlchildnamespaces[abbrev]) |
199 |
|
except AttributeError: |
200 |
|
pass |
201 |
|
|
202 |
xmlEntity = self.getXmlTag() |
xmlEntity = self.getXmlTag() |
203 |
xmlString = "%s<%s%s%s" % (gap[:-2],xmlns, xmlEntity, xmlnsdef) |
xmlString = "%s<%s%s%s" % (gap[:-2],xmlns, xmlEntity, xmlnsdef) |
204 |
|
|
206 |
pos = indent |
pos = indent |
207 |
attrs = self.__dict__.keys() |
attrs = self.__dict__.keys() |
208 |
attrs.sort() |
attrs.sort() |
209 |
|
|
210 |
|
# Make 'name' first |
211 |
|
if 'name' in attrs: |
212 |
|
attrs.pop(attrs.index('name')) |
213 |
|
attrs.insert(0,'name') |
214 |
|
|
215 |
for attribute in attrs: |
for attribute in attrs: |
216 |
# skip keys beginning with _ |
# skip keys beginning with _ |
217 |
if attribute[0] == "_": |
if attribute[0] == "_": |
233 |
else: |
else: |
234 |
addl = ' %s="N"' % (attribute) |
addl = ' %s="N"' % (attribute) |
235 |
elif typecast == GTypecast.names: |
elif typecast == GTypecast.names: |
236 |
addl = ' %s="%s"' % \ |
if type(val) == types.StringType: |
237 |
(attribute, string.join(val,',')) |
addl = ' %s="%s"' % (attribute, string.join(val.decode(gConfig('textEncoding')),',')) |
238 |
|
else: |
239 |
|
addl = ' %s="%s"' % (attribute, string.join(val,',')) |
240 |
else: |
else: |
241 |
addl = ' %s="%s"' % (attribute, saxutils.escape('%s' % val)) |
if type(val) == types.StringType: |
242 |
|
addl = ' %s="%s"' % (attribute, saxutils.escape('%s' % val.decode(gConfig('textEncoding')))) |
243 |
|
else: |
244 |
|
addl = ' %s="%s"' % (attribute, saxutils.escape('%s' % val)) |
245 |
|
if len(addl) + pos > 78: |
246 |
|
xmlString += "\n" + " " * indent + addl |
247 |
|
pos = indent |
248 |
|
else: |
249 |
|
xmlString += addl |
250 |
|
pos += len(addl) |
251 |
|
if attribute.find('__') > 0 and attribute.split('__')[0] in xmlnamespaces.keys(): |
252 |
|
if val != None: |
253 |
|
if type(val) == types.StringType: |
254 |
|
addl = ' %s="%s"' % (attribute.replace('__',':'), saxutils.escape('%s' % val.decode(gConfig('textEncoding')))) |
255 |
|
else: |
256 |
|
addl = ' %s="%s"' % (attribute.replace('__',':'), saxutils.escape('%s' % val)) |
257 |
if len(addl) + pos > 78: |
if len(addl) + pos > 78: |
258 |
xmlString += "\n" + " " * indent + addl |
xmlString += "\n" + " " * indent + addl |
259 |
pos = indent |
pos = indent |
321 |
# Moves upward though the parents of an object till |
# Moves upward though the parents of an object till |
322 |
# it finds the parent of the specified type |
# it finds the parent of the specified type |
323 |
# |
# |
324 |
def findChildOfType(self, type, includeSelf=1, allowAllChildren=1): |
def findChildOfType(self, type, includeSelf=1, allowAllChildren=0): |
325 |
|
|
326 |
if includeSelf and self._type == type: |
if includeSelf and self._type == type: |
327 |
return self |
return self |
340 |
|
|
341 |
|
|
342 |
# |
# |
343 |
|
# findChildrenOfType |
344 |
|
# |
345 |
|
# find all children of a specific type |
346 |
|
# |
347 |
|
def findChildrenOfType(self, type, includeSelf=1, allowAllChildren=0): |
348 |
|
|
349 |
|
rs = [] |
350 |
|
|
351 |
|
if includeSelf and self._type == type: |
352 |
|
rs += [self] |
353 |
|
|
354 |
|
for child in self._children: |
355 |
|
if child._type == type: |
356 |
|
rs += [child] |
357 |
|
|
358 |
|
if allowAllChildren: |
359 |
|
for child in self._children: |
360 |
|
rs += child.findChildOfType(type,0, 1) |
361 |
|
|
362 |
|
return rs |
363 |
|
|
364 |
|
|
365 |
|
# |
366 |
# getDescription |
# getDescription |
367 |
# |
# |
368 |
# Return a useful description of this object |
# Return a useful description of this object |
376 |
else: |
else: |
377 |
return self._type[2:] + " (%s)" % self._type[2:] |
return self._type[2:] + " (%s)" % self._type[2:] |
378 |
|
|
379 |
|
# Hooks |
380 |
|
def __getitem__(self, key): |
381 |
|
return self._getItemHook(key) |
382 |
|
|
383 |
|
def __setitem__(self, key, value): |
384 |
|
return self._setItemHook(key, value) |
385 |
|
|
386 |
|
def _getItemHook(self, key): |
387 |
|
return self.__dict__[key] |
388 |
|
|
389 |
|
def _setItemHook(self, key, value): |
390 |
|
self.__dict__[key] = value |
391 |
|
|
392 |
|
|
393 |
|
# |
394 |
|
# ParserMultiplexor |
395 |
|
# |
396 |
|
# When a GParser's BaseClass needs to be dependent upon |
397 |
|
# an attribute, the tool can use a customized ParserMultiplexor, |
398 |
|
# overwriting the getClass method. |
399 |
|
# |
400 |
|
# e.g., assume we have an xml tag 'goblin', that |
401 |
|
# corresponds to a GObj-based class Goblin. However, |
402 |
|
# if <goblin style="boo"> we really need a BooGoblin |
403 |
|
# object or if <goblin style="foo"> then we need a |
404 |
|
# FooBoblin object, then the a GoblinPlexor would |
405 |
|
# define getClass as: |
406 |
|
# |
407 |
|
# def getClass(self): |
408 |
|
# if self.style == 'boo': |
409 |
|
# return BooGoblin |
410 |
|
# elif self.style == 'foo': |
411 |
|
# return FooGoblin |
412 |
|
# else: |
413 |
|
# return Goblin |
414 |
|
# |
415 |
|
class ParserMultiplexor(ParserObj): |
416 |
|
|
417 |
|
def _buildObject(self): |
418 |
|
newObj = self.getClass()(None) |
419 |
|
for attr, value in self.__dict__.items(): |
420 |
|
if attr not in ('_buildObject','getClass') and attr[:2] != '__': |
421 |
|
newObj.__dict__[attr] = value |
422 |
|
|
423 |
|
if self._parent: |
424 |
|
self._parent._children[self._parent._children.find(self)] = newObj |
425 |
|
return newObj._buildObject(self) |
426 |
|
|
427 |
|
|
428 |
|
# This should return a GObj-based class |
429 |
|
def getClass(self): |
430 |
|
raise "Virtual method not implemented" |
431 |
|
|
432 |
|
|