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 |
# GParser.py |
# GParser.py |
29 |
|
|
30 |
import sys, copy, types |
import sys, copy, types |
31 |
from gnue.common.GObjects import GObj |
from gnue.common.GObjects import GObj |
32 |
|
from gnue.common.GRootObj import GRootObj |
33 |
from gnue.common.GTrigger import GTrigger |
from gnue.common.GTrigger import GTrigger |
34 |
from gnue.common.FileUtils import openResource |
from gnue.common.FileUtils import openResource |
35 |
|
|
85 |
def loadXMLObject(stream, handler, rootType, xmlFileType, |
def loadXMLObject(stream, handler, rootType, xmlFileType, |
86 |
initialize=1, attributes={}, initParameters={}): |
initialize=1, attributes={}, initParameters={}): |
87 |
|
|
|
|
|
88 |
# Create a parser |
# Create a parser |
89 |
parser = xml.sax.make_parser() |
parser = xml.sax.make_parser() |
90 |
|
|
91 |
# Set up some namespace-related stuff for the parsers |
# Set up some namespace-related stuff for the parsers |
92 |
parser.setFeature(xml.sax.handler.feature_namespaces, 1) |
parser.setFeature(xml.sax.handler.feature_namespaces, 1) |
93 |
|
|
94 |
# Allow for parameter external entities |
# Allow for parameter external entities |
95 |
## Does not work with expat!!! ## |
## Does not work with expat!!! ## |
96 |
##parser.setFeature(xml.sax.handler.feature_external_pes, 1) |
##parser.setFeature(xml.sax.handler.feature_external_pes, 1) |
109 |
object = dh.getRoot() |
object = dh.getRoot() |
110 |
|
|
111 |
if not object: |
if not object: |
112 |
raise MarkupError, _("Error loading %s: empty definition file") % (xmlFileType) |
tmsg = _("Error loading %s: empty definition file") % (xmlFileType) |
113 |
|
raise MarkupError, tmsg |
114 |
elif object._type != rootType: |
elif object._type != rootType: |
115 |
raise MarkupError, _("Error loading %s: not a valid %s definition (expected: %s, got: %s)") % (xmlFileType, |
tmsg = _("Error loading %s: not a valid %s definition (expected: %s, got: %s)") % \ |
116 |
xmlFileType, rootType, object._type) |
(xmlFileType, xmlFileType, rootType, object._type) |
117 |
|
raise MarkupError, tmsg |
118 |
|
|
119 |
dh.finalValidation() |
dh.finalValidation() |
120 |
|
|
121 |
# Set the object's attributes |
# Set the root object's attributes |
122 |
object.__dict__.update(attributes) |
# |
123 |
|
# There should only be 1 root object but GNUe Forms |
124 |
|
# allows for nested forms so we have to walk the tree |
125 |
|
# |
126 |
|
# |
127 |
|
#object.__dict__.update(attributes) |
128 |
|
|
129 |
|
object.walk(addAttributesWalker,attributes=attributes) |
130 |
|
|
|
|
|
131 |
if initialize: |
if initialize: |
132 |
GDebug.printMesg(10,"Initializing the object tree starting at %s" %(object)) |
GDebug.printMesg(10,"Initializing the object tree starting at %s" %(object)) |
133 |
object.phaseInit(dh._phaseInitCount) |
object.phaseInit(dh._phaseInitCount) |
135 |
|
|
136 |
|
|
137 |
return object |
return object |
138 |
|
####################################################### |
139 |
|
# |
140 |
|
# addAttributesWalker |
141 |
|
# |
142 |
|
####################################################### |
143 |
|
def addAttributesWalker(object, attributes={}): |
144 |
|
if isinstance(object,GRootObj): |
145 |
|
object.__dict__.update(attributes) |
146 |
|
|
147 |
|
|
148 |
|
|
149 |
####################################################### |
####################################################### |
177 |
|
|
178 |
self.xmlElements = {} |
self.xmlElements = {} |
179 |
self.xmlMasqueradeNamespaceElements = None |
self.xmlMasqueradeNamespaceElements = None |
180 |
|
self.xmlNamespaceAttributesAsPrefixes = 0 |
181 |
|
|
182 |
self.xmlStack = [] |
self.xmlStack = [] |
183 |
self.nameStack = [] |
self.nameStack = [] |
185 |
self.uniqueIDs = {} |
self.uniqueIDs = {} |
186 |
self.root = None |
self.root = None |
187 |
self._phaseInitCount = 0 |
self._phaseInitCount = 0 |
188 |
|
|
189 |
self._requiredTags = [] |
self._requiredTags = [] |
190 |
self._singleInstanceTags = [] |
self._singleInstanceTags = [] |
191 |
self._tagCounts = {} |
self._tagCounts = {} |
192 |
|
|
193 |
|
|
194 |
# |
# |
195 |
# Called by client code to get the "root" node |
# Called by client code to get the "root" node |
196 |
# |
# |
218 |
self._singleInstanceTags.append(element) |
self._singleInstanceTags.append(element) |
219 |
except KeyError: |
except KeyError: |
220 |
pass |
pass |
221 |
|
|
222 |
def finalValidation(self): |
def finalValidation(self): |
223 |
for element in self._singleInstanceTags: |
# TODO: too simple a validation need to be per object instance |
224 |
if self._tagCounts[element] > 1: |
#for element in self._singleInstanceTags: |
225 |
raise MarkupError, _("File has multiple instances of <%s> when only one allowed") % (element) |
# if self._tagCounts[element] > 1: |
226 |
|
# raise MarkupError, _("File has multiple instances of <%s> when only one allowed") % (element) |
227 |
|
|
228 |
for element in self._requiredTags: |
for element in self._requiredTags: |
229 |
if self._tagCounts[element] < 1: |
if self._tagCounts[element] < 1: |
230 |
raise MarkupError, _("File is missing required tag <%s>") % (element) |
tmsg = _("File is missing required tag <%s>") % (element) |
231 |
|
raise MarkupError, tmsg |
232 |
|
|
233 |
|
|
234 |
# |
# |
235 |
# Called by the internal SAX parser whenever |
# Called by the internal SAX parser whenever |
244 |
# |
# |
245 |
# No namespace qualifier |
# No namespace qualifier |
246 |
# |
# |
|
self._tagCounts[name] += 1 |
|
247 |
GDebug.printMesg(50, "<%s>" % name) |
GDebug.printMesg(50, "<%s>" % name) |
248 |
|
|
249 |
try: |
try: |
250 |
baseAttrs = self.xmlElements[name].get('Attributes',{}) |
baseAttrs = self.xmlElements[name].get('Attributes',{}) |
251 |
except KeyError: |
except KeyError: |
252 |
raise MarkupError, _('Error processing <%s> tag [I do not know what a <%s> tag does]') % (name, name) |
tmsg = _("Error processing <%s> tag [I do not know what a <%s> tag does]") \ |
253 |
|
% (name, name) |
254 |
|
raise MarkupError, tmsg |
255 |
|
|
256 |
|
xmlns = {} |
257 |
|
|
258 |
for qattr in saxattrs.keys(): |
for qattr in saxattrs.keys(): |
259 |
attrns, attr = qattr |
attrns, attr = qattr |
260 |
encoding= sys.getdefaultencoding() |
|
261 |
if encoding == 'ascii': |
if attrns: |
262 |
encoding = 'iso8859-1' # TODO: fix this when we have [common] section |
if not self.xmlNamespaceAttributesAsPrefixes: |
263 |
try: # in gnue.conf |
tmsg = _("Unexpected namespace on attribute") |
264 |
encoding = gConfig('formFontEncoding') |
raise tmsg |
265 |
except: |
prefix = attrns.split(':')[-1] |
266 |
pass |
attrs[prefix + '__' + attr] = saxattrs[qattr] |
267 |
|
xmlns[prefix] = attrns |
268 |
# Typecasting, anyone? If attribute should be int, make it an int |
|
269 |
try: |
else: |
270 |
attrs[attr] = baseAttrs[attr].get('Typecast',GTypecast.text)(saxattrs[qattr].encode(encoding)) # default(baseAttrs[attr],'Typecast',GTypecast.text)(saxattrs[qattr]) |
|
271 |
loadedxmlattrs[attr] = attrs[attr] |
# Typecasting, anyone? If attribute should be int, make it an int |
272 |
except KeyError: |
try: |
273 |
raise MarkupError, _('Error processing <%s> tag [I do not recognize the "%s" attribute') % (name, attr) |
attrs[attr] = baseAttrs[attr].get('Typecast',GTypecast.text)(saxattrs[qattr].encode(gConfig('textEncoding'))) |
274 |
except: |
loadedxmlattrs[attr] = attrs[attr] |
275 |
raise MarkupError, _('Error processing <%s> tag [invalid type for "%s" attribute; value is "%s"]') % (name, attr, saxattrs[qattr]) |
except KeyError: |
276 |
|
tmsg = _('Error processing <%s> tag [I do not recognize the "%s" attribute')\ |
277 |
# If this attribute must be unique, check for duplicates |
% (name, attr) |
278 |
if baseAttrs[attr].get('Unique',0): # default (baseAttrs[attr],'Unique',0): |
raise MarkupError, tmsg |
279 |
if self.uniqueIDs.has_key('%s' % (saxattrs[qattr])): |
except: |
280 |
raise MarkupError, _('Error processing <%s> tag ["%s" attribute should be unique; duplicate value is "%s"]') % (name, attr, saxattrs[qattr]) |
tmsg = _('Error processing <%s> tag [invalid type for "%s" attribute; value is "%s"]')\ |
281 |
|
% (name, attr, saxattrs[qattr]) |
282 |
|
raise MarkupError, tmsg |
283 |
|
|
284 |
|
# If this attribute must be unique, check for duplicates |
285 |
|
if baseAttrs[attr].get('Unique',0): # default (baseAttrs[attr],'Unique',0): |
286 |
|
if self.uniqueIDs.has_key('%s' % (saxattrs[qattr])): |
287 |
|
tmsg = _('Error processing <%s> tag ["%s" attribute should be unique; duplicate value is "%s"]')\ |
288 |
|
% (name, attr, saxattrs[qattr]) |
289 |
|
raise MarkupError, tmsg |
290 |
|
|
291 |
for attr in baseAttrs.keys(): |
for attr in baseAttrs.keys(): |
292 |
if not attrs.has_key(attr): |
if not attrs.has_key(attr): |
297 |
|
|
298 |
# Check for missing required attributes |
# Check for missing required attributes |
299 |
elif baseAttrs[attr].get('Required', 0): #default(baseAttrs[attr], 'Required', 0): |
elif baseAttrs[attr].get('Required', 0): #default(baseAttrs[attr], 'Required', 0): |
300 |
raise MarkupError, _('Error processing <%s> tag [required attribute "%s" not present]') % (name, attr) |
tmsg = _('Error processing <%s> tag [required attribute "%s" not present]')\ |
301 |
|
% (name, attr) |
302 |
|
raise MarkupError, tmsg |
303 |
|
|
304 |
|
attrs['_xmlnamespaces'] = xmlns |
305 |
|
|
306 |
if self.bootstrapflag: |
if self.bootstrapflag: |
307 |
if self.xmlStack[0] != None: |
if self.xmlStack[0] != None: |
311 |
self.root = object |
self.root = object |
312 |
self.bootstrapflag = 1 |
self.bootstrapflag = 1 |
313 |
|
|
314 |
|
self._tagCounts[name] += 1 |
315 |
|
|
316 |
object._xmltag = name |
object._xmltag = name |
317 |
|
|
318 |
elif self.xmlMasqueradeNamespaceElements: |
elif self.xmlMasqueradeNamespaceElements: |
434 |
rv.__dict__[key] = self._loadedxmlattrs[key] |
rv.__dict__[key] = self._loadedxmlattrs[key] |
435 |
GDebug.printMesg (5, ">>> Moving %s" % key) |
GDebug.printMesg (5, ">>> Moving %s" % key) |
436 |
rv._buildObject() |
rv._buildObject() |
437 |
|
else: |
438 |
|
tmsg = _("Unable to find an importable object named %s in %s") \ |
439 |
|
% (self.name, self.library) |
440 |
|
raise tmsg |
441 |
|
|
442 |
# |
# |
443 |
# __findImportItem |
# __findImportItem |
459 |
return rv |
return rv |
460 |
else: |
else: |
461 |
return None |
return None |
462 |
|
|
463 |
|
|
464 |
class GImport(GObj): |
class GImport(GObj): |
465 |
def __init__(self, parent=None): |
def __init__(self, parent=None): |
468 |
self._form = None |
self._form = None |
469 |
self._inits = [self.primaryInit] |
self._inits = [self.primaryInit] |
470 |
self._xmlParser = self.findParentOfType(None)._xmlParser |
self._xmlParser = self.findParentOfType(None)._xmlParser |
471 |
|
|
472 |
def primaryInit(self): |
def primaryInit(self): |
473 |
handle = openResource(self.library) |
handle = openResource(self.library) |
474 |
form = self._xmlParser.loadFile(handle, self.findParentOfType(None)._app, initialize=0) |
form = self._xmlParser.loadFile(handle, self.findParentOfType(None)._app, initialize=0) |
480 |
importNames = string.split(string.replace(self._loadedxmlattrs[attribute],' ',''),',') |
importNames = string.split(string.replace(self._loadedxmlattrs[attribute],' ',''),',') |
481 |
|
|
482 |
instanceType = self._xmlParser.getXMLelements()[string.lower(attribute)]['BaseClass'] |
instanceType = self._xmlParser.getXMLelements()[string.lower(attribute)]['BaseClass'] |
483 |
|
|
484 |
if importAll or len(importNames): |
if importAll or len(importNames): |
485 |
for child in form._children: |
for child in form._children: |
486 |
if isinstance(child,instanceType) and \ |
if isinstance(child,instanceType) and \ |
507 |
}, |
}, |
508 |
'ParentTags': rootTag, |
'ParentTags': rootTag, |
509 |
} |
} |
510 |
|
|
511 |
for key in elements.keys(): |
for key in elements.keys(): |
512 |
if elements[key].has_key('Importable') and elements[key]['Importable']: |
if elements[key].has_key('Importable') and elements[key]['Importable']: |
513 |
name = "import-%s" % key |
name = "import-%s" % key |
517 |
|
|
518 |
p = copy.deepcopy(elements[key]) |
p = copy.deepcopy(elements[key]) |
519 |
p['BaseClass'] = GImportItem |
p['BaseClass'] = GImportItem |
520 |
|
|
521 |
if not p.has_key('Attributes'): |
if not p.has_key('Attributes'): |
522 |
p['Attributes'] = {} |
p['Attributes'] = {} |
523 |
|
|