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