[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r8096 - in trunk/gnue-common/src: definitions logic
From: |
johannes |
Subject: |
[gnue] r8096 - in trunk/gnue-common/src: definitions logic |
Date: |
Tue, 15 Nov 2005 07:35:44 -0600 (CST) |
Author: johannes
Date: 2005-11-15 07:35:43 -0600 (Tue, 15 Nov 2005)
New Revision: 8096
Modified:
trunk/gnue-common/src/definitions/GBinary.py
trunk/gnue-common/src/definitions/GObjects.py
trunk/gnue-common/src/definitions/GParser.py
trunk/gnue-common/src/definitions/GParserHelpers.py
trunk/gnue-common/src/definitions/GRootObj.py
trunk/gnue-common/src/definitions/__init__.py
trunk/gnue-common/src/logic/GTrigger.py
Log:
Code cleanup according to technote 15
Modified: trunk/gnue-common/src/definitions/GBinary.py
===================================================================
--- trunk/gnue-common/src/definitions/GBinary.py 2005-11-11 18:27:31 UTC
(rev 8095)
+++ trunk/gnue-common/src/definitions/GBinary.py 2005-11-15 13:35:43 UTC
(rev 8096)
@@ -1,130 +1,209 @@
+# GNU Enterprise Common Library - GNUe XML object definitions - Binary objects
#
-# This file is part of GNU Enterprise.
+# Copyright 2001-2005 Free Software Foundation
#
-# GNU Enterprise is free software; you can redistribute it
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation; either
+# License as published by the Free Software Foundation; either
# version 2, or (at your option) any later version.
#
# GNU Enterprise is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied
-# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
-# You should have received a copy of the GNU General Public
+# You should have received a copy of the GNU General Public
# License along with program; see the file COPYING. If not,
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000-2005 Free Software Foundation
-#
-#
-# FILE:
-# GBinary.py
-#
-# DESCRIPTION:
-# Provides a container object for binary data.
-#
-# NOTES:
-#
+# $Id$
+"""
+Provides a container object for binary data.
+"""
+__all__ = ['UnsupportedFormatError', 'GBinary', 'getXMLelements']
+
import base64
+
+from gnue.common.apps import errors
from gnue.common.definitions.GObjects import GObj
-#
+
+# =============================================================================
+# Exceptions
+# =============================================================================
+
+class UnsupportedFormatError (errors.ApplicationError):
+ def __init__ (self, format):
+ msg = u_("Unsupported binary format: '%(format)s'") % {'format': format}
+ raise errors.ApplicationError.__init__ (self, msg)
+
+
+# =============================================================================
# GBinary
-#
-#
-class GBinary(GObj):
- def __init__(self, name="GBinary", parent=None):
- GObj.__init__(self, name, parent=None)
- self.__data__ = ""
- self.format = "base64"
+# =============================================================================
+
+class GBinary (GObj):
+ """
+ Container class for binary data. The only format currently supported is
+ 'base64'.
+ """
+
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__(self, name = "GBinary", parent = None):
+
+ GObj.__init__ (self, name, parent = None)
+ self.__data__ = ""
+ self.format = "base64"
self._phaseInits = [self.init]
- def init(self):
+ # ---------------------------------------------------------------------------
+ # Initialize instance
+ # ---------------------------------------------------------------------------
+
+ def init (self):
+ """
+ Prepare the __data__ attribute from all the children's contents.
+
+ @raises UnsupportedFormatError: if the format is not supported
+ """
+
if self.format == 'base64':
- self.__data__ = base64.decodestring(self.getChildrenAsContent())
+ self.__data__ = base64.decodestring (self.getChildrenAsContent ())
else:
- raise "Unsupported binary format: %s" % self.format
+ raise UnsupportedFormatError, self.format
self._children = []
- def set(self, data):
+
+ # ---------------------------------------------------------------------------
+ # Set the data for the object
+ # ---------------------------------------------------------------------------
+
+ def set (self, data):
+ """
+ Set the data for the object
+
+ @param data: the data to set
+ """
+
self.__data__ = data
- def get(self, data):
+
+ # ---------------------------------------------------------------------------
+ # Get the currenlty defined data
+ # ---------------------------------------------------------------------------
+
+ def get (self, data):
+ """
+ @returns: the data of this object
+ """
+
return data
- #
- # dumpXML
- #
+
+ # ---------------------------------------------------------------------------
# Dumps an XML representation of the object
- # used in saving
- #
- def dumpXML(self, lookupDict, treeDump=None, gap=None,xmlnamespaces={},
- stripPrefixes = None):
+ # ---------------------------------------------------------------------------
+ def _dumpXML_ (self, lookupDict, treeDump, gap, xmlnamespaces, textEncoding,
+ stripPrefixes, escape):
+ """
+ Return a XML representation of the object.
+
+ @param lookupDict: dictionary describing the XML entities, their
+ attributes and types
+ @param treeDump: if True, also include a XML representation of all
children
+ @param gap: string defining the current indentation level
+ @param xmlnamespaces: dictionary with the available XML namespaces
+ @param textEncoding: encoding used to transform string-type attributes into
+ unicode. If textEncoding is set to '<locale>' (default) it will be set to
+ the configuration variable 'textEncoding', i.e. from gnue.conf
+ @param stripPrefixes: a list of prefixes that will automatically be removed
+ from the objects type. This can be used to remove the GF from the start
+ of all the gnue-forms objects. If set to None (the default) then the
+ behaviour will be the old style which removes the first two characters
+ from the type.
+ @param escape: if set to True the resulting XML string should be escaped
+
+ @returns: a string with the object's XML representation
+ """
+
xmlEntity = "binary"
- xmlString = "%s<%s" % (gap[:-2],xmlEntity)
+ xmlString = "%s<%s" % (gap [:-2],xmlEntity)
- indent = len(xmlString)
- pos = indent
- for attribute in self.__dict__.keys():
+ indent = len (xmlString)
+ pos = indent
- # variables beginning with _ are never saved out to file
- # they are internal to the program
- if attribute[0] == "_":
- continue
+ for attribute in [a for a in self.__dict__ if a [0] != '_']:
+ val = self.__dict__ [attribute]
- val = self.__dict__[attribute]
- if lookupDict[xmlEntity].has_key('Attributes') and \
- lookupDict[xmlEntity]['Attributes'].has_key(attribute):
+ if lookupDict [xmlEntity].has_key ('Attributes') and \
+ lookupDict [xmlEntity]['Attributes'].has_key (attribute):
+
+ attrDef = lookupDict [xmlEntity]['Attributes'][attribute]
+
if val != None and \
- (not
lookupDict[xmlEntity]['Attributes'][attribute].has_key('Default') or \
- (lookupDict[xmlEntity]['Attributes'][attribute]['Default']) !=
(val)):
- typecast = lookupDict[xmlEntity]['Attributes'][attribute]['Typecast']
- if typecast == GTypecast.boolean \
- and val == 1:
+ (not 'Default' in attrDef or attrDef ['Default'] != (val)):
+
+ typecast = attrDef ['Typecast']
+ if typecast == GTypecast.boolean and val == 1:
addl = ' %s=""' % (attribute)
elif typecast == GTypecast.names:
- addl = ' %s="%s"' % \
- (attribute, string.join(val,','))
+ addl = ' %s="%s"' % (attribute, ','.join (val))
else:
- addl = ' %s="%s"' % (attribute, saxutils.escape('%s' % val))
+ addl = ' %s="%s"' % (attribute, saxutils.escape ('%s' % val))
+
if len(addl) + pos > 78:
xmlString += "\n" + " " * indent + addl
pos = indent
else:
xmlString = xmlString + addl
- pos += len(addl)
+ pos += len (addl)
xmlString += ">\n"
if self.format == 'base64':
- xmlString += base64.encodestring(self.__data__)
+ xmlString += base64.encodestring (self.__data__)
else:
- raise "Unsupported binary format: %s" % self.format
- xmlString += "%s</%s>\n" % (gap[:-2], xmlEntity)
+ raise UnsupportedFormatError, self.format
+ xmlString += "%s</%s>\n" % (gap [:-2], xmlEntity)
+
return xmlString
- def getChildrenAsContent(self):
+ # ---------------------------------------------------------------------------
+ # Return the children's content
+ # ---------------------------------------------------------------------------
+
+ def getChildrenAsContent (self):
+ """
+ A L{GBinary} instance cannot have children, so the result of this function
+ is just the same as the method L{get}.
+
+ @returns: the data of the object
+ """
+
return self.__data__
+# =============================================================================
+# Return any XML elements associated with GBinary
+# =============================================================================
+def getXMLelements (updates={}):
+ """
+ Return any XML elements associated with GBinary
+ @returns: dictionary with all elements associated with GBinary
+ """
-#
-# Return any XML elements associated with
-# GTriggers. Bases is a dictionary of tags
-# whose values are update dictionaries.
-# For example: bases={'datasource': {'BaseClass':myDataSource}}
-# sets xmlElements['datasource']['BaseClass'] = myDataSource
-#
-def getXMLelements(updates={}):
-
xmlElements = {
'binary': {
'BaseClass': GBinary,
@@ -146,8 +225,7 @@
'ParentTags': None },
}
- for alteration in updates.keys():
- xmlElements[alteration].update(updates[alteration])
+ for alteration in updates.keys ():
+ xmlElements [alteration].update (updates [alteration])
return xmlElements
-
Property changes on: trunk/gnue-common/src/definitions/GBinary.py
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: trunk/gnue-common/src/definitions/GObjects.py
===================================================================
--- trunk/gnue-common/src/definitions/GObjects.py 2005-11-11 18:27:31 UTC
(rev 8095)
+++ trunk/gnue-common/src/definitions/GObjects.py 2005-11-15 13:35:43 UTC
(rev 8096)
@@ -1,6 +1,9 @@
+# GNU Enterprise Common Library - GNUe XML object definitions
#
-# This file is part of GNU Enterprise.
+# Copyright 2001-2005 Free Software Foundation
#
+# This file is part of GNU Enterprise
+#
# GNU Enterprise is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
@@ -16,64 +19,110 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000-2005 Free Software Foundation
-#
-# FILE:
-# GObjects.py
-#
-# DESCRIPTION:
+# $Id$
+
"""
Base class for GNUe objects which can be represented as XML
"""
-__revision__ = "$Id$"
+__all__ = ['GObj', 'ParserMultiplexor', 'GUndividedCollection']
+
from xml.sax import saxutils
-from gnue.common.apps import GDebug
-import string
-import types
from gnue.common.definitions.GParserHelpers import GContent, ParserObj
from gnue.common.formatting import GTypecast
from gnue.common.logic.GTriggerCore import GTriggerCore
-#
-# Class GObj
-#
-# Base class for GNUe objects which
-# can be represented by XML tags
-#
-class GObj(GTriggerCore, ParserObj):
+
+# =============================================================================
+# Base class for GNUe object which can be represented by XML tags
+# =============================================================================
+
+class GObj (GTriggerCore, ParserObj):
"""
- The base class for almost all GNUe objects.
+ The base class for almost all GNUe objects. GObj based objects can be
+ represented by XML tags in a GParser based setup. This class introduces the
+ concept of phased initialization as well as dictionary style access.
- GObj based objects can be represented by XML tags in a GParser
- based setup.
+ This is the method of attribute access used by Designer and Reports.
+ For example. if foo is a GObject, then the following are equivalent::
+ foo.required = 'Y'
+ foo['required'] = 'Y'
+
+ The advantage of this method, however, is when namespaces are used
+ in the GObj XML document (i.e., reports). e.g., ::
+ foo['Char:x'] = 1
+ foo['Char:y'] = 2
+
+ These don't have a clean equivalent using the .attribute method.
+ (Though, technically, a tool could access foo.Char__x, but that
+ should be considered bad style.)
+
+ Eventually, .attribute style access should probably be deprecated,
+ so we can clean up the python namespaces of GObjects. (i.e., we could
+ keep all XML-storable attributes in one dict instead of in the
+ namespace __dict__.
"""
- def __init__(self, *args, **parms):
- GTriggerCore.__init__(self)
- ParserObj.__init__(self, *args, **parms)
+
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, *args, **parms):
+
+ GTriggerCore.__init__ (self)
+ ParserObj.__init__ (self, *args, **parms)
+
self._inits = []
- def buildObject(self, **params):
- """
- A convenience function for applications NOT using GParser to load an
object tree.
+ # ---------------------------------------------------------------------------
+ # Dictionary style attribute access
+ # ---------------------------------------------------------------------------
+
+ def __getitem__ (self, key):
+
+ return self.__dict__ [key.replace (':', '__')]
+
+
+ # ---------------------------------------------------------------------------
+
+ def __setitem__ (self, key, value):
+
+ return self._setItemHook (key.replace (':', '__'), value)
+
+
+ # ---------------------------------------------------------------------------
+ # Build an object using attributes given as keyword arguments
+ # ---------------------------------------------------------------------------
+
+ def buildObject (self, **params):
"""
- self.__dict__.update(params)
- return self._buildObject()
+ A convenience function for applications NOT using GParser to load an object
+ tree.
+ """
+ self.__dict__.update (params)
+ return self._buildObject ()
- def buildAndInitObject(self, **params):
+
+ # ---------------------------------------------------------------------------
+ # Build and initialize an object using attributes given as keyword arguments
+ # ---------------------------------------------------------------------------
+
+ def buildAndInitObject (self, **params):
"""
- This is a convenience function for applications
- NOT using GParser to load an object tree.
+ This is a convenience function for applications NOT using GParser to load
+ an object tree.
"""
- self.phaseInit(self.buildObject(**params))
+ self.phaseInit (self.buildObject (**params))
- #
+
+ # ---------------------------------------------------------------------------
# phaseInit
- #
- def phaseInit(self, iterations=0):
+ # ---------------------------------------------------------------------------
+
+ def phaseInit (self, iterations = 0):
"""
Starts GNUe's phased initialization system from this object down.
@@ -100,21 +149,164 @@
as the children may not be loaded yet or may not yet have the needed
information.
- @type iterations: integer
@param iterations: Limits the number of passes to the specified number.
- This doesn't appear to be used anywhere.
"""
+
if iterations == 0:
- iterations = self.maxInits()
- for phase in range(iterations):
- self._phaseInit(phase)
+ iterations = self.maxInits ()
- def _phaseInit(self, phase):
+ for phase in range (iterations):
+ self._phaseInit (phase)
+
+
+ # ---------------------------------------------------------------------------
+ # Get the maximium size of all the _inits lists
+ # ---------------------------------------------------------------------------
+
+ def maxInits (self):
"""
- Used internally by phaseInit to walk through the
- object tree initializing objects.
+ maxInits returns the maximum size of all the _inits list from this object
+ or it's children
"""
+ self._initCount = 0
+ self.walk (self.__maxInitsWalker)
+ return self._initCount
+
+ # ---------------------------------------------------------------------------
+
+ def __maxInitsWalker (self, object):
+ """
+ The function passed to the tree walker to extract the length of the _inits
+ list.
+
+ @param object: L{GObj} to the get the length of it's _inits sequence
+ """
+ if hasattr (object, '_inits'):
+ self._initCount = max (self._initCount, len (object._inits))
+
+
+ # ---------------------------------------------------------------------------
+ # Show the XML tree of an object
+ # ---------------------------------------------------------------------------
+
+ def showTree (self, indent = 0):
+ """
+ A recusive function to print an indented text representation of the GObj
+ tree from this object down. This is usefull for debugging purposes.
+
+ @param indent: Sets the level of indention. Used during recursion to
+ properly indent the tree.
+ @type indent: int
+ """
+
+ print ' ' * indent + `self._type`, self
+
+ for child in self._children:
+ child.showTree (indent + 2)
+
+
+ # ---------------------------------------------------------------------------
+ # Get the XML tag used to represent the object
+ # ---------------------------------------------------------------------------
+
+ def getXmlTag (self, stripPrefixes = None):
+ """
+ Returns the xml tag to be used to represent the object.
+
+ @param stripPrefixes: A list of prefixes that will automatically be removed
+ from the objects type. This can be used to remove the gf from the start
+ of all the gnue-forms objects. If set to None (the default) then the
+ behaviour will be the old style which removes the first two characters
+ from the type.
+
+ @returns: The XML tag to use
+ @rtype: string
+ """
+
+ if stripPrefixes is None:
+ return self._type [2:].replace ('_', '-').lower ()
+
+ for prefix in stripPrefixes:
+ if prefix == self._type [:len (prefix)]:
+ return self._type [len (prefix):].replace ('_', '-').lower ()
+
+ return self._type.replace ('_', '-').lower ()
+
+
+ # ---------------------------------------------------------------------------
+ # Function for traversing an object tree
+ # ---------------------------------------------------------------------------
+
+ def walk (self, function, *args, **parms):
+ """
+ Function that recursively walks down through a tree of L{ParserObj}
+ instances and applies a function to them.
+
+ @param function: the function to call for every element found in the tree
+ """
+
+ function (self, *args, **parms)
+ for child in self._children:
+ if isinstance (child, GObj):
+ child.walk (function, *args, **parms)
+
+
+ # ---------------------------------------------------------------------------
+ # Get an iterator for child objects
+ # ---------------------------------------------------------------------------
+
+ def iterator (self, test = None, types = (), includeSelf = True):
+ """
+ Return a python iterator of child objects.
+
+ @param test: A function that should return true or false to
+ indicate whether a GObject should be included in the
+ iterator. This method will be passed a GObj instance.
+ e.g., test=lambda obj: obj._type in ('GFField,'GFEntry')
+ @type test: method
+
+ @param types: A list of valid child types to return.
+ E.g., types=('GFField','GFEntry')
+ @type types: list
+
+ @param includeSelf: Should the current object be included in the tests?
+ @type includeSelf: boolean
+
+ @return: An iterator of matching objects
+
+ """
+ if includeSelf:
+ objects = [self]
+ else:
+ objects = self._children
+ set = []
+
+ def _includable (object):
+ include = True
+ if test:
+ include = include and test (object)
+ if types:
+ include = include and object._type in types
+ if include:
+ set.append (object)
+
+ for child in objects:
+ child.walk (_includable)
+
+ return _GObjectIterator (set)
+
+
+ # ---------------------------------------------------------------------------
+ # Worker function to perform an initialization
+ # ---------------------------------------------------------------------------
+
+ def _phaseInit (self, phase):
+ """
+ Used internally by phaseInit to walk through the object tree initializing
+ objects.
+ """
+
## TODO: Below is a call-less recursive version of
## TODO: phaseInit. Needs to be profiled both ways.
## TODO: Profile tests have shown this to be .001
@@ -134,244 +326,201 @@
## continue
inits = self._inits
- if (len(inits) > phase) and inits[phase]:
- assert gDebug(7,"%s: Init Phase %s" % (self._type, phase+1))
- inits[phase]()
+ if (len (inits) > phase) and inits [phase]:
+ assert gDebug (7,"%s: Init Phase %s" % (self._type, phase+1))
+ inits [phase] ()
for child in self._children:
try:
initter = child._phaseInit
except AttributeError:
continue
- initter(phase)
+ initter (phase)
- def _buildObject(self):
- """
- # This function is called after the parsers have completely
- # constructed. All children should be in place and
- # attributes and content should be set at this point.
- # Return the number of phaseInit iterations your object will
- # need.
- #
- # NOTE: Do not initialize datasources, etc at this point.
- # This is only so content can be set, etc, after
- # loading from XML.
- #
- """
- return len(self._inits)
+ # ---------------------------------------------------------------------------
+ # Get the number of phaseInit iterations needed by the object
+ # ---------------------------------------------------------------------------
- def maxInits(self):
+ def _buildObject (self):
"""
- maxInits returns the maximum size of all the _inits
- list from this object or it's children
- """
- self._initCount = 0
- self.walk(self._maxInitsWalker)
- return self._initCount
+ This function is called after the parsers have completely constructed. All
+ children should be in place and attributes and content should be set at
+ this point. Return the number of phaseInit iterations your object will
+ need.
- def _maxInitsWalker(self, object):
- """
- The function passed to the tree walker to extract the
- length of the _inits list. Used by maxInits.
- """
- if hasattr(object, '_inits'):
- self._initCount = max(self._initCount, len(object._inits))
+ NOTE: Do not initialize datasources, etc at this point. This is only so
+ content can be set, etc, after loading from XML.
-
- def getChildrenAsContent(self):
+ @returns: number of the phaseInit iterations needed by this object
"""
- Returns the content of any GContent objects that are children
- of this object.
- @rtype: string or binary(?)
- @return: The contents of the children
- """
+ return len (self._inits)
- # This is down here to avoid recursive importing
- from gnue.common.definitions.GBinary import GBinary
- content = ""
- for child in self._children:
- if isinstance(child, GContent):
- content += child._content
- elif isinstance(child, GBinary):
- content += child.__data__
- return content
+ # ---------------------------------------------------------------------------
+ # callback function called when an item has been changed
+ # ---------------------------------------------------------------------------
- def showTree(self, indent=0):
+ def _setItemHook (self, key, value):
"""
- A recusive function to print an indented text representation of
- the GObj tree from this object down.
+ This bit of nastiness is here to let GNUe Designer capture the setting of
+ GObject properties. This is primarily used in the wizard system so Designer
+ can act in real time as a wizard sets a document's properties.
- This is usefull for debugging purposes.
+ I.e., if a wizard sets::
+ field['width'] = 10
- @param indent: Sets the level of indention. Used during recursion
- to properly indent the tree.
- @type indent: int
+ Designer can immediately changed the visual width of the field as displayed
+ on screen.
"""
- print ' ' * indent + `self._type`, self
+ self.__dict__ [key] = value
- for child in self._children:
- child.showTree(indent + 2)
- #
- # addChild
- #
- #
- def addChild(self, child):
- """
- Adds an object to an instances list of children
+ # ---------------------------------------------------------------------------
+ # Implementation of virtual methods
+ # ---------------------------------------------------------------------------
- @type child: GObj derived class
- @param child: The object to add.
+ def _dumpXML_ (self, lookupDict, treeDump, gap, xmlnamespaces, textEncoding,
+ stripPrefixes, escape):
"""
- self._children.append(child)
-
- def getXmlTag(self, stripPrefixes=None):
+ Dumps an XML representation of the object
"""
- Returns the xml tag to be used to represent the object.
- @param stripPrefixes: A list of prefixes that will automatically
- be removed from the objects type. This can be
- used to remove the gf from the start of all
- the gnue-forms objects. If set to None (the default)
- then the behaviour will be the old style which
- removes the first two characters from the type.
- @return: The xml tag to use
- @rtype: string
- """
- if stripPrefixes == None:
- return string.lower(string.replace(self._type[2:], '_', '-'))
- for prefix in stripPrefixes:
- if prefix == self._type[:len(prefix)]:
- return string.lower(string.replace(self._type[len(prefix):], '_', '-'))
- return string.lower(string.replace(self._type, '_', '-'))
-
- def dumpXML(self, lookupDict, treeDump=None, gap=" ", xmlnamespaces={},
- textEncoding='<locale>', stripPrefixes=None):
- """
- Dumps an XML representation of the object
- """
- xmlns = ""
+ xmlns = ""
xmlnsdef = ""
- if textEncoding=='<locale>':
- textEncoding=gConfig('textEncoding')
+ if textEncoding == '<locale>':
+ textEncoding = gConfig('textEncoding')
try:
if self._xmlnamespace:
try:
- xmlns = xmlnamespaces[self._xmlnamespace] + ":"
+ xmlns = xmlnamespaces [self._xmlnamespace] + ":"
+
except KeyError:
- i = 0
+ i = 0
xmlns = "out"
- while xmlns in xmlnamespaces.values():
- i += 1
+
+ while xmlns in xmlnamespaces.values ():
+ i += 1
xmlns = "out%s" % i
- xmlnamespaces[self._xmlnamespace] = xmlns
+
+ xmlnamespaces [self._xmlnamespace] = xmlns
xmlnsdef = ' xmlns:%s="%s"' % (xmlns, self._xmlnamespace)
- xmlns += ":"
+ xmlns += ":"
+
except AttributeError:
try:
if self._xmlchildnamespace:
- if not xmlnamespaces.has_key(self._xmlchildnamespace):
- i = 0
+ if not xmlnamespaces.has_key (self._xmlchildnamespace):
+ i = 0
ns = "out"
- while ns in xmlnamespaces.values():
+
+ while ns in xmlnamespaces.values ():
i += 1
ns = "out%s" % i
- xmlnamespaces[self._xmlnamespace] = ns
+
+ xmlnamespaces [self._xmlnamespace] = ns
xmlnsdef = ' xmlns:%s="%s"' % (ns, self._xmlchildnamespace)
+
except AttributeError:
pass
try:
if self._xmlchildnamespaces:
- for abbrev in self._xmlchildnamespaces.keys():
- xmlnsdef += ' xmlns:%s="%s"' % (abbrev,
self._xmlchildnamespaces[abbrev])
+ for abbrev in self._xmlchildnamespaces.keys ():
+ xmlnsdef += ' xmlns:%s="%s"' % \
+ (abbrev, self._xmlchildnamespaces [abbrev])
+
except AttributeError:
pass
- xmlEntity = self.getXmlTag(stripPrefixes)
+ xmlEntity = self.getXmlTag (stripPrefixes)
xmlString = "%s<%s%s%s" % (gap[:-2], xmlns, xmlEntity, xmlnsdef)
- indent = len(xmlString)
- pos = indent
- attrs = self.__dict__.keys()
- attrs.sort()
+ indent = len (xmlString)
+ pos = indent
+ attrs = self.__dict__.keys ()
+ attrs.sort ()
# Make 'name' first
if 'name' in attrs:
- attrs.pop(attrs.index('name'))
- attrs.insert(0, 'name')
+ attrs.pop (attrs.index ('name'))
+ attrs.insert (0, 'name')
- for attribute in attrs:
- # skip keys beginning with _
- if attribute[0] == "_":
- continue
+ # Iterate over all attributes which do not start with an underscore
+ for attribute in [a for a in attrs if a [0] != "_"]:
+ val = self.__dict__ [attribute]
- val = self.__dict__[attribute]
if (xmlns and attribute in self._listedAttributes) or \
- (not xmlns and lookupDict[xmlEntity].has_key('Attributes') and \
- lookupDict[xmlEntity]['Attributes'].has_key(attribute)):
+ (not xmlns and lookupDict [xmlEntity].has_key ('Attributes') and \
+ lookupDict [xmlEntity]['Attributes'].has_key (attribute)):
+
+ attrDef = lookupDict [xmlEntity]['Attributes'][attribute]
+
if val != None and \
- (xmlns or (not
lookupDict[xmlEntity]['Attributes'][attribute].has_key('Default') or \
- (lookupDict[xmlEntity]['Attributes'][attribute]['Default']) !=
(val))):
+ (xmlns or (not 'Default' in attrDef or \
+ (attrDef ['Default']) != (val))):
- try:
- typecast =
lookupDict[xmlEntity]['Attributes'][attribute]['Typecast']
- except:
- typecast = GTypecast.text
+ typecast = attrDef.get ('Typecast', GTypecast.text)
if typecast == GTypecast.boolean:
- if val:
- addl = ' %s="Y"' % (attribute)
- else:
- addl = ' %s="N"' % (attribute)
+ addl = ' %s="%s"' % (attribute, ['N', 'Y'][bool (val)])
+
elif typecast == GTypecast.names:
- if type(val) == types.StringType:
- #addl = ' %s="%s"' % (attribute,
string.join(val.decode(textEncoding), ','))
- addl = ' %s="%s"' % (attribute, string.join(unicode(val,
textEncoding), ','))
+ if isinstance (val, (list, tuple)):
+ addl = ' %s="%s"' % (attribute, ','.join (val))
+ elif isinstance (val, string):
+ addl = ' %s="%s"' % (attribute, unicode (val, textEncoding))
else:
- addl = ' %s="%s"' % (attribute, string.join(val, ','))
+ addl = ' %s="%s"' % (attribute, val)
+
else:
- if type(val) == types.StringType:
- #addl = ' %s="%s"' % (attribute, saxutils.escape('%s' %
val.decode(textEncoding)))
- addl = ' %s="%s"' % (attribute, saxutils.escape('%s' %
unicode(val, textEncoding)))
- else:
- addl = ' %s="%s"' % (attribute, saxutils.escape('%s' % val))
+ cont = '%s' % val
+ if isinstance (val, str):
+ cont = unicode (val, textEncoding)
- if len(addl) + pos > 78:
+ addl = ' %s="%s"' % (attribute, saxutils.escape (cont))
+
+ if len (addl) + pos > 78:
xmlString += "\n" + " " * indent + addl
- pos = indent
+ pos = indent
else:
xmlString += addl
- pos += len(addl)
+ pos += len (addl)
- if attribute.find('__') > 0 and attribute.split('__')[0] in
xmlnamespaces.keys():
+ if attribute.find ('__') > 0 and \
+ attribute.split ('__') [0] in xmlnamespaces:
+
if val != None:
- if type(val) == types.StringType:
- addl = ' %s="%s"' % (attribute.replace('__', ':'),
saxutils.escape('%s' % unicode(val, textEncoding)))
+ attrName = attribute.replace ('__', ':')
+ attrValue = val
+
+ if isinstance (val, str):
+ attrValue = unicode (val, textEncoding)
else:
try:
- if val == int(val):
- val = int(val)
+ if val == int (val):
+ attrValue = int (val)
+
except:
pass
- addl = ' %s="%s"' % (attribute.replace('__', ':'),
saxutils.escape('%s' % val))
- if len(addl) + pos > 78:
+
+ addl = ' %s="%s"' % (attrName, saxutils.escape ('%s' % attrValue))
+
+ if len (addl) + pos > 78:
xmlString += "\n" + " " * indent + addl
pos = indent
else:
xmlString += addl
- pos += len(addl)
+ pos += len (addl)
- if len(self._children):
+ if len (self._children):
hasContent = 0
for child in self._children:
- hasContent = hasContent or isinstance(child, GContent)
+ hasContent = hasContent or isinstance (child, GContent)
if hasContent:
xmlString += ">"
else:
@@ -379,250 +528,73 @@
if treeDump:
for child in self._children:
- xmlString += child.dumpXML(lookupDict, 1, gap+" ",
- textEncoding=textEncoding, xmlnamespaces=xmlnamespaces,
stripPrefixes=stripPrefixes)
+ xmlString += child.dumpXML (lookupDict, True, gap + " ",
+ xmlnamespaces, textEncoding, stripPrefixes)
if hasContent:
xmlString += "</%s%s>\n" % (xmlns, xmlEntity)
else:
- xmlString += "%s</%s%s>\n" % (gap[:-2], xmlns, xmlEntity)
+ xmlString += "%s</%s%s>\n" % (gap [:-2], xmlns, xmlEntity)
+
else:
xmlString += "/>\n"
return xmlString
- def walk(self, function, *args, **parms):
- """
- Function that recursively walks down through a tree of GObj
- instances and applies a function to them.
- """
- function(self, *args, **parms)
- for child in self._children:
- if isinstance(child, GObj):
- child.walk(function, *args, **parms)
- def iterator(self, test=None, types=(), includeSelf=True):
- """
- Return a python iterator of child objects.
+# =============================================================================
+# ParserMultiplexor
+# =============================================================================
- @param test: A function that should return true or false to
- indicate whether a GObject should be included in the
- iterator. This method will be passed a GObj instance.
- e.g., test=lambda obj: obj._type in ('GFField,'GFEntry')
- @type test: method
+class ParserMultiplexor (ParserObj):
+ """
+ When a GParser's BaseClass needs to be dependent upon an attribute, the tool
+ can use a customized ParserMultiplexor, overwriting the getClass method.
- @param types: A list of valid child types to return.
- E.g., types=('GFField','GFEntry')
- @type types: list
-
- @param includeSelf: Should the current object be included in the tests?
- @type includeSelf: boolean
-
- @return: An iterator of matching objects
-
- """
- if includeSelf:
- objects = [self]
+ e.g., assume we have a XML tag 'goblin', that corresponds to a GObj-based
+ class Goblin. However, if <goblin style="boo"> we really need a BooGoblin
+ object or if <goblin style="foo"> then we need a FooBoblin object, then the a
+ GoblinPlexor would define getClass as:
+
+ def getClass (self):
+ if self.style == 'boo':
+ return BooGoblin
+ elif self.style == 'foo':
+ return FooGoblin
else:
- objects = self._children
- set = []
+ return Goblin
+ """
- def _includable(object):
- include = True
- if test:
- include = include and test(object)
- if types:
- include = include and object._type in types
- if include:
- set.append(object)
+ # ---------------------------------------------------------------------------
+ # Build an object
+ # ---------------------------------------------------------------------------
- for child in objects:
- child.walk(_includable)
+ def _buildObject (self):
- return _GObjectIterator(set)
+ newObj = self.getClass ()(None)
+ for attr, value in self.__dict__.items ():
+ if attr not in ('_buildObject', 'getClass') and attr [:2] != '__':
+ newObj.__dict__ [attr] = value
- def findParentOfType(self, parentType, includeSelf=1):
- """
- Moves upward though the parents of an object till
- it finds the parent of the specified type
- """
- if includeSelf:
- parentObject = self
- else:
- parentObject = self.getParent ()
+ parent = self.getParent ()
+ if parent:
+ parent._children [parent._children.find (self)] = newObj
- while 1:
- if parentObject == None:
- return None
- elif parentObject._type == parentType:
- return parentObject
+ return newObj._buildObject (self)
- # If passed a type of NONE it finds the top object in the tree
- if not parentType and not parentObject.getParent ():
- return parentObject
- parentObject = parentObject.getParent ()
+ # ---------------------------------------------------------------------------
+ # This should return a GObj-based class
+ # ---------------------------------------------------------------------------
- def findChildNamed(self, name, childType = None):
+ def getClass (self):
"""
- Moves downward though the children of an object till
- it finds the child with the specified name.
+ Get the actual class to instanciate for this XML element
- @param name: The name to search for
- @param childType: The type of object to search for, if None then any type
- will match.
- @return: The child with the matching name, or None if child not found
+ @returns: class to be used for this XML element
"""
- for child in self._children:
- if child.name == name:
- if childType is None or child._type == childType:
- return child
-
- return None
-
- def findChildOfType(self, childType, includeSelf=1, allowAllChildren=0):
- """
- Moves downward though the children of an object till
- it finds the child of the specified type
-
- """
-
- if includeSelf and self._type == childType:
- return self
-
- for child in self._children:
- if child._type == childType:
- return child
-
- if allowAllChildren:
- for child in self._children:
- o = child.findChildOfType(childType, 0, 1)
- if o:
- return o
-
- return None
-
-
- def findChildrenOfType(self, childType, includeSelf=1, allowAllChildren=0):
- """
- find all children of a specific type
- """
- rs = []
-
- if includeSelf and self._type == childType:
- rs += [self]
-
- for child in self._children:
- if child._type == childType:
- rs += [child]
-
- if allowAllChildren:
- for child in self._children:
- try:
- rs += child.findChildrenOfType(childType, 0, 1)
- except AttributeError:
- pass # not all children will be GObj and support that function
-
- return rs
-
-
- def getDescription(self):
- """
- Return a useful description of the object.
- Currently used by GNUe Designer.
- """
- if hasattr(self, '_description'):
- return self._description
- elif hasattr(self, 'name'):
- return self.name + " (%s)" % self._type[2:]
- else:
- return self._type[2:] + " (%s)" % self._type[2:]
-
- # ===========================================================================
- # Dictionary-style access to GObject attributes (namespace-safe)
- # ===========================================================================
- """
- This is the method of attribute access used by Designer and Reports.
- For example. if foo is a GObject, then the following are equivalent:
- foo.required = 'Y'
- foo['required'] = 'Y'
-
- The advantage of this method, however, is when namespaces are used
- in the GObj XML document (i.e., reports). e.g., :
- foo['Char:x'] = 1
- foo['Char:y'] = 2
- These don't have a clean equivalent using the .attribute method.
- (Though, technically, a tool could access foo.Char__x, but that
- should be considered bad style.)
-
- Eventually, .attribute style access should probably be deprecated,
- so we can clean up the python namespaces of GObjects. (i.e., we could
- keep all XML-storable attributes in one dict instead of in the
- namespace __dict__.
- """
- def __getitem__(self, key):
- return self.__dict__[key.replace(':', '__')]
-
- def __setitem__(self, key, value):
- return self._setItemHook(key.replace(':', '__'), value)
-
- def _setItemHook(self, key, value):
- """
- This bit of nastiness is here to let GNUe Designer
- capture the setting of GObject properties. This is
- primarily used in the wizard system so Designer
- can act in real time as a wizard sets a document's
- properties.
-
- I.e., if a wizard sets::
- field['width'] = 10
-
- Designer can immediately changed the visual width
- of the field as displayed on screen.
- """
- self.__dict__[key] = value
-
-
-#
-# ParserMultiplexor
-#
-# When a GParser's BaseClass needs to be dependent upon
-# an attribute, the tool can use a customized ParserMultiplexor,
-# overwriting the getClass method.
-#
-# e.g., assume we have an xml tag 'goblin', that
-# corresponds to a GObj-based class Goblin. However,
-# if <goblin style="boo"> we really need a BooGoblin
-# object or if <goblin style="foo"> then we need a
-# FooBoblin object, then the a GoblinPlexor would
-# define getClass as:
-#
-# def getClass(self):
-# if self.style == 'boo':
-# return BooGoblin
-# elif self.style == 'foo':
-# return FooGoblin
-# else:
-# return Goblin
-#
-class ParserMultiplexor(ParserObj):
-
- def _buildObject(self):
- newObj = self.getClass()(None)
- for attr, value in self.__dict__.items():
- if attr not in ('_buildObject', 'getClass') and attr[:2] != '__':
- newObj.__dict__[attr] = value
-
- parent = self.getParent ()
- if parent:
- parent._children [parent._children.find (self)] = newObj
- return newObj._buildObject (self)
-
-
- # This should return a GObj-based class
- def getClass(self):
raise "Virtual method not implemented"
@@ -632,6 +604,10 @@
class GUndividedCollection (GObj):
"""
+ GUndividedCollection implements a collection class where the children in a
+ diff () won't get divided. Example: A primary key definition can contain
+ multiple primary key fields. If a primary key definition differs from another
+ one, it's fields must be kept as a union.
"""
#
----------------------------------------------------------------------------
@@ -649,7 +625,21 @@
#
----------------------------------------------------------------------------
def diff (self, goal, maxIdLength):
+ """
+ Build an object tree representing the difference between two object trees.
+ @param goal: L{ParserObj} tree to compare this object's tree to.
+ @param maxIdLength: if defined, use only up to maxIdLength characters of
+ the object name to check for identity.
+ @returns: L{ParserObj} tree representing the difference. Every object in
+ this tree has an additional attribute B{_action} which can contain one of
+ the following values:
+
+ * add: the object is only available in the 'goal' tree
+ * change: the object is avaialable in both trees, but differs
+ * remove: the object is only available in the 'source' tree
+ """
+
result = ParserObj.diff (self, goal, maxIdLength)
if result is not None:
@@ -680,18 +670,49 @@
# =============================================================================
-# Convenience class for the GObject .iterator() method
+# Convenience class for the GObject .iterator () method
# =============================================================================
+
class _GObjectIterator:
- def __init__(self, set):
- self.stack = set[:]
+ """
+ Convenience class for L{GObj.iterator} method providing an iterator over a
+ given set of L{GObj} instances (children).
+ """
- def __iter__(self):
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, set):
+
+ self.stack = set [:]
+
+
+ # ---------------------------------------------------------------------------
+ # Return the iterator object
+ # ---------------------------------------------------------------------------
+
+ def __iter__ (self):
+ """
+ @returns: the iterator object itself.
+ """
+
return self
- def next(self):
+
+ # ---------------------------------------------------------------------------
+ # Get the next item
+ # ---------------------------------------------------------------------------
+
+ def next (self):
+ """
+ Return the next item from the container.
+ @returns: the next item from the container
+ @raises StopIteration: If no more items are available in the container.
+ """
+
if self.stack:
- return self.stack.pop(0)
+ return self.stack.pop (0)
else:
raise StopIteration
Modified: trunk/gnue-common/src/definitions/GParser.py
===================================================================
--- trunk/gnue-common/src/definitions/GParser.py 2005-11-11 18:27:31 UTC
(rev 8095)
+++ trunk/gnue-common/src/definitions/GParser.py 2005-11-15 13:35:43 UTC
(rev 8096)
@@ -1,6 +1,9 @@
+# GNU Enterprise Common Library - GNUe XML object definitions - XML Parser
#
-# This file is part of GNU Enterprise.
+# Copyright 2001-2005 Free Software Foundation
#
+# This file is part of GNU Enterprise
+#
# GNU Enterprise is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
@@ -16,18 +19,15 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000-2005 Free Software Foundation
-#
-# FILE:
-# GParser.py
-#
-# DESCRIPTION:
+# $Id: $
+
"""
Class that contains a SAX2-based XML processor for GNUe
"""
-# NOTES:
-#
+__all__ = ['MarkupError', 'loadXMLObject', 'normalise_whitespace',
+ 'xmlHandler', 'GImportItem', 'GImport']
+
import sys, copy, types
from gnue.common.definitions.GObjects import GObj
from gnue.common.definitions.GRootObj import GRootObj
@@ -38,6 +38,7 @@
from xml.sax.handler import property_lexical_handler
from xml.sax import saxutils
import xml.sax
+
except ImportError:
print """
This GNUe tool requires pythons XML module be installed.
@@ -58,11 +59,11 @@
from gnue.common.definitions.GParserHelpers import GContent, GComment
-#######################################################
-#
-# Error classed raised for markup errors
-#
-class MarkupError(errors.ApplicationError):
+# =============================================================================
+# Exceptions
+# =============================================================================
+
+class MarkupError (errors.ApplicationError):
def __init__ (self, message, url = None, line = None):
errors.ApplicationError.__init__ (self, message)
text = [message]
@@ -78,34 +79,30 @@
self.detail = string.join (text, os.linesep)
-#######################################################
-#
-# loadXMLObject
-#
-# This method loads an object from an XML file and
-# returns that object. If initialize is 1 (default),
-# then the object is initialized and ready to go.
-# Setting initialize to 0 is useful for a design
-# environment where the object is not actually
-# being used, but simply loaded as a document.
-#
-# "attributes" is a dictionary containing extra
-# attributes that should be attached to this object.
-#
-# e.g., if attributes={myproperty:[0,1,2]}, then
-# before the object is initialized or returned,
-# object.myproperty == [0,1,2].
-#
-#######################################################
+# -----------------------------------------------------------------------------
+# Build an object from a XML stream
+# -----------------------------------------------------------------------------
-def loadXMLObject(stream, handler, rootType, xmlFileType,
- initialize=True, attributes={}, initParameters={}, url = None):
+def loadXMLObject (stream, handler, rootType, xmlFileType,
+ initialize = True, attributes = {}, initParameters = {}, url = None):
+ """
+ This method loads an object from a XML stream and returns that object. If
+ initialize is True (default), then the object is initialized and ready to go.
+ Setting initialize to 0 is useful for a design environment where the object
+ is not actually being used, but simply loaded as a document.
+ "attributes" is a dictionary containing extra attributes that should be
+ attached to this object.
+
+ e.g., if attributes={myproperty:[0,1,2]}, then before the object is
+ initialized or returned, object.myproperty == [0,1,2].
+ """
+
# Create a parser
- parser = xml.sax.make_parser()
+ parser = xml.sax.make_parser ()
# Set up some namespace-related stuff for the parsers
- parser.setFeature(xml.sax.handler.feature_namespaces, 1)
+ parser.setFeature (xml.sax.handler.feature_namespaces, 1)
# Allow for parameter external entities
## Does not work with expat!!! ##
@@ -125,13 +122,13 @@
dh.url = url
dh.parser = parser
- dh.initValidation()
+ dh.initValidation ()
# Tell the parser to use our handler
- parser.setContentHandler(dh)
+ parser.setContentHandler (dh)
try:
- parser.setProperty(property_lexical_handler, dh)
+ parser.setProperty (property_lexical_handler, dh)
except Exception, e:
print e
@@ -141,7 +138,7 @@
except xml.sax.SAXParseException, e:
raise MarkupError, (errors.getException () [2], url, e.getLineNumber ())
- object = dh.getRoot()
+ object = dh.getRoot ()
if not object:
tmsg = u_("Error loading %s: empty definition file") % (xmlFileType)
@@ -155,7 +152,7 @@
'got' : object._type}
raise MarkupError, (tmsg, url)
- object._rootComments = dh.getRootComments()
+ object._rootComments = dh.getRootComments ()
dh.finalValidation ()
@@ -167,66 +164,67 @@
#
#object.__dict__.update(attributes)
- object.walk(addAttributesWalker,attributes=attributes)
+ object.walk (__addAttributesWalker, attributes = attributes)
if initialize:
- assert gDebug (7, "Initializing the object tree starting at %s" %(object))
- object.phaseInit(dh._phaseInitCount)
+ assert gDebug (7, "Initializing the object tree starting at %s" % (object))
+ object.phaseInit (dh._phaseInitCount)
# Break the cyclic reference in the content handler, so garbage collection is
# able to collect it
dh.parser = None
return object
-#######################################################
-#
-# addAttributesWalker
-#
-#######################################################
-def addAttributesWalker(object, attributes={}):
- if isinstance(object,GRootObj):
- object.__dict__.update(attributes)
+# -----------------------------------------------------------------------------
-#######################################################
-#
-# normalise_whitespace
-#
-# Remove redundant whitespace from a string ( from xml-howto )
-#
-#######################################################
-def normalise_whitespace(text):
- return string.join( string.split(text), ' ')
+def __addAttributesWalker (object, attributes = {}):
+ if isinstance (object, GRootObj):
+ object.__dict__.update (attributes)
-def default(attrs, key, default):
- try:
- return attrs[key]
- except KeyError:
- return default
+# ---------------------------------------------------------------------------
+# Remove redundant whitespace characters from a string
+# ---------------------------------------------------------------------------
-#######################################################
-#
-# xmlHandler
-#
-# This class is called by the XML parser to
-# process the xml file.
-#
-#######################################################
-class xmlHandler(xml.sax.ContentHandler):
+def normalise_whitespace (text):
+ """
+ Remove redundant whitespace characters from a string.
- # Set to default namespace (which would be dropped)
- # i.e., if default namespace is "Foo", then <Foo:test> would
- # just be processed as <test>.
- default_namespace = None
+ @param text: string to remove redundant whitespaces (space, tabs, ...)
+ @returns: normalized string
+ """
- # Drop any elements that have a namespaces we don't know about?
+ return ' '.join (text.split ())
+
+
+# =============================================================================
+# XML Content handler
+# =============================================================================
+
+class xmlHandler (xml.sax.ContentHandler):
+ """
+ This class is used by the XML parser to process the XML file.
+
+ @cvar default_namespace: The default namespace (which would be dropped), i.e.
+ if the default namespace is 'Foo', then <Foo:test> would just be processed
+ as <test>.
+ @cvar ignore_unknown_namespaces: If set to True, any elements that have an
+ unknown namespace will be dropped.
+ """
+
+ default_namespace = None
ignore_unknown_namespaces = False
- def __init__(self):
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self):
+
self.xmlElements = {}
# This is a hack, currently used only by GRPassThru
@@ -236,83 +234,115 @@
self.xmlNamespaceAttributesAsPrefixes = False
# Internal stuff
- self.xmlStack = []
- self.nameStack = []
- self.bootstrapflag = False
- self.uniqueIDs = {}
- self.root = None
- self._phaseInitCount = 0
+ self.xmlStack = []
+ self.nameStack = []
+ self.bootstrapflag = False
+ self.uniqueIDs = {}
+ self.root = None
+ self.url = None
+ self.doImportLayoutParser = True
- self._requiredTags = []
+ self._phaseInitCount = 0
+ self._requiredTags = []
self._singleInstanceTags = []
- self._tagCounts = {}
- self.url = None
- self._rootComments = []
- self.doImportLayoutParser = True
+ self._tagCounts = {}
+ self._rootComments = []
- #
+
+ # ---------------------------------------------------------------------------
# Called by client code to get the "root" node
- #
- def getRoot(self):
+ # ---------------------------------------------------------------------------
+
+ def getRoot (self):
+ """
+ @returns: the root node of the object tree
+ """
+
return self.root
- #
+
+ # ---------------------------------------------------------------------------
# Builds structures need to verify requirements in the file
- #
- def initValidation(self):
- #
- # Build list of tags along with a list of
- # require tags
- #
- for element in self.xmlElements.keys():
- self._tagCounts[element] = 0
+ # ---------------------------------------------------------------------------
+
+ def initValidation (self):
+ """
+ Update some statistics about the elements in use. All 'required' elements
+ will be added to the sequence L{_requiredTags} and all elements having
+ a True value set for 'SingleInstance' will be added to the sequence
+ L{_singleInstanceTags}. Additionally the tag-counter dictionary will
+ be reset.
+ """
+
+ for element in self.xmlElements:
+ self._tagCounts [element] = 0
try:
- if self.xmlElements[element]['Required'] == 1:
- self._requiredTags.append(element)
+ if self.xmlElements [element]['Required']:
+ self._requiredTags.append (element)
+
except KeyError:
pass
try:
- if self.xmlElements[element]['SingleInstance'] == 1:
- self._singleInstanceTags.append(element)
+ if self.xmlElements [element]['SingleInstance']:
+ self._singleInstanceTags.append (element)
+
except KeyError:
pass
- def finalValidation(self):
+
+ # ---------------------------------------------------------------------------
+ # Final validation
+ # ---------------------------------------------------------------------------
+
+ def finalValidation (self):
+ """
+ Perform a final validation of the tags. Checks if all required tags are
+ really defined (via tag-counter dictionary).
+ """
+
# TODO: too simple a validation need to be per object instance
#for element in self._singleInstanceTags:
# if self._tagCounts[element] > 1:
- # raise MarkupError, _("File has multiple instances of <%s> when only
one allowed") % (element)
+ # raise MarkupError, \
+ # _("File has multiple instances of <%s> when only one allowed") \
+ # % (element)
for element in self._requiredTags:
- if self._tagCounts[element] < 1:
- tmsg = u_("File is missing required tag <%s>") % (element)
- raise MarkupError, (tmsg, self.url)
+ if self._tagCounts [element] < 1:
+ raise MarkupError, \
+ (u_("File is missing required tag <%s>") % element, self.url)
- #
- # Called by the internal SAX parser whenever
- # a starting XML element/tag is encountered.
- #
- def startElementNS(self, qtag, qname, saxattrs):
+ # ---------------------------------------------------------------------------
+ # Start of a XML element
+ # ---------------------------------------------------------------------------
- ns, name = qtag
- attrs = {}
+ def startElementNS (self, qtag, qname, saxattrs):
+ """
+ Called by the internal SAX parser whenever a starting XML tag is
+ encountered.
+ """
+
+ ns, name = qtag
+ attrs = {}
loadedxmlattrs = {}
- baseAttrs = {}
+ baseAttrs = {}
# Updating self.xmlElements with namespace specific parser definitions
# to let designer handle layout tags.
if self.default_namespace is None and self.doImportLayoutParser and ns:
try:
- gnue, tool, toolNS = ns.split(':')
- layoutParser = dyn_import('gnue.%s.adapters.filters.%s.LayoutParser' %
\
- (tool.lower(), toolNS))
- self.xmlElements.update(layoutParser.getXMLelements())
+ gnue, tool, toolNS = ns.split (':')
+ layoutParser = dyn_import ('gnue.%s.adapters.filters.%s.LayoutParser' \
+ % (tool.lower (), toolNS))
+ self.xmlElements.update (layoutParser.getXMLelements ())
self.default_namespace = ns
+
except:
self.doImportLayoutParser = False
- assert gDebug (7, "No parser defined for namespace %s, using PassThru
objects." % ns)
+ assert gDebug (7, "No parser defined for namespace %s, " \
+ "using PassThru objects." % ns)
if not ns or ns == self.default_namespace:
#
@@ -321,7 +351,7 @@
assert gDebug (7, "<%s>" % name)
try:
- baseAttrs = self.xmlElements[name].get('Attributes',{})
+ baseAttrs = self.xmlElements [name].get ('Attributes', {})
except KeyError:
raise MarkupError, \
@@ -331,47 +361,36 @@
xmlns = {}
- for qattr in saxattrs.keys():
+ for qattr in saxattrs.keys ():
attrns, attr = qattr
if attrns:
if not self.xmlNamespaceAttributesAsPrefixes:
tmsg = _("Unexpected namespace on attribute")
raise MarkupError, (tmsg, self.url, self.parser.getLineNumber ())
- prefix = attrns.split(':')[-1]
- attrs[prefix + '__' + attr] = saxattrs[qattr]
- xmlns[prefix] = attrns
+ prefix = attrns.split (':') [-1]
+ attrs [prefix + '__' + attr] = saxattrs [qattr]
+ xmlns [prefix] = attrns
- loadedxmlattrs[attr] = saxattrs[qattr]
+ loadedxmlattrs [attr] = saxattrs [qattr]
else:
-
# Typecasting, anyone? If attribute should be int, make it an int
try:
- attrs [attr] = baseAttrs [attr].get ('Typecast',
GTypecast.text)(saxattrs[qattr])
- loadedxmlattrs[attr] = attrs[attr]
+ typecast = baseAttrs [attr].get ('Typecast', GTypecast.text)
+ attrs [attr] = typecast (saxattrs [qattr])
+ loadedxmlattrs [attr] = attrs [attr]
+
except KeyError:
raise MarkupError, \
(u_('Error processing <%(tagname)s> tag [I do not '
'recognize the "%(attribute)s" attribute]') \
- % {'tagname': name,
- 'attribute': attr}, self.url, self.parser.getLineNumber ())
+ % {'tagname': name, 'attribute': attr},
+ self.url, self.parser.getLineNumber ())
- # this error shouldn't occure anymore
- #except UnicodeError:
- # tmsg = _('Error processing <%s> tag [Encoding error: invalid
character in "%s" attribute;]')\
- # % (name, attr)
- # raise MarkupError, tmsg
-
- #except StandardError, msg:
- # raise
- # tmsg = _('Error processing <%s> tag [invalid type for "%s"
attribute; value is "%s"]')\
- # % (name, attr, saxattrs[qattr])
- # raise MarkupError, tmsg
-
# If this attribute must be unique, check for duplicates
- if baseAttrs[attr].get('Unique',0): # default
(baseAttrs[attr],'Unique',0):
- if self.uniqueIDs.has_key('%s' % (saxattrs[qattr])):
+ if baseAttrs [attr].get ('Unique', False):
+ if self.uniqueIDs.has_key ('%s' % (saxattrs [qattr])):
tmsg = u_('Error processing <%(tag)s> tag ["%(attribute)s" '
'attribute should be unique; duplicate value is '
'"%(duplicate)s"]') \
@@ -380,65 +399,64 @@
'duplicate': saxattrs [qattr]}
raise MarkupError, (tmsg, self.url, self.parser.getLineNumber ())
- # FIXME: If we really want to have a working 'Unique'-Attribute, we
- # would add the following line. But this would break forms atm.
- # self.uniqueIDs ["%s" % saxattrs [qattr]] = True
+ self.uniqueIDs ["%s" % saxattrs [qattr]] = True
- for attr in baseAttrs.keys():
+ for attr in baseAttrs:
try:
- if not attrs.has_key(attr):
-
+ if not attr in attrs:
# Pull default values for missing attributes
- if baseAttrs[attr].has_key ('Default'):
- attrs[attr] = baseAttrs[attr].get('Typecast', GTypecast.text)
(baseAttrs[attr]['Default'])
+ if 'Default' in baseAttrs [attr]:
+ typecast = baseAttrs [attr].get ('Typecast', GTypecast.text)
+ attrs [attr] = typecast (baseAttrs [attr]['Default'])
# Check for missing required attributes
- elif baseAttrs[attr].get('Required', False):
- tmsg = u_('Error processing <%(tagname)s> tag [required
attribute '
- '"%(attribute)s" not present]') \
- % {'tagname' : name,
- 'attribute': attr}
- raise MarkupError, (tmsg, self.url, self.parser.getLineNumber ())
- except (AttributeError, KeyError), msg:
- raise errors.SystemError, _(
- 'Error in GParser xmlElement definition for %s/%s'
- ) % (name, attr) + '\n' + str(msg)
+ elif baseAttrs [attr].get ('Required', False):
+ tm = u_('Error processing <%(tagname)s> tag [required attribute '
+ '"%(attribute)s" not present]') \
+ % {'tagname': name, 'attribute': attr}
+ raise MarkupError, (tm, self.url, self.parser.getLineNumber ())
- attrs['_xmlnamespaces'] = xmlns
+ except (AttributeError, KeyError), msg:
+ raise errors.SystemError, \
+ u_("Error in GParser xmlElement definition for %(tag)s/%(attr)s"
+ "\n%(message)s") \
+ % {'tag': name, 'attr': attr, 'message': msg}
+ attrs ['_xmlnamespaces'] = xmlns
+
if self.bootstrapflag:
- if self.xmlStack[0] != None:
- object = self.xmlElements[name]['BaseClass'](self.xmlStack[0])
+ if self.xmlStack [0] is not None:
+ object = self.xmlElements [name]['BaseClass'] (self.xmlStack [0])
else:
- object = self.xmlElements[name]['BaseClass']()
+ object = self.xmlElements [name]['BaseClass'] ()
self.root = object
self.bootstrapflag = 1
try:
- self._tagCounts[name] += 1
+ self._tagCounts [name] += 1
+
except KeyError:
pass
- object._xmltag = name
- object._xmlnamespace = ns
- object._listedAttributes = loadedxmlattrs.keys()
+ object._xmltag = name
+ object._xmlnamespace = ns
+ object._listedAttributes = loadedxmlattrs.keys ()
elif self.xmlMasqueradeNamespaceElements:
#
# namespace qualifier and we are masquerading
#
-
assert gDebug (7, "<%s:%s>" % (ns,name))
- for qattr in saxattrs.keys():
+ for qattr in saxattrs:
attrns, attr = qattr
+ attrs [attr] = saxattrs [qattr]
+ loadedxmlattrs [attr] = saxattrs [qattr]
- attrs[attr] = saxattrs[qattr]
- loadedxmlattrs[attr] = saxattrs[qattr]
+ try:
+ object = self.xmlMasqueradeNamespaceElements (self.xmlStack [0])
- try:
- object = self.xmlMasqueradeNamespaceElements(self.xmlStack[0])
except IndexError:
tmsg = u_("Error processing <%(namespace)s:%(name)s> tag: root "
"element needs to be in default namespace") \
@@ -446,277 +464,372 @@
'name' : name}
raise MarkupError, (tmsg, self.url, self.parser.getLineNumber ())
- object._xmltag = name
- object._xmlnamespace = ns
- object._listedAttributes = loadedxmlattrs.keys()
+ object._xmltag = name
+ object._xmlnamespace = ns
+ object._listedAttributes = loadedxmlattrs.keys ()
elif self.ignore_unknown_namespaces:
- self.xmlStack.insert(0, None)
- self.nameStack.insert(0, None)
+ self.xmlStack.insert (0, None)
+ self.nameStack.insert (0, None)
+
return
+
else:
#
# namespace qualifier and we are not masquerading
#
- tmsg = u_("WARNING: Markup includes unsupported namespace '%s'." ) %
(ns)
+ tmsg = u_("WARNING: Markup includes unsupported namespace '%s'.") % ns
raise MarkupError, (tmsg, self.url, self.parser.getLineNumber ())
- # Save the attributes loaded from XML file
- # (i.e., attributes that were not defaulted)
+ # Save the attributes loaded from XML file (i.e., attributes that were not
+ # defaulted)
object._loadedxmlattrs = loadedxmlattrs
# We make the url of the xml-stream and the line number of the element
# available to the instance (for later error handling)
- object._lineNumber = self.parser.getLineNumber ()
- object._url = self.url
+ object._lineNumber = self.parser.getLineNumber ()
+ object._url = self.url
# Set the attributes
- object.__dict__.update(attrs)
+ object.__dict__.update (attrs)
- self.xmlStack.insert(0, object)
- self.nameStack.insert(0, name)
+ self.xmlStack.insert (0, object)
+ self.nameStack.insert (0, name)
# processing trigger/procedure code from external files
- for qattr in saxattrs.keys():
+ for qattr in saxattrs.keys ():
attrns, attr = qattr
if baseAttrs.has_key ('file') and attr == 'file':
- textEncoding=gConfig('textEncoding')
- handle = openResource(attrs[attr])
- text = handle.read().decode(textEncoding)
- handle.close()
+ # FIXME: find a better way to handle encoding of external resources
+ textEncoding = gConfig('textEncoding')
+ handle = openResource (attrs [attr])
+ text = handle.read ().decode (textEncoding)
+ handle.close ()
- if self.xmlStack[0] != None:
- GContent(self.xmlStack[0], text)
+ if self.xmlStack [0] != None:
+ GContent (self.xmlStack [0], text)
- #
- # Called by the internal SAX parser whenever
- # text (not part of a tag) is encountered.
- #
- def characters(self, text):
+
+
+ # ---------------------------------------------------------------------------
+ # Process text which is not part of a tag (=contents)
+ # ---------------------------------------------------------------------------
+
+ def characters (self, text):
+ """
+ Called by the internal SAX parser whenever text (not part of a tag) is
+ encountered.
+ """
- if self.xmlStack[0] != None:
-
+ if self.xmlStack [0] != None:
# Masqueraging namespace elements, then keep content
xmlns = self.xmlMasqueradeNamespaceElements and \
- isinstance(self.xmlStack[0],self.xmlMasqueradeNamespaceElements)
+ isinstance (self.xmlStack [0], self.xmlMasqueradeNamespaceElements)
# Should we keep the text?
- if xmlns or self.xmlElements[self.nameStack[0]].get('MixedContent',0):
-
+ if xmlns or self.xmlElements [self.nameStack [0]].get('MixedContent', 0):
if xmlns or
self.xmlElements[self.nameStack[0]].get('KeepWhitespace',0):
- GContent(self.xmlStack[0], text)
+ GContent (self.xmlStack [0], text)
else:
# Normalize
- if len(string.replace(string.replace(string.replace(text,'
',''),'\n',''),'\t','')):
+ if len (text.strip ()):
text = normalise_whitespace (text)
else:
text = ""
- if len(text):
- GContent(self.xmlStack[0], text)
+ if len (text):
+ GContent (self.xmlStack [0], text)
- #
- # Called by the internal SAX parser whenever
- # an ending XML tag/element is encountered.
- #
- def endElementNS(self, qtag, qname):
+
+ # ---------------------------------------------------------------------------
+ # End of a XML tag encountered
+ # ---------------------------------------------------------------------------
+
+ def endElementNS (self, qtag, qname):
+ """
+ Called by the internal SAX parser whenever an ending XML tag/element is
+ encountered.
+ """
+
ns, name = qtag
- self.nameStack.pop(0)
- child = self.xmlStack.pop(0)
+ self.nameStack.pop (0)
+ child = self.xmlStack.pop (0)
if not child:
return
- inits = child._buildObject()
+ inits = child._buildObject ()
self._phaseInitCount = (inits != None and inits > self._phaseInitCount \
and inits or self._phaseInitCount)
assert gDebug (7, "</%s>" % name)
- # lexical handler stuff
- def comment(self, text):
+ # ---------------------------------------------------------------------------
+ # Get the root comments sequence
+ # ---------------------------------------------------------------------------
+
+ def getRootComments (self):
+ """
+ @returns: sequence of comment tags given before the root node
+ """
+
+ return self._rootComments
+
+
+ # ---------------------------------------------------------------------------
+ # Lexical handler stuff
+ # ---------------------------------------------------------------------------
+
+ def comment (self, text):
+
if self.root is None:
- self._rootComments.append(text)
+ self._rootComments.append (text)
else:
- if self.xmlStack[0] != None:
- GComment(self.xmlStack[0], text)
+ if self.xmlStack [0] != None:
+ GComment (self.xmlStack [0], text)
- def startCDATA(self):
+ # ---------------------------------------------------------------------------
+
+ def startCDATA (self):
pass
- def endCDATA(self):
+ # ---------------------------------------------------------------------------
+
+ def endCDATA (self):
pass
- def startDTD(self, name, public_id, system_id):
+ # ---------------------------------------------------------------------------
+
+ def startDTD (self, name, public_id, system_id):
pass
- def endDTD(self):
+ # ---------------------------------------------------------------------------
+
+ def endDTD (self):
pass
- def startEntity(self, name):
+ # ---------------------------------------------------------------------------
+
+ def startEntity (self, name):
pass
- def endEntity(self, name):
+ # ---------------------------------------------------------------------------
+
+ def endEntity (self, name):
pass
- def getRootComments(self):
- return self._rootComments
-class GImportItem(GObj):
- def __init__(self, parent=None, type="GCImport-Item"):
- GObj.__init__(self, parent, type=type)
+# =============================================================================
+# Base class for importable items
+# =============================================================================
+
+class GImportItem (GObj):
+ """
+ This class is used for loading importable items from external resources.
+ """
+
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, parent = None, type = "GCImport-Item"):
+
+ GObj.__init__ (self, parent, type = type)
+
self._loadedxmlattrs = {} # Set by parser
- self._inits = [self.primaryInit]
- self._xmlParser = self.findParentOfType(None)._xmlParser
+ self._inits = [self.__primaryInit]
+ self._xmlParser = self.findParentOfType (None)._xmlParser
- def _buildObject(self):
- if hasattr(self,'_xmltag'):
+
+ # ---------------------------------------------------------------------------
+ # Prepare the type or the importclass for the object
+ # ---------------------------------------------------------------------------
+
+ def _buildObject (self):
+ """
+ After the parser has built the object determine either the apropriate type
+ or the importclass for the object. This will be needed by the phase-init.
+
+ @returns: number of phase initializations needed by this object
+ """
+
+ if hasattr (self, '_xmltag'):
self._type = 'GC%s' % self._xmltag
- if not hasattr(self,'_importclass'):
- self._importclass = self._xmlParser\
- .getXMLelements()[string.lower(self._type[9:])]['BaseClass']
- return GObj._buildObject(self)
- def primaryInit(self):
- #
- # Open the library and convert it into objects
- #
- handle = openResource(self.library)
- parent = self.findParentOfType (None)
+ if not hasattr (self, '_importclass'):
+ item = self._type [9:].lower ()
+ self._importclass = self._xmlParser.getXMLelements () [item]['BaseClass']
- # Let the parent provide it's instance either as _app or _instance
- if hasattr (parent, '_instance'):
- instance = parent._instance
- elif hasattr (parent, '_app'):
- instance = parent._app
- else:
- instance = None
+ return GObj._buildObject (self)
- form = self._xmlParser.loadFile (handle, instance, initialize = 0)
- handle.close ()
- id = 'id'
- if hasattr(self,'name'):
- id = 'name'
- #
- # Configure the imported object, assign as a child of self
- #
- rv = self.__findImportItem(self, form, id)
- if rv != None:
- rv.setParent (self)
- rv._IMPORTED = 1
- self._children.append(rv)
- #
- # transfer attributes reassigned during the import
- #
- for key in self._loadedxmlattrs.keys():
- if key[0] != '_':
- rv.__dict__[key] = self._loadedxmlattrs[key]
- assert gDebug (7, ">>> Moving %s" % key)
- rv._buildObject()
- else:
- raise MarkupError, \
- (u_("Unable to find an importable object named %(name)s in "
- "%(library)s") \
- % {'name' : self.name, 'library': self.library},
- self.url)
- #
- # __findImportItem
- #
- # finds the item in the object tree with the
- # same name and instance type
- #
- def __findImportItem(self, find, object, id):
- if isinstance(object, find._importclass) and \
- hasattr(object, id) and \
- object.__dict__[id] == find.__dict__[id]:
+ # ---------------------------------------------------------------------------
+ # Phase I init
+ # ---------------------------------------------------------------------------
+
+ def __primaryInit (self):
+
+ # Open the library and convert it into objects
+ handle = openResource (self.library)
+ parent = self.findParentOfType (None)
+
+ # Let the parent provide it's instance either as _app or _instance
+ if hasattr (parent, '_instance'):
+ instance = parent._instance
+ elif hasattr (parent, '_app'):
+ instance = parent._app
+ else:
+ instance = None
+
+ form = self._xmlParser.loadFile (handle, instance, initialize = 0)
+ handle.close ()
+
+ id = hasattr (self, 'name') and 'name' or 'id'
+
+ # Configure the imported object, assign as a child of self
+ rv = self.__findImportItem (self, form, id)
+ if rv is not None:
+ rv._IMPORTED = True
+ rv.setParent (self)
+ self.addChild (rv)
+
+ # transfer attributes reassigned during the import
+ for key in [k for k in self._loadedxmlattrs.keys () if k [0] != '_']:
+ rv.__dict__ [key] = self._loadedxmlattrs [key]
+ assert gDebug (7, ">>> Moving %s" % key)
+
+ rv._buildObject ()
+
+ else:
+ raise MarkupError, \
+ (u_("Unable to find an importable object named %(name)s in "
+ "%(library)s") % {'name' : self.name, 'library': self.library},
+ self.url)
+
+
+ # ---------------------------------------------------------------------------
+ # find an item of a given name and type
+ # ---------------------------------------------------------------------------
+
+ def __findImportItem (self, find, object, id):
+
+ if isinstance (object, find._importclass) and \
+ hasattr (object, id) and \
+ object.__dict__ [id] == find.__dict__ [id]:
return object
- elif hasattr(object,'_children'):
+
+ elif hasattr (object,'_children'):
rv = None
for child in object._children:
- rv = self.__findImportItem(find, child, id)
+ rv = self.__findImportItem (find, child, id)
if rv:
break
+
return rv
+
else:
return None
-class GImport(GObj):
- def __init__(self, parent=None):
- GObj.__init__(self, parent, type="GCImport")
- self.library = ""
- self._form = None
- self._inits = [self.primaryInit]
- self._xmlParser = self.findParentOfType(None)._xmlParser
+# =============================================================================
+# Generic class for importable objects
+# =============================================================================
- def primaryInit(self):
- handle = openResource(self.library)
- form = self._xmlParser.loadFile(handle, self.findParentOfType(None)._app,
initialize=0)
- handle.close()
+class GImport (GObj):
- for attribute in self._loadedxmlattrs.keys():
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__(self, parent = None):
+
+ GObj.__init__ (self, parent, type = "GCImport")
+ self.library = ""
+ self._form = None
+ self._inits = [self.__primaryInit]
+ self._xmlParser = self.findParentOfType (None)._xmlParser
+
+
+ # ---------------------------------------------------------------------------
+ # Phase I initialization
+ # ---------------------------------------------------------------------------
+
+ def __primaryInit (self):
+
+ handle = openResource (self.library)
+ form = self._xmlParser.loadFile (handle,
+ self.findParentOfType (None)._app, initialize = False)
+ handle.close ()
+
+ for attribute in self._loadedxmlattrs.keys ():
if attribute != 'library':
- importAll = self._loadedxmlattrs[attribute] == "*"
- importNames =
string.split(string.replace(self._loadedxmlattrs[attribute],' ',''),',')
+ attr = self._loadedxmlattrs [attribute]
+ importAll = attr == "*"
+ importNames = attr.replace (' ', '').split (',')
- instanceType =
self._xmlParser.getXMLelements()[string.lower(attribute)]['BaseClass']
+ elements = self._xmlParser.getXMLelements ()
+ instanceType = elements [attribute.lower ()]['BaseClass']
- if importAll or len(importNames):
+ if importAll or len (importNames):
for child in form._children:
- if isinstance(child,instanceType) and \
+ if isinstance (child, instanceType) and \
(importAll or child.name in importNames):
child.setParent (self)
child._IMPORTED = 1
- self._children.append(child)
- child._buildObject()
+ self.addChild (child)
+ child._buildObject ()
-def buildImportableTags(rootTag, elements):
- #
- # Scans xml elements and looks for Importable = 1
- # Items with this set can be imported
- # If an object needs to be importable,
- # simply add its tag name to the tuple below
- # and make sure it has a "name" attribute
- # (otherwise we don't know how to reference
- # it in the imported file).
- #
- importElement = {'BaseClass': GImport,
- 'Attributes': {'library': {
- 'Required': 1,
- 'Typecast': GTypecast.name },
- },
- 'ParentTags': rootTag,
- }
- for key in elements.keys():
- if elements[key].has_key('Importable') and elements[key]['Importable']:
- name = "import-%s" % key
- copy._deepcopy_dispatch[types.FunctionType] = copy._deepcopy_atomic
- copy._deepcopy_dispatch[types.ClassType] = copy._deepcopy_atomic
- copy._deepcopy_dispatch[type(int)] = copy._deepcopy_atomic
+# -----------------------------------------------------------------------------
+# build importable tags
+# -----------------------------------------------------------------------------
- p = copy.deepcopy(elements[key])
- p['BaseClass'] = GImportItem
+def buildImportableTags (rootTag, elements):
+ """
+ Scans XML elements and looks for 'Importable' items. If an object needs to be
+ importable, simply add its tag name to the tuple below and make sure it has a
+ "name" attribute (otherwise we don't know how to reference it in the imported
+ file).
+ """
- if not p.has_key('Attributes'):
- p['Attributes'] = {}
+ importElement = {'BaseClass' : GImport,
+ 'Attributes': {'library': {
+ 'Required': True,
+ 'Typecast': GTypecast.name},
+ },
+ 'ParentTags': rootTag,
+ }
- p['Attributes']['library'] = {
- 'Required': 1,
+ for key in elements.keys ():
+ if elements [key].get ('Importable', False):
+ name = "import-%s" % key
+
+ copy._deepcopy_dispatch [types.FunctionType] = copy._deepcopy_atomic
+ copy._deepcopy_dispatch [types.ClassType] = copy._deepcopy_atomic
+ copy._deepcopy_dispatch [type (int)] = copy._deepcopy_atomic
+
+ p = copy.deepcopy (elements [key])
+ p ['BaseClass'] = GImportItem
+
+ if not p.has_key ('Attributes'):
+ p ['Attributes'] = {}
+
+ p ['Attributes']['library'] = {
+ 'Required': True,
'Typecast': GTypecast.name }
- p['MixedContent'] = 0
- p['Required'] = 0
- elements[name] = p
+ p ['MixedContent'] = False
+ p ['Required'] = False
- importElement['Attributes'][key] = {
- 'Typecast': GTypecast.name,
- 'Default': "" }
+ elements [name] = p
- if len(importElement['Attributes'].keys()):
- elements['import'] = importElement
- return elements
+ importElement ['Attributes'][key] = {'Typecast': GTypecast.name,
+ 'Default' : ""}
+
+ if importElement ['Attributes']:
+ elements ['import'] = importElement
+
+ return elements
Modified: trunk/gnue-common/src/definitions/GParserHelpers.py
===================================================================
--- trunk/gnue-common/src/definitions/GParserHelpers.py 2005-11-11 18:27:31 UTC
(rev 8095)
+++ trunk/gnue-common/src/definitions/GParserHelpers.py 2005-11-15 13:35:43 UTC
(rev 8096)
@@ -21,15 +21,35 @@
#
# $Id$
+"""
+Base classes for GNUe objects which can be represented as XML.
+"""
+
from xml.sax import saxutils
-from types import StringType
+from gnue.common.apps import errors
+__all__ = ['ParserObj', 'GLeafNode', 'GContent', 'GComment']
+
# =============================================================================
+# Exceptions
+# =============================================================================
+
+class AssignmentTypeError (errors.ApplicationError):
+ def __init__ (self, dst, source):
+ msg = u_("Cannot assign class '%(source)s' to class '%(dest)s'") \
+ % {'source': source.__class__, 'dest': dst.__class__}
+ errors.ApplicationError.__init__ (self, msg)
+
+
+# =============================================================================
# Base class for GParser objects
# =============================================================================
class ParserObj:
+ """
+ Base class for objects handled by a L{gnue.common.definitions.GParser}.
+ """
# ---------------------------------------------------------------------------
# Constructor
@@ -58,7 +78,7 @@
"""
Returns the immediate parent of an object instance in a GObj tree.
- @return: The parent of the object in the GObj tree.
+ @returns: The parent of the object in the GObj tree.
@rtype: any
"""
@@ -80,35 +100,36 @@
# ---------------------------------------------------------------------------
- # Return a compareable id of an object
+ # add an object to the list of children
# ---------------------------------------------------------------------------
- def _id_ (self, maxIdLength = None):
+ def addChild (self, child):
"""
- Return a compareable and identifying id of an object within a tree. Usually
- this is it's name (if available) or it's object type (as given in the
- constructor).
+ Add an object to the list of children
- @param maxIdLength: if not None only return up to maxIdLength characters.
- @return: id for the instance
+ @param child: The object to add.
+ @type child: L{ParserObj} derived class
"""
- if hasattr (self, 'name'):
- result = self.name.lower ()
- if maxIdLength is not None:
- result = result [:maxIdLength]
- else:
- result = self._type
+ self._children.append (child)
- return result
-
# ---------------------------------------------------------------------------
# Assign a given set of attributes from another instance
# ---------------------------------------------------------------------------
def assign (self, source, recursive = False):
"""
+ Assign all attributes from a given object to this one. If the recursive
+ option is given, all of the source's children will be I{duplicated} and
+ assigned to this object.
+
+ @param source: the L{ParserObj} instance to assign attributes from
+ @param recursive: if True, all children of source will be recursiveley
+ duplicated and assigned to this object
+
+ @raises AssignmentTypeError: if the source object is another class than
+ this object
"""
if self.__class__ != source.__class__:
@@ -139,6 +160,8 @@
def merge (self, other, maxIdLength = None):
"""
Incorporate all subtrees from the given object tree of this instances type.
+
+ @param other: L{ParserObj} tree to be merged into this object tree
"""
# First find objects of the same type in the other tree
@@ -168,6 +191,18 @@
def diff (self, goal, maxIdLength = None):
"""
+ Build an object tree representing the difference between two object trees.
+
+ @param goal: L{ParserObj} tree to compare this object's tree to.
+ @param maxIdLength: if defined, use only up to maxIdLength characters of
+ the object name to check for identity.
+ @returns: L{ParserObj} tree representing the difference. Every object in
+ this tree has an additional attribute B{_action} which can contain one of
+ the following values:
+
+ * add: the object is only available in the 'goal' tree
+ * change: the object is avaialable in both trees, but differs
+ * remove: the object is only available in the 'source' tree
"""
result = None
@@ -231,14 +266,273 @@
# ---------------------------------------------------------------------------
- # Set the diff-action for a given object
+ # Return a XML representation of the object
# ---------------------------------------------------------------------------
+ def dumpXML (self, lookupDict, treeDump = False, gap = " ",
+ xmlnamespaces = {}, textEncoding = '<locale>', stripPrefixes = None,
+ escape = True):
+ """
+ Return a XML representation of the object.
+
+ @param lookupDict: dictionary describing the XML entities, their
+ attributes and types
+ @param treeDump: if True, also include a XML representation of all
children
+ @param gap: string defining the current indentation level
+ @param xmlnamespaces: dictionary with the available XML namespaces
+ @param textEncoding: encoding used to transform string-type attributes into
+ unicode. If textEncoding is set to '<locale>' (default) it will be set to
+ the configuration variable 'textEncoding', i.e. from gnue.conf
+ @param stripPrefixes: a list of prefixes that will automatically be removed
+ from the objects type. This can be used to remove the GF from the start
+ of all the gnue-forms objects. If set to None (the default) then the
+ behaviour will be the old style which removes the first two characters
+ from the type.
+ @param escape: if set to True the resulting XML string should be escaped
+
+ @returns: a string with the object's XML representation
+ """
+
+ return self._dumpXML_ (lookupDict, treeDump, gap, xmlnamespaces,
+ textEncoding, stripPrefixes, escape)
+
+
+ # ---------------------------------------------------------------------------
+ # Find the first parent instance of a given type
+ # ---------------------------------------------------------------------------
+
+ def findParentOfType (self, parentType, includeSelf = True):
+ """
+ Moves upward though the parents of an object till it finds the parent of
+ the specified type.
+
+ @param parentType: type of the object to be found
+ @param includeSelf: if set to True, the search starts with this object
+ instead of the object's parent.
+
+ @returns: the first parent object of the given type or None if no such
+ object was found.
+ """
+
+ parentObject = includeSelf and self or self.__parent
+
+ while True:
+ if parentObject is None:
+ return None
+
+ elif parentObject._type == parentType:
+ return parentObject
+
+ # If passed a type of NONE it finds the top object in the tree
+ if not parentType and not parentObject.__parent:
+ return parentObject
+
+ parentObject = parentObject.__parent
+
+
+ # ---------------------------------------------------------------------------
+ # Find the first child object with a given name and type
+ # ---------------------------------------------------------------------------
+
+ def findChildNamed (self, name, childType = None):
+ """
+ Moves downward though the children of an object till it finds the child
+ with the specified name.
+
+ @param name: The name to search for
+ @param childType: The type of object to search for, if None then any type
+ will match.
+
+ @return: The child with the matching name, or None if child not found
+ """
+
+ for child in self._children:
+ if child.name == name:
+ if childType is None or child._type == childType:
+ return child
+
+ return None
+
+
+ # ---------------------------------------------------------------------------
+ # Find the first child of a given type
+ # ---------------------------------------------------------------------------
+
+ def findChildOfType (self, childType, includeSelf = True,
+ allowAllChildren = False):
+ """
+ Moves downward through the children of an object till it finds the child of
+ the specified type.
+
+ @param childType: type of the child to be searched for
+ @param includeSelf: if set to True, the search starts with this instance
+ @param allowAllChildren: if set to True, the search will be performed
+ recursive.
+
+ @returns: the first child of the requested type or None if no such object
+ is found.
+ """
+
+ if includeSelf and self._type == childType:
+ return self
+
+ for child in self._children:
+ if child._type == childType:
+ return child
+
+ if allowAllChildren:
+ for child in self._children:
+ o = child.findChildOfType (childType, False, True)
+ if o:
+ return o
+
+ return None
+
+
+ # ---------------------------------------------------------------------------
+ # Find children of a given type
+ # ---------------------------------------------------------------------------
+
+ def findChildrenOfType (self, childType, includeSelf = True,
+ allowAllChildren = False):
+ """
+ Find all children of a specific type.
+
+ @param childType: type of the objects to match
+ @param includeSelf: if set to True, the search will be started with this
+ instance.
+ @param allowAllChildren: if set to True, recursivley step down the object
+ tree and add all children of the requested type
+
+ @returns: sequence with all child objects matching the requested type
+ """
+
+ result = []
+ add = result.append
+ extend = result.extend
+
+ if includeSelf and self._type == childType:
+ add (self)
+
+ for child in self._children:
+ if child._type == childType:
+ add (child)
+
+ if allowAllChildren:
+ for child in self._children:
+ extend (child.findChildrenOfType (childType, False, True))
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Get a description for an object
+ # ---------------------------------------------------------------------------
+
+ def getDescription (self):
+ """
+ Return a useful description of the object. Currently used by GNUe Designer.
+ """
+
+ if hasattr (self, '_description'):
+ return self._description
+
+ elif hasattr (self, 'name'):
+ return "%s (%s)" % (self.name, self._type [2:])
+
+ else:
+ return "%s (%s)" % (self._type [2:], self._type [2:])
+
+
+ # ---------------------------------------------------------------------------
+ # Get the contents of all children of type GContent
+ # ---------------------------------------------------------------------------
+
+ def getChildrenAsContent (self):
+ """
+ Returns the content of any GContent objects that are children of this
+ object.
+
+ @returns: The contents of the children
+ """
+
+ result = ""
+
+ for child in self._children:
+ if isinstance (child, GContent):
+ result += child._content
+
+ elif isinstance (child, GBinary):
+ result += child.__data__
+
+ return result
+
+
+ # ===========================================================================
+ # Virtual functions
+ # ===========================================================================
+
+ def _id_ (self, maxIdLength = None):
+ """
+ Return a compareable and identifying id of an object within a tree. Usually
+ this is it's name (if available) or it's object type (as given in the
+ constructor).
+
+ @param maxIdLength: if not None only return up to maxIdLength characters.
+ @return: id for the instance
+ """
+
+ if hasattr (self, 'name'):
+ result = self.name.lower ()
+ if maxIdLength is not None:
+ result = result [:maxIdLength]
+ else:
+ result = self._type
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
+
def _diffActionWalker_ (self, obj, action):
+ """
+ Set the action attribute of a given object to the specified action.
+ @param obj: L{ParserObj} to set the action attribute
+ @param action: the action to be set
+ """
+
obj._action = action
+ # ---------------------------------------------------------------------------
+
+ def _dumpXML_ (self, lookupDict, treeDump, gap, xmlnamespaces, textEncoding,
+ stripPrefixes, escape):
+ """
+ Return a XML representation of the object.
+
+ @param lookupDict: dictionary describing the XML entities, their
+ attributes and types
+ @param treeDump: if True, also include a XML representation of all
children
+ @param gap: string defining the current indentation level
+ @param xmlnamespaces: dictionary with the available XML namespaces
+ @param textEncoding: encoding used to transform string-type attributes into
+ unicode. If textEncoding is set to '<locale>' (default) it will be set to
+ the configuration variable 'textEncoding', i.e. from gnue.conf
+ @param stripPrefixes: a list of prefixes that will automatically be removed
+ from the objects type. This can be used to remove the GF from the start
+ of all the gnue-forms objects. If set to None (the default) then the
+ behaviour will be the old style which removes the first two characters
+ from the type.
+ @param escape: if set to True the resulting XML string should be escaped
+
+ @returns: a string with the object's XML representation
+ """
+
+ raise NotImplementedError
+
+
# =============================================================================
# Mixin-class for leaf node objects
# =============================================================================
@@ -263,6 +557,9 @@
# =============================================================================
class GContent (ParserObj):
+ """
+ Class representing XML content.
+ """
# ---------------------------------------------------------------------------
# Constructor
@@ -271,7 +568,8 @@
def __init__ (self, parent, content = None):
ParserObj.__init__ (self, parent, '_content_')
- self._content = content
+ self._content = content
+ self._description = "(Content)"
# ---------------------------------------------------------------------------
@@ -279,6 +577,9 @@
# ---------------------------------------------------------------------------
def getEscapedContent (self):
+ """
+ @returns: The escaped contents of this object
+ """
return saxutils.escape (self._content)
@@ -288,53 +589,62 @@
# ---------------------------------------------------------------------------
def getContent (self):
+ """
+ @returns: The contents of this object
+ """
return self._content
# ---------------------------------------------------------------------------
- # Return a xml representation of the object
+ # Show a contents element within an (indented) tree
# ---------------------------------------------------------------------------
- def dumpXML (self, lookupDict, treeDump = None, gap = None,
- escape = 1, textEncoding = '<locale>', xmlnamespaces = {},
- stripPrefixes = None):
+ def showTree (self, indent = 0):
+ """
+ Show a contents element within an indented tree
+ """
- if textEncoding == '<locale>':
- textEncoding = gConfig ('textEncoding')
+ print ' ' * indent + 'GContent ' + `self._content`
- if type (self._content) == StringType:
- xmlString = '%s' % unicode (self._content, textEncoding)
- else:
- xmlString = self._content
- return escape and saxutils.escape (xmlString) or xmlString
-
-
# ---------------------------------------------------------------------------
- # Show a contents element within an (indented) tree
+ # Don't merge contents instances
# ---------------------------------------------------------------------------
- def showTree (self, indent = 0):
+ def merge (self, other):
+ """
+ Content objects cannot be merged together
+ """
- print ' ' * indent + 'GContent ' + `self._content`
+ return
# ---------------------------------------------------------------------------
- # Return a useful description of this object (used by designer clients)
+ # Implementation of virtual methods
# ---------------------------------------------------------------------------
- def getDescription (self):
+ def _dumpXML_ (self, lookupDict, treeDump, gap, xmlnamespaces, textEncoding,
+ stripPrefixes, escape):
+ """
+ Return a XML representation of the contents. If the contents is a plain
+ string (non unicode) it will be converted into unicode using the specified
+ encoding or (if set to '<locale>') using the encoding as defined by the
+ configuration variable 'textEncoding'. If the contents is of any other
+ type it will be returned as is.
- return "(Content)"
+ @returns: XML representation of the contents
+ """
+ if textEncoding == '<locale>':
+ textEncoding = gConfig ('textEncoding')
- # ---------------------------------------------------------------------------
- # Don't merge contents instances
- # ---------------------------------------------------------------------------
+ if isinstance (self._content, str):
+ xmlString = '%s' % unicode (self._content, textEncoding)
+ else:
+ xmlString = self._content
- def merge (self, other):
- return
+ return escape and saxutils.escape (xmlString) or xmlString
# =============================================================================
@@ -342,6 +652,9 @@
# =============================================================================
class GComment (ParserObj):
+ """
+ Class representing a comment within a XML tree.
+ """
# ---------------------------------------------------------------------------
# Constructor
@@ -352,14 +665,27 @@
ParserObj.__init__ (self, parent, '_comment_')
self._comment = comment
- def dumpXML (self, lookupDict, treeDump = None, gap = "",
- escape = 1, textEncoding = '<locale>', xmlnamespaces = {},
- stripPrefixes = None):
+ # ---------------------------------------------------------------------------
+ # Implementation of virtual methods
+ # ---------------------------------------------------------------------------
+
+ def _dumpXML_ (self, lookupDict, treeDump, gap, xmlnamespaces, textEncoding,
+ stripPrefixes, escape):
+ """
+ Return a XML representation of the comment. If the comment is a plain
+ string (non unicode) it will be converted into unicode using the specified
+ encoding or (if set to '<locale>') using the encoding as defined by the
+ configuration variable 'textEncoding'. If the comment is of any other
+ type it will be returned as is.
+
+ @returns: XML representation of the contents
+ """
+
if textEncoding == '<locale>':
textEncoding = gConfig ('textEncoding')
- if type (self._comment) == StringType:
+ if isinstance (self._comment, str):
xmlString = '%s' % unicode (self._comment, textEncoding)
else:
xmlString = self._comment
Modified: trunk/gnue-common/src/definitions/GRootObj.py
===================================================================
--- trunk/gnue-common/src/definitions/GRootObj.py 2005-11-11 18:27:31 UTC
(rev 8095)
+++ trunk/gnue-common/src/definitions/GRootObj.py 2005-11-15 13:35:43 UTC
(rev 8096)
@@ -1,65 +1,88 @@
+# GNU Enterprise Common Library - GNUe XML object definitions - Root Node
#
-# This file is part of GNU Enterprise.
+# Copyright 2001-2005 Free Software Foundation
#
-# GNU Enterprise is free software; you can redistribute it
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation; either
+# License as published by the Free Software Foundation; either
# version 2, or (at your option) any later version.
#
# GNU Enterprise is distributed in the hope that it will be
-# useful, but WITHOUT ANY WARRANTY; without even the implied
-# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
-# You should have received a copy of the GNU General Public
+# You should have received a copy of the GNU General Public
# License along with program; see the file COPYING. If not,
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000-2005 Free Software Foundation
-#
-#
-# FILE:
-# GRootObj.py
-#
-# DESCRIPTION:
-# Provides the base class that can optionally be used by root objects
-# in a GObj based tree.
-#
-# NOTES:
-#
+# $Id$
+"""
+Provides the base class that can optionally be used by root objects in a GObj
+based tree.
+"""
+__all__ = ['GRootObj']
+
from gnue.common.logic.NamespaceCore import GObjNamespace
from gnue.common.definitions.GObjects import GObj
-#
+from gnue.common.utils.FileUtils import dyn_import
+
+# =============================================================================
# GRootObj
-#
-#
-class GRootObj(GObj):
- def __init__(self, rootName, xmlElementCallback, xmlParser, *args, **parms):
- GObj.__init__(self,*args, **parms)
+# =============================================================================
+
+class GRootObj (GObj):
+
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, rootName, xmlElementCallback, xmlParser, *args, **parms):
+
+ GObj.__init__ (self, *args, **parms)
+
self._triggerNamespaceTree = None
- self._rname = rootName
- self.__xmlElementCallback = xmlElementCallback
- self._xmlParser = xmlParser
- self._xmlnamespaces = {}
- self._standardnamespaces = {}
- self._rootComments = []
+ self._rname = rootName
+
+ if isinstance (xmlParser, basestring):
+ self._xmlParser = dyn_import (xmlParser)
+ else:
+ self._xmlParser = xmlParser
+
+ self._xmlnamespaces = {}
+ self._standardnamespaces = {}
+ self._rootComments = []
# This will store any "global myVar" that the triggers execute.
self._globalRuntimeNamespace = {}
- def initTriggerSystem(self):
- self._triggerNamespaceTree = GObjNamespace(self,rootName=self._rname)
+ self.__xmlElementCallback = xmlElementCallback
- def dumpXML(self, lookupDict={}, treeDump=1, gap=" ", xmlnamespaces={},\
- textEncoding='<locale>', stripPrefixes=None):
- xmlElements = lookupDict
- xmlElements.update(self.__xmlElementCallback())
- return GObj.dumpXML(self, xmlElements, \
- treeDump, gap, xmlnamespaces=self._standardnamespaces, \
- textEncoding=textEncoding, stripPrefixes=stripPrefixes)
+ # ---------------------------------------------------------------------------
+ # Initialize the trigger system
+ # ---------------------------------------------------------------------------
+ def initTriggerSystem (self):
+ self._triggerNamespaceTree = GObjNamespace (self, rootName = self._rname)
+
+
+ # ---------------------------------------------------------------------------
+ # Get the object's XML code tree
+ # ---------------------------------------------------------------------------
+
+ def dumpXML (self, lookupDict = {}, treeDump = True, gap = " ",
+ xmlnamespaces= {}, textEncoding = '<locale>', stripPrefixes = None):
+
+ xmlElements = lookupDict
+ xmlElements.update (self.__xmlElementCallback ())
+
+ return GObj.dumpXML (self, xmlElements, treeDump, gap,
+ xmlnamespaces = self._standardnamespaces, textEncoding = textEncoding,
+ stripPrefixes = stripPrefixes)
Property changes on: trunk/gnue-common/src/definitions/GRootObj.py
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: trunk/gnue-common/src/definitions/__init__.py
===================================================================
--- trunk/gnue-common/src/definitions/__init__.py 2005-11-11 18:27:31 UTC
(rev 8095)
+++ trunk/gnue-common/src/definitions/__init__.py 2005-11-15 13:35:43 UTC
(rev 8096)
@@ -0,0 +1,26 @@
+# GNU Enterprise Common Library - GNUe XML object definitions
+#
+# Copyright 2001-2005 Free Software Foundation
+#
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
+
+"""
+GNUe object trees based on XML.
+"""
Property changes on: trunk/gnue-common/src/definitions/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: trunk/gnue-common/src/logic/GTrigger.py
===================================================================
--- trunk/gnue-common/src/logic/GTrigger.py 2005-11-11 18:27:31 UTC (rev
8095)
+++ trunk/gnue-common/src/logic/GTrigger.py 2005-11-15 13:35:43 UTC (rev
8096)
@@ -184,21 +184,22 @@
else:
return string.upper(self.type)
- #
- # dumpXML
- #
- #
- def dumpXML(self, lookupDict, treeDump=None, gap=None, xmlnamespaces={},
- textEncoding='<locale>', stripPrefixes=None):
+
+ # ---------------------------------------------------------------------------
+ # Dump a XML representation of a trigger
+ # ---------------------------------------------------------------------------
+
+ def _dumpXML_ (self, lookupDict, treeDump, gap, xmlnamespaces, textEncoding,
+ stripPrefixes, escape):
"""
Dumps an XML representation of a trigger.
- used in saving.
"""
try:
- escape = not gConfig('StoreTriggersAsCDATA')
+ asCData = not gConfig ('StoreTriggersAsCDATA')
+
except:
- escape = False
+ asCData = False
xmlEntity = "trigger"
xmlString = "%s<%s" % (gap[:-2],xmlEntity)
@@ -244,12 +245,13 @@
xmlString += ">\n"
if treeDump:
- if hasContent and not escape:
+ if hasContent and not asCData:
xmlString += "<![CDATA["
for child in self._children:
- xmlString += child.dumpXML(lookupDict, 1,gap+" ",escape=escape,
- stripPrefixes = stripPrefixes)
- if hasContent and not escape:
+ xmlString += child.dumpXML (lookupDict, True , gap + " ",
+ xmlnamespaces, textEncoding, stripPrefixes, escape)
+
+ if hasContent and not asCData:
xmlString += "]]>"
if hasContent:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r8096 - in trunk/gnue-common/src: definitions logic,
johannes <=