So, I have been doing a bunch of tweaking to generateDS and just wanted to
post the changes I made...the most major thing I changed is that rather than
having like 1700 lines of duplicated code in every .py file generated from
an XSD, I had it write out the base stuff to one file and then the output
file imports everything from that file...

I had like 13 XSDs to generate code for and it was a hassle to clean up the
code manually and remove all the duplicate stuff so thats why I changed
this...

I also made it so that rather than inserting included XSDs into the current
tree (which is technically proper) I take that file and call main in
generateDS to generate a seperate file. Then I save the file name and add it
to a list of imports at the top of the file

Another change I made is that rather than making every XSD contain main I
create a seperate parser.py file which will parse in an XML file and then do
the export. Also added a --python option to use exportLiteral instead of
export

The last few changes I made aren't really done...I just added to the
simpleType implementation a little bit. I added a restriction attribute to
the simpletype class which is a constraint facet. This constraint facet can
be used to generate validation code for value...not very clean and probably
not proper but its a start...I started, then looked at the w3c documentation
for constraints and simpletypes...then gave up, haha

Anyway, here are some patch files...I ignored whitespace, you may notice
that I used tabs instead of spaces in some of the simpletype generated
code...you can use it or not, just thought I would through it out there

-Brandon
--- generateDS.py	2009-06-02 11:55:53.258830896 -0600
+++ ../../../../tools/policy/generateDS.py	2009-06-02 11:57:02.298098654 -0600
@@ -86,7 +86,6 @@
 import urllib2
 import imp
 from xml.sax import handler, make_parser
-import xml.sax.xmlreader
 import logging
 import keyword
 import StringIO
@@ -172,7 +171,7 @@
         NameType, NCNameType, QNameType, NameTypes, \
         AnyAttributeType, SimpleTypeType, RestrictionType, \
         WhiteSpaceType, ListType, EnumerationType, UnionType, \
-        OtherSimpleTypes
+		OtherSimpleTypes, minInclusiveType, maxInclusiveType
     AttributeGroupType = nameSpace + 'attributeGroup'
     AttributeType = nameSpace + 'attribute'
     BooleanType = nameSpace + 'boolean'
@@ -190,8 +189,7 @@
         nameSpace + 'short',
         nameSpace + 'long',
         nameSpace + 'int',
-        nameSpace + 'short',
-        )
+		nameSpace + 'short',)
     #ShortType = nameSpace + 'short'
     #LongType = nameSpace + 'long'
     DecimalType = nameSpace + 'decimal'
@@ -212,8 +210,7 @@
     StringType = (nameSpace + 'string',
         nameSpace + 'duration',
         nameSpace + 'anyURI',
-        nameSpace + 'normalizedString',
-        )
+		nameSpace + 'normalizedString',)
     TokenType = nameSpace + 'token'
     NameType = nameSpace + 'Name'
     NCNameType = nameSpace + 'NCName'
@@ -266,10 +263,9 @@
         nameSpace + 'unsignedByte',
         nameSpace + 'unsignedInt',
         nameSpace + 'unsignedLong',
-        nameSpace + 'unsignedShort',
-    )
-
-
+		nameSpace + 'unsignedShort',)
+	minInclusiveType = nameSpace + "minInclusive"
+	maxInclusiveType = nameSpace + "maxInclusive"
 
 #
 # For debugging.
@@ -300,6 +296,33 @@
     def __init__(self):
         pass
 
+class ConstrainingFacet:
+	def __init__(self):
+		self.length = None
+		self.minLength = None
+		self.maxLength = None
+		self.pattern = None
+		self.enumeration = None
+		self.whiteSpace = None
+		self.maxInclusive = None
+		self.minExclusive = None
+		self.minInclusive = None
+		self.totalDigits = None
+		self.fractionDigits = None
+
+	def get_validator(self, indent):
+		st = "%sdef validate(self):\n" % "\t" * indent
+		if self.length is not None:
+			st += "%sif len(self.value) > %d:\n" % ("\t" * (indent + 1), int(self.length))
+			st += "%s	return False\n" % ("\t" * (indent + 1),)
+		if self.minInclusive is not None:
+			st += "%sif self.value < %d:\n" % ("\t" * (indent + 1), int(self.minInclusive))
+			st += "%s	return False\n" % ("\t" * (indent + 1),)
+		if self.maxInclusive is not None:
+			st += "%sif self.value > %d:\n" % ("\t" * (indent + 1), int(self.maxInclusive))
+			st += "%s	return False\n" % ("\t" * (indent + 1),)
+		st += "%spass\n\n" % ("\t" * (indent + 1),)
+		return st
 
 class SimpleTypeElement(XschemaElementBase):
     def __init__(self, name):
@@ -318,6 +341,8 @@
         self.unionOf = list()
         self.simpleType = 0
         self.listType = 0
+		self.restrictions = ConstrainingFacet()
+
     def setName(self, name): self.name = name
     def getName(self): return self.name
     def setBase(self, base): self.base = base
@@ -922,8 +947,7 @@
                 elif name == 'targetNamespace':
                     Targetnamespace = value
         elif (name == ElementType or 
-            ((name == ComplexTypeType) and (len(self.stack) == 1))
-            ):
+			((name == ComplexTypeType) and (len(self.stack) == 1))):
             self.inElement = 1
             self.inNonanonymousComplexType = 1
             element = XschemaElement(attrs)
@@ -1091,6 +1115,12 @@
             # fixlist
             if self.inSimpleType and self.inRestrictionType:
                 self.stack[-1].setListType(1)
+		elif name == minInclusiveType:
+			if self.inSimpleType and self.inRestrictionType:
+				self.stack[-1].restrictions.minInclusive = attrs['value']
+		elif name == maxInclusiveType:
+			if self.inSimpleType and self.inRestrictionType:
+				self.stack[-1].restrictions.maxInclusive = attrs['value']
         logging.debug("Start element stack: %d" % len(self.stack))
 
     def endElement(self, name):
@@ -2291,9 +2321,7 @@
         ((childType in StringType or
             childType == TokenType or
             childType == DateTimeType or
-            childType == DateType
-        )) #or is_simple_type)
-        ):
+			childType == DateType))):
         s1 = '        %s child_.nodeType == Node.ELEMENT_NODE and \\\n' % \
              keyword
         wrt(s1)
@@ -2440,8 +2468,7 @@
         # Is this a simple type?
         base = child.getBase()
         if (child.getSimpleType() or
-            (base and base in SimpleTypeDict)
-            ):
+			(base and base in SimpleTypeDict)):
             s1 = "            obj_ = None\n"
         else:
             # name_type_problem
@@ -2699,8 +2726,7 @@
                 childType == PositiveIntegerType or
                 childType == NonPositiveIntegerType or
                 childType == NegativeIntegerType or
-                childType == NonNegativeIntegerType
-                ):
+				childType == NonNegativeIntegerType):
                 if default is None:
                     add(', %s=None' % cleanName)
                 else:
@@ -3101,11 +3127,43 @@
 # Generated %s by generateDS.py.
 #
 
+%s
+
+#
+# Data representation classes.
+#
+
+"""
+
+# Fool (and straighten out) the syntax highlighting.
+# DUMMY = '''
+
+def generateImports(imports):
+	global TEMPLATE_IMPORTS
+	imp = ""
+	for module in imports:
+		imp += "from %s import *\n" % module
+
+	TEMPLATE_IMPORTS = TEMPLATE_IMPORTS % {"include_modules":imp}
+
+def generateHeader(outfile, prefix):
+	s1 = TEMPLATE_HEADER % (time.ctime(), TEMPLATE_IMPORTS)
+	outfile.write(s1)
+
+TEMPLATE_IMPORTS = """
 import sys
 import getopt
+import date_calcs
+import types
+from base import ExternalEncoding, GeneratedsSuper, MixedContainer, _MemberSpec, \\
+	exp, quote_attrib, quote_xml, quote_python, showIndent
 from string import lower as str_lower
 from xml.dom import minidom
 from xml.dom import Node
+%(include_modules)s
+"""
+
+TEMPLATE_BASE = """
 
 #
 # User methods
@@ -3185,6 +3243,8 @@
 
 def quote_python(inStr):
     s1 = inStr
+	if s1 is None:
+		return "None"
     if s1.find("'") == -1:
         if s1.find('\\n') == -1:
             return "'%%s'" %% s1
@@ -3276,31 +3336,16 @@
     def get_container(self): return self.container
 
 
-#
-# Data representation classes.
-#
-
 """
 
-# Fool (and straighten out) the syntax highlighting.
-# DUMMY = '''
-
-def generateHeader(outfile, prefix):
-    s1 = TEMPLATE_HEADER % (time.ctime(), ExternalEncoding, )
-    outfile.write(s1)
-
-
 TEMPLATE_MAIN = """\
-USAGE_TEXT = \"\"\"
-Usage: python <%(prefix)sParser>.py [ -s ] <in_xml_file>
-Options:
-    -s        Use the SAX parser, not the minidom parser.
-\"\"\"
+#!/usr/bin/env python
 
-def usage():
-    print USAGE_TEXT
-    sys.exit(1)
+from xml.dom import minidom
+from zesmauto.lib.policy.common import ESMPolicyGroup
+import sys
 
+from optparse import OptionParser
 
 def parse(inFileName):
     doc = minidom.parse(inFileName)
@@ -3343,11 +3388,18 @@
 
 
 def main():
-    args = sys.argv[1:]
-    if len(args) == 1:
-        parse(args[0])
+	parser = OptionParser()
+	parser.add_option("--python", action="store_true", default=False, help="output read in xml file to python code")
+
+	options, args = parser.parse_args()
+
+	if not args:
+		parser.error("please provide an XML file to parse")
+
+	if options.python:
+		parseLiteral(args[0])
     else:
-        usage()
+		parse(args[0])
 
 
 if __name__ == '__main__':
@@ -3832,9 +3884,18 @@
 
 def generateSimpleTypes(outfile, prefix, simpleTypeDict):
     wrt = outfile.write
-    for simpletype in simpleTypeDict.keys():
+	for simpletype, element in simpleTypeDict.items():
         wrt('class %s(object):\n' % simpletype)
-        wrt('    pass\n')
+		if element.values:
+			for value in element.values:
+				wrt("	%s=%s\n" % (value, `value`))
+		wrt("	def __init__(self, value):\n")
+		wrt("		self.value = value\n\n")
+
+		wrt("	def __str__(self):\n")
+		wrt("		return str(self.value)\n\n")
+
+		wrt(element.restrictions.get_validator(1))
         wrt('\n\n')
 
 
@@ -3853,7 +3914,7 @@
         outfile = os.tmpfile()
     processed = []
     generateHeader(outfile, prefix)
-    #generateSimpleTypes(outfile, prefix, SimpleTypeDict)
+	generateSimpleTypes(outfile, prefix, SimpleTypeDict)
     DelayedElements = []
     DelayedElements_subclass = []
     elements = root.getChildren()
@@ -3887,7 +3948,9 @@
     # It failed when we stopped putting simple types into ElementDict.
     # When there are duplicate names, the SAX parser probably does
     #   not work anyway.
-    generateMain(outfile, prefix, root)
+	mainfile = open("parser.py", "w")
+	generateMain(mainfile, prefix, root)
+	mainfile.close()
     outfile.close()
     if subclassFilename:
         generateSubclasses(root, subclassFilename, behaviorFilename,
@@ -4010,6 +4073,7 @@
     dh = XschemaHandler()
 ##    parser.setDocumentHandler(dh)
     parser.setContentHandler(dh)
+	include_modules = []
     if xschemaFileName == '-':
         infile = sys.stdin
     else:
@@ -4018,7 +4082,7 @@
         import process_includes
         process_includes.DIRPATH = Dirpath
         outfile = StringIO.StringIO()
-        process_includes.process_include_files(infile, outfile)
+		include_modules = process_includes.process_include_files2(infile, outfile)
         outfile.seek(0)
 ##        #
 ##        print '-' * 50
@@ -4028,12 +4092,18 @@
 ##        print '-' * 50
 ##        #
         infile = outfile
+	generateImports(include_modules)
     parser.parse(infile)
     root = dh.getRoot()
     root.annotate()
     #debug_show_elements(root)
     generate(outfileName, subclassFilename, behaviorFilename, 
         prefix, root, superModule)
+	#write out base.py
+	base_fname = "base.py"
+	base_f = open(base_fname, "w")
+	base_f.write(TEMPLATE_BASE % ExternalEncoding)
+
 
 def debug_show_elements(root):
     #print 'ElementDict:', ElementDict
@@ -4058,7 +4128,7 @@
     sys.exit(1)
 
 
-def main():
+def main(argv=None):
     global Force, GenerateProperties, SubclassSuffix, RootElement, \
         ValidatorBodiesBasePath, UseOldGetterSetter, \
         UserMethodsPath, XsdNameSpace, \
@@ -4066,7 +4136,7 @@
         TEMPLATE_MAIN, TEMPLATE_SUBCLASS_FOOTER, Dirpath, \
         ExternalEncoding
     outputText = True
-    args = sys.argv[1:]
+	args = argv or sys.argv[1:]
     try:
         options, args = getopt.getopt(args, 'hfyo:s:p:a:b:mu:',
             ['help', 'search-path=', 'subclass-suffix=', 'root-element=', 'super=',
@@ -4160,4 +4230,3 @@
 ##    import pdb
 ##    pdb.run('main()')
 
-
--- process_includes.py	2009-06-02 12:05:58.037740233 -0600
+++ ../../../../tools/policy/process_includes.py	2009-06-01 13:08:07.708986989 -0600
@@ -19,6 +19,7 @@
     python process_includes.py infile.xsd > outfile.xsd
     cat infile.xsd | python process_includes.py > outfile.xsd
 """
+from zesmauto.tools.policy import generateDS
 
 #
 # Imports
@@ -90,6 +91,17 @@
     process_include_tree(root)
     doc.write(outfile)
 
+def process_include_files2(infile, outfile):
+	"""
+	returns: (list) - The module names that need to be imported  
+	"""
+	doc = etree.parse(infile)
+	root = doc.getroot()
+	module_names = []
+	process_include_tree2(root, module_names)
+	doc.write(outfile)
+	return module_names
+
 
 def process_path(root, idx, path):
     count = idx
@@ -102,6 +114,38 @@
         count += 1
     return count
 
+def get_args(path):
+	"""Use same args user requested, replacing output file and using the
+	include file for parsing"""
+	filename = os.path.basename(path)
+	basename = filename[:filename.find(".")]
+	args = sys.argv[1:]
+	outname = basename + ".py"
+	for i, arg in enumerate(args):
+		if arg == "-o":
+			break
+	else:
+		args.append("-o")
+		i = len(args)
+	args[i + 1] = outname
+	for i, arg in enumerate(args):
+		if os.path.exists(arg) and not arg == outname:
+			break
+	else:
+		i = len(args)
+	args[i] = path
+	return args
+
+def process_path2(path):
+	filename = os.path.basename(path)
+	basename = filename[:filename.find(".")]
+	generateDS.Force = 1 # force overwrite, do not prompt
+	## Call parseAndGenerate again...use basename.py for output file.
+	## default to no subclasses, no prefix, use path given, no behavior, do process includes
+	args = get_args(path)
+	generateDS.main(args)
+	return basename
+
 def process_include_tree(root):
     global DIRPATH
     
@@ -121,7 +165,7 @@
                 idx = process_path(root, idx, path)
             else:
                 for d in DIRPATH:
-                    path = os.path.join(d,locn)
+					path = os.path.join(d, path)
                     if os.path.exists(path):
                         idx = process_path(root, idx, path)
                         break
@@ -155,6 +199,58 @@
             idx += 1
         children = root.getchildren()
 
+def process_include_tree2(root, module_names):
+	global DIRPATH
+
+	idx = 0
+	children = root.getchildren()
+	while idx < len(children):
+		child = children[idx]
+		tag = child.tag
+		if type(tag) == type(""):
+			tag = NAMESPACE_PAT.sub("", tag)
+		else:
+			tag = None
+		if tag == 'include' and 'schemaLocation' in child.attrib:
+			root.remove(child)
+			path = child.attrib['schemaLocation']
+			if os.path.exists(path):
+				module_names.append(process_path2(path))
+			else:
+				for d in DIRPATH:
+					path = os.path.join(d, path)
+					if os.path.exists(path):
+						module_names.append(process_path2(path))
+						break
+				else:
+					msg = "Can't find include file %s.  Aborting." % (path,)
+					raise IOError(msg)
+		elif tag == 'import' and 'schemaLocation' in child.attrib:
+			root.remove(child)
+			locn = child.attrib['schemaLocation']
+			if locn.startswith('ftp:') or locn.startswith('http:'):
+				try:
+					path, msg = urllib.urlretrieve(locn)
+					module_names.append(process_path2(path))
+				except:
+					msg = "Can't retrieve import file %s.  Aborting." % (locn,)
+					raise IOError(msg)
+			else:
+				if os.path.exists(locn):
+					module_names.append(process_path2(locn))
+				else:
+					for d in DIRPATH:
+						path = os.path.join(d, locn)
+						if os.path.exists(path):
+							module_names.append(process_path2(path))
+							break
+					else:
+						msg = "Can't find import file %s.  Aborting." % (locn,)
+						raise IOError(msg)
+		else:
+			process_include_tree2(child, module_names)
+			idx += 1
+		children = root.getchildren()
 
 def make_file(outFileName):
     global FORCE
@@ -209,4 +305,3 @@
     #import pdb; pdb.set_trace()
     main()
 
-
------------------------------------------------------------------------------
OpenSolaris 2009.06 is a cutting edge operating system for enterprises 
looking to deploy the next generation of Solaris that includes the latest 
innovations from Sun and the OpenSource community. Download a copy and 
enjoy capabilities such as Networking, Storage and Virtualization. 
Go to: http://p.sf.net/sfu/opensolaris-get
_______________________________________________
generateds-users mailing list
generateds-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/generateds-users

Reply via email to