From ec8daa16bf59a43989160ec0b98b28838b1f0655 Mon Sep 17 00:00:00 2001 From: dkuhlman <none@none> Date: Wed, 8 Oct 2014 16:07:14 -0700 Subject: [PATCH] Added generation of simpleType validators from XML schema --- README | 8 +- generateDS.html | 31 +- generateDS.py | 372 +++--- generateDS.txt | 28 +- gui/generateds_gui.py | 2 +- librarytemplate_howto.html | 6 +- librarytemplate_howto.txt | 2 +- process_includes.py | 5 +- setup.py | 2 +- tests/OnePer/oneperType00_1One.py | 5 + tests/OnePer/oneperType00_2One.py | 5 + tests/OnePer/oneperType01_1One.py | 5 + tests/OnePer/oneperType01_2One.py | 5 + tests/OnePer/oneperType02_1One.py | 5 + tests/OnePer/oneperType02_2One.py | 5 + tests/OnePer/oneperType03_1One.py | 5 + tests/OnePer/oneperType03_2One.py | 5 + tests/abstract_type1_sup.py | 5 + tests/abstract_type2_sup.py | 5 + tests/annotations1_sup.py | 5 + tests/annotations2_sup.py | 5 + tests/anonymous_type.xsd | 6 + tests/anonymous_type1_sup.py | 26 +- tests/anonymous_type2_sup.py | 26 +- tests/anysimpletype1_sup.py | 5 + tests/anysimpletype2_sup.py | 5 + tests/anywildcard1_sup.py | 5 + tests/anywildcard2_sup.py | 5 + tests/attr_groups1_sup.py | 5 + tests/attr_groups2_sup.py | 5 + tests/extensions1_sup.py | 27 +- tests/extensions2_sup.py | 27 +- tests/mapcleanname1_sup.py | 5 + tests/mapcleanname2_sup.py | 5 + tests/out1_sup.py | 16 +- tests/out2_sup.py | 16 +- tests/people_procincl1_sup.py | 16 +- tests/people_procincl2_sup.py | 16 +- tests/prefix_classname1_sup.py | 16 +- tests/prefix_classname2_sup.py | 16 +- tests/recursive_simpletype1_sup.py | 5 + tests/recursive_simpletype2_sup.py | 5 + tests/simplecontent_restriction1_sup.py | 5 + tests/simplecontent_restriction2_sup.py | 5 + tests/simpletype_memberspecs1_sup.py | 5 + tests/simpletype_memberspecs2_sup.py | 5 + tests/simpletypes_other1_sup.py | 5 + tests/simpletypes_other2_sup.py | 5 + tests/test.py | 34 +- tests/to_etree.xsd | 1 - tests/to_etree1_sup.py | 27 +- tests/to_etree2_sup.py | 27 +- tests/validate_simpletypes.xml | 28 + tests/validate_simpletypes.xsd | 93 ++ tests/validate_simpletypes1_out.xml | 30 + tests/validate_simpletypes1_sub.py | 235 ++++ tests/validate_simpletypes1_sup.py | 1396 ++++++++++++++++++++++ tests/validate_simpletypes1_warnings.txt | 20 + tests/validate_simpletypes2_out.xml | 30 + tests/validate_simpletypes2_sub.py | 235 ++++ tests/validate_simpletypes2_sup.py | 1396 ++++++++++++++++++++++ tests/validate_simpletypes2_warnings.txt | 20 + tutorial/generateds_tutorial.html | 6 +- tutorial/generateds_tutorial.txt | 2 +- tutorial/generateds_tutorial.zip | Bin 48761 -> 48764 bytes 65 files changed, 4181 insertions(+), 203 deletions(-) create mode 100644 tests/validate_simpletypes.xml create mode 100644 tests/validate_simpletypes.xsd create mode 100644 tests/validate_simpletypes1_out.xml create mode 100644 tests/validate_simpletypes1_sub.py create mode 100644 tests/validate_simpletypes1_sup.py create mode 100644 tests/validate_simpletypes1_warnings.txt create mode 100644 tests/validate_simpletypes2_out.xml create mode 100644 tests/validate_simpletypes2_sub.py create mode 100644 tests/validate_simpletypes2_sup.py create mode 100644 tests/validate_simpletypes2_warnings.txt diff --git a/README b/README index 198b2e5..61e09eb 100644 --- a/README +++ b/README @@ -141,9 +141,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Change history -------------- -Version 2.13b (09/14/2014) +Version 2.14a (10/08/2014) - Fixed export of simpleType lists (added "' '.join(data)". Thanks to Per Rosengren for catching this. +- Added new style validation of simpleType data. Validation + requirements are captured from the XML schema definition of the + simpleType, e.g. 'restriction base="..."' etc. Thanks to + azer gh for implementing this extended capability. +- Added unit test for simpleType validation, including test for + proper detection of bad (invalid) data. Version 2.13a (09/09/2014) - Minor fix to function generateToEtreeChildren. Must generate diff --git a/generateDS.html b/generateDS.html index 4ed9fd4..90dfb32 100644 --- a/generateDS.html +++ b/generateDS.html @@ -205,7 +205,7 @@ ul.auto-toc { <tr><th class="docinfo-name">Author:</th> <td>Dave Kuhlman</td></tr> <tr><th class="docinfo-name">Contact:</th> -<td><a class="first last reference external" href="mailto:dkuhlman@davekuhlman.org">dkuhlman@davekuhlman.org</a></td></tr> +<td>dkuhlman (at) davekuhlman (dot) org</td></tr> <tr><th class="docinfo-name">Address:</th> <td><pre class="address"> <a class="first last reference external" href="http://www.davekuhlman.org">http://www.davekuhlman.org</a> @@ -220,7 +220,7 @@ They are used by updateversion.py. --> <col class="field-name" /> <col class="field-body" /> <tbody valign="top"> -<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.13a</td> +<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.14a</td> </tr> </tbody> </table> @@ -229,7 +229,7 @@ They are used by updateversion.py. --> <col class="field-name" /> <col class="field-body" /> <tbody valign="top"> -<tr class="field"><th class="field-name">date:</th><td class="field-body">September 09, 2014</td> +<tr class="field"><th class="field-name">date:</th><td class="field-body">October 08, 2014</td> </tr> </tbody> </table> @@ -552,6 +552,11 @@ Options: module. Default="???" --validator-bodies=path Path to a directory containing files that provide bodies (implementations) of validator methods. + --use-old-simpletype-validators + Use the old style simpleType validator functions + stored in a specified directory, instead of the + new style validators generated directly from the + XML schema. See option --validator-bodies. --use-getter-setter Generate getter and setter methods. Values: "old" - Name getters/setters getVar()/setVar(). "new" - Name getters/setters get_var()/set_var(). @@ -729,6 +734,17 @@ an optional ".py" extension. If a file is not provided for a given type, an empty body (<tt class="docutils literal">pass</tt>) is generated. In these files, lines with "##" in the first two columns are ignored and are not inserted.</dd> +<dt>use-old-simpletype-validators</dt> +<dd><tt class="docutils literal">generateDS.py</tt> is capable of generating validator bodies -- +the code that validates data content in an XML instance +docuement and writes out warning messages if that data does not +satisfy the facets in the <tt class="docutils literal">xs:restriction</tt> in the +<tt class="docutils literal">xs:simpleType</tt> defintion in the XML schema. Use this option +if you want to use your own validation bodies/code defined in a +specified directory . See option <tt class="docutils literal"><span class="pre">--validator-bodies</span></tt> for +information on that. <em>Without</em> this option +(<tt class="docutils literal"><span class="pre">--use-old-simpletype-validators</span></tt>), the validator code will +be generated directly from the XML schema, which is the default.</dd> <dt>use-getter-setter</dt> <dd><p class="first"><tt class="docutils literal">generateDS.py</tt> now generates getter and setter methods (for variable "abc", for example) with the names get_abc() and @@ -761,7 +777,12 @@ changes to the generated python code.</dd> <dd>Do not process included XML Schema files. By default, generateDS.py will insert content from files referenced by <tt class="docutils literal"><include ... /></tt> elements into the XML Schema to be processed. -See section <a class="reference internal" href="#include-file-processing">Include file processing</a>.</dd> +See section <a class="reference internal" href="#include-file-processing">Include file processing</a>. Note that include +processing, which is performed in <tt class="docutils literal">process_includes.py</tt> is +required for generating validator bodies from the XML schema, +because the Lxml ElementTree produced in <tt class="docutils literal">process_includes.py</tt> +is needed to generate the validator code. So, using this option +also turns off automatic generation of validator code.</dd> <dt>silence</dt> <dd>Normally, the code generated with generateDS echoes the information being parsed. To prevent the echo from occurring, @@ -2886,7 +2907,7 @@ following among others:</p> <div class="footer"> <hr class="footer" /> <a class="reference external" href="generateDS.txt">View document source</a>. -Generated on: 2014-09-09 20:05 UTC. +Generated on: 2014-10-08 22:22 UTC. Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source. </div> diff --git a/generateDS.py b/generateDS.py index 12f65cd..145f995 100755 --- a/generateDS.py +++ b/generateDS.py @@ -1,7 +1,7 @@ #!/usr/bin/env python """ Synopsis: - Generate Python classes from XML Schema definition. + Generate Python classes from XML schema definition. Input is read from in_xsd_file or, if "-" (dash) arg, from stdin. Output is written to files named in "-o" and "-s" options. Usage: @@ -35,6 +35,11 @@ Options: module. Default="???" --validator-bodies=path Path to a directory containing files that provide bodies (implementations) of validator methods. + --use-old-simpletype-validators + Use the old style simpleType validator functions + stored in a specified directory, instead of the + new style validators generated directly from the + XML schema. See option --validator-bodies. --use-getter-setter Generate getter and setter methods. Values: "old" - Name getters/setters getVar()/setVar(). "new" - Name getters/setters get_var()/set_var(). @@ -51,10 +56,10 @@ Options: generated files. This is useful if you want to minimize the amount of (no-operation) changes to the generated python code. - --no-process-includes Do not process included XML Schema files. By + --no-process-includes Do not process included XML schema files. By default, generateDS.py will insert content from files referenced by <include ... /> - elements into the XML Schema to be processed. + elements into the XML schema to be processed. --silence Normally, the code generated with generateDS echoes the information being parsed. To prevent the echo from occurring, use the --silence switch. @@ -148,11 +153,6 @@ import keyword import StringIO import textwrap - - -#sorry :couldnt pass the filename but with global variable,as i want to use it in validations try to correct this -xsdFileName=[] - # Default logger configuration logging.basicConfig( level=logging.DEBUG, @@ -184,11 +184,14 @@ logging.disable(logging.INFO) # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.13b' +VERSION = '2.14a' ##VERSION## GenerateProperties = 0 UseGetterSetter = 'new' +UseOldSimpleTypeValidators = False +SchemaLxmlTree = None +XsdFileName=[] MemberSpecs = None DelayedElements = set() DelayedElements_subclass = set() @@ -3933,9 +3936,11 @@ def generateCtor(wrt, prefix, element): wrt(' self.%s = %s\n' % (name, name)) else: wrt(' self.%s = %s\n' % (name, name)) - #azg: validate if it is a simple type: validation shows warning so no fear that an error would rise + # validate if it is a simple type. Validation shows + # a warning so no fear that an error would rise. if (child.getSimpleType()): - wrt(' self.validate_%s(self.%s)\n' % (child.getSimpleType(), name)) + wrt(' self.validate_%s(self.%s)\n' % ( + child.getSimpleType(), name)) eltype = element.getType() if (element.getSimpleContent() or element.isMixed() or @@ -3951,145 +3956,197 @@ def generateCtor(wrt, prefix, element): # end generateCtor -#validate directly from xsd file, no need to specify directory for validation -def getValidatorBody(stName,typexs,base): -#azg - - az_s1 = ' if value is not None and all_validtion:\n' - from lxml import etree - ns = {'xs': 'http://www.w3.org/2001/XMLSchema'} - file = xsdFileName[0] - tree = etree.parse(file) - ns= {"xs": "http://www.w3.org/2001/XMLSchema"} - - #on determine l elemnt ou le type est definit - bases = tree.xpath("//xs:simpleType[@name=$n]/xs:restriction[@base=$b]",namespaces=ns,n=stName,b=base) - enumerations = [] - #une liste qui contient les restrictions deja traitees - already_processed=[] - for restriction in bases[0]: - restriction_name = restriction.tag - if 'pattern' in restriction_name and 'pattern' not in already_processed: - pattern =tree.xpath("//xs:simpleType[@name=$n]/xs:restriction[@base=$b]/xs:pattern/@value",namespaces=ns,n=stName,b=base)[0] - #convertir en string si le type n est pas string (car on ne peut pas comparer un pattern qu avec un type string - valuestring ='(str(value))' - toencode = '% {"value" : value}' - if 'string' in base: - valuestring ='(value)' - toencode = '% {"value" : value}.encode("utf-8")' - az_s1+=" a = re_.compile('%(pattern)s')\n" %{"pattern": pattern} - az_s1+=" if not a.match%(valuestring)s:\n" % {"valuestring":valuestring} - az_s1+=" warnings.warn('Value %(val)s dosent match xsd pattern restriction on %(typename)s' %(express)s )\n" %{ "val":'%(value)s' , "typename" : stName, "express": toencode } - already_processed.append('pattern') - elif 'enumeration' in restriction_name and 'enumeration' not in already_processed: - enumerations =tree.xpath("//xs:simpleType[@name=$n]/xs:restriction[@base=$b]/xs:enumeration/@value",namespaces=ns,n=stName,b=base) - already_processed.append('enumeration') - if len(enumerations)>0: - az_s1+=" enumerations=%(enumerations)s\n" % {'enumerations' : enumerations} - az_s1+=" enumeration_respectee = False\n" - az_s1+=" for enum in enumerations:\n" - az_s1+=" if value == enum:\n" - az_s1+=" enumeration_respectee=True\n" - az_s1+=" break\n" - az_s1+=" if not enumeration_respectee:\n" - az_s1+=" warnings.warn('Value %(val)s dosent match xsd enumeration restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": '% {"value" : value.encode("utf-8")}'} - elif 'maxLength' in restriction_name and 'maxLength' not in already_processed: - valuestring ='(str(value))' - toencode = '% {"value" : value}' - if 'string' in base: - valuestring ='(value)' - toencode = '% {"value" : value}.encode("utf-8")' - maxLength =tree.xpath("//xs:simpleType[@name=$n]/xs:restriction[@base=$b]/xs:maxLength/@value",namespaces=ns,n=stName,b=base)[0] - az_s1+=" if len%(valuestring)s > %(maxLength)s:\n" % {'maxLength' : maxLength, "valuestring" :valuestring} - az_s1+=" warnings.warn('Value %(val)s dosent match xsd maxLength restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode} - elif 'minLength' in restriction_name and 'minLength' not in already_processed: - valuestring ='(str(value))' - toencode = '% {"value" : value}' - if 'string' in base: - valuestring ='(value)' - toencode = '% {"value" : value}.encode("utf-8")' - minLength =tree.xpath("//xs:simpleType[@name=$n]/xs:restriction[@base=$b]/xs:minLength/@value",namespaces=ns,n=stName,b=base)[0] - az_s1+=" if len%(valuestring)s < %(minLength)s:\n" % {'minLength' : minLength, "valuestring" :valuestring} - az_s1+=" warnings.warn('Value %(val)s dosent match xsd minLength restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode} - already_processed.append('minLength') - elif 'minInclusive' in restriction_name and 'minInclusive' not in already_processed: - valuestring ='(value)' - toencode = '% {"value" : value}' - if 'string' in base: - valuestring ='len(str(value))' - toencode = '% {"value" : value}.encode("utf-8")' - minInclusive =tree.xpath("//xs:simpleType[@name=$n]/xs:restriction[@base=$b]/xs:minInclusive/@value",namespaces=ns,n=stName,b=base)[0] - az_s1+=" if %(valuestring)s <= %(minInclusive)s:\n" % {'minInclusive' : minInclusive, "valuestring" :valuestring} - az_s1+=" warnings.warn('Value %(val)s dosent match xsd minInclusive restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode } - already_processed.append('minInclusive') - elif 'maxInclusive' in restriction_name and 'maxInclusive' not in already_processed: - valuestring ='(value)' - toencode = '% {"value" : value}' - if 'string' in base: - valuestring ='len(str(value))' - toencode = '% {"value" : value}.encode("utf-8")' - maxInclusive =tree.xpath("//xs:simpleType[@name=$n]/xs:restriction[@base=$b]/xs:maxInclusive/@value",namespaces=ns,n=stName,b=base)[0] - az_s1+=" if %(valuestring)s >= %(maxInclusive)s:\n" % {'maxInclusive' : maxInclusive, "valuestring" :valuestring} - az_s1+=" warnings.warn('Value %(val)s dosent match xsd maxInclusive restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode } - already_processed.append('maxInclusive') - elif 'totalDigits' in restriction_name and 'totalDigits' not in already_processed: - valuestring ='(str(value))' - toencode = '% {"value" : value}' - if 'string' in base: - valuestring ='(value)' - toencode = '% {"value" : value}.encode("utf-8")' - totalDigits =tree.xpath("//xs:simpleType[@name=$n]/xs:restriction[@base=$b]/xs:totalDigits/@value",namespaces=ns,n=stName,b=base)[0] - az_s1+=" if len%(valuestring)s >= %(totalDigits)s:\n" % {'totalDigits' : totalDigits, "valuestring" :valuestring} - az_s1+=" warnings.warn('Value %(val)s dosent match xsd maxInclusive restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode } - already_processed.append('totalDigits') - - - - - - - - - - - - - - - az_s1+= ' pass\n' - - - return az_s1 - -#/azg - - - - - - retrieved = 0 - if ValidatorBodiesBasePath: - found = 0 - path = '%s%s%s.py' % (ValidatorBodiesBasePath, os.sep, stName, ) - if os.path.exists(path): - found = 1 +# find the simple type, either a named simpleType or an anonymous one. +def find_simple_type_def(tree, stName, element, child, ns, base): + st = None + if stName: + st_defs = tree.xpath("//xs:simpleType[@name=$n]", namespaces=ns, n=stName) + if st_defs: + st = st_defs[0] else: - path = '%s%s%s' % (ValidatorBodiesBasePath, os.sep, stName, ) + typeName = element.getType() + childName = child.getName() + # search for an anonymous simpleType. + el_defs = tree.xpath("//xs:complexType[@name=$typeName]//xs:element[@name=$childName]/xs:simpleType", + namespaces=ns, typeName=typeName, childName=childName) + if el_defs: + st = el_defs[0] + else: + # search for an anonymous simpleType inside an anonymous complexType. + el_defs = tree.xpath("//xs:element[@name=$typeName]/xs:complexType//xs:element[@name=$childName]/xs:simpleType", + namespaces=ns, typeName=typeName, childName=childName) + return st + + +#validate directly from xsd file, no need to specify directory for validation +def getValidatorBody(stName, base, element, child): + if not UseOldSimpleTypeValidators and SchemaLxmlTree is not None: + # generate validator bodies directly from the XML schema. + s1 = ' if value is not None and Validate_simpletypes_:\n' + initial_len = len(s1) + ns = {'xs': 'http://www.w3.org/2001/XMLSchema'} + fileName = XsdFileName[0] + tree = SchemaLxmlTree + ns= {"xs": "http://www.w3.org/2001/XMLSchema"} + #on determine l elemnt ou le type est definit + st = find_simple_type_def(tree, stName, element, child, ns, base) + if st is not None: + bases = st.xpath("xs:restriction[@base=$b]", namespaces=ns, n=stName, b=base) + #une liste qui contient les restrictions deja traitees + already_processed=[] + if bases: + for restriction in bases[0]: + restriction_name = restriction.tag + if 'pattern' in restriction_name and 'pattern' not in already_processed: + pattern = st.xpath("xs:restriction[@base=$b]/xs:pattern/@value", namespaces=ns, n=stName, b=base) + if pattern: + pattern = pattern[0] + already_processed.append('pattern') + #convertir en string si le type n est pas string (car on ne peut pas comparer un pattern qu avec un type string + valuestring ='(str(value))' + toencode = '% {"value" : value}' + if 'string' in base: + valuestring = '(value)' + toencode = '% {"value" : value.encode("utf-8")}' + s1 += " a = re_.compile('%(pattern)s')\n" %{"pattern": pattern} + s1 += " if not a.match%(valuestring)s:\n" % {"valuestring":valuestring} + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd pattern restriction on %(typename)s' %(express)s )\n" %{ "val":'%(value)s' , "typename" : stName, "express": toencode } + elif 'enumeration' in restriction_name and 'enumeration' not in already_processed: + enumerations = st.xpath("xs:restriction[@base=$b]/xs:enumeration/@value", namespaces=ns, n=stName, b=base) + if enumerations: + already_processed.append('enumeration') + s1 += " enumerations = %(enumerations)s\n" % {'enumerations' : enumerations} + s1 += " enumeration_respectee = False\n" + s1 += " for enum in enumerations:\n" + s1 += " if value == enum:\n" + s1 += " enumeration_respectee = True\n" + s1 += " break\n" + s1 += " if not enumeration_respectee:\n" + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd enumeration restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": '% {"value" : value.encode("utf-8")}'} + elif 'maxLength' in restriction_name and 'maxLength' not in already_processed: + valuestring = '(str(value))' + toencode = '% {"value" : value}' + if 'string' in base: + valuestring = '(value)' + toencode = '% {"value" : value.encode("utf-8")}' + maxLength = st.xpath("xs:restriction[@base=$b]/xs:maxLength/@value", namespaces=ns, n=stName, b=base) + if maxLength: + maxLength = maxLength[0] + already_processed.append('maxLength') + s1 += " if len%(valuestring)s > %(maxLength)s:\n" % {'maxLength' : maxLength, "valuestring" :valuestring} + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd maxLength restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode} + elif 'minLength' in restriction_name and 'minLength' not in already_processed: + valuestring = '(str(value))' + toencode = '% {"value" : value}' + if 'string' in base: + valuestring = '(value)' + toencode = '% {"value" : value.encode("utf-8")}' + minLength = st.xpath("xs:restriction[@base=$b]/xs:minLength/@value", namespaces=ns, n=stName, b=base) + if minLength: + minLength = minLength[0] + already_processed.append('minLength') + s1 += " if len%(valuestring)s < %(minLength)s:\n" % {'minLength' : minLength, "valuestring" :valuestring} + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd minLength restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode} + elif 'length' in restriction_name and 'length' not in already_processed: + valuestring = '(str(value))' + toencode = '% {"value" : value}' + if 'string' in base: + valuestring = '(value)' + toencode = '% {"value" : value.encode("utf-8")}' + length = st.xpath("xs:restriction[@base=$b]/xs:length/@value", namespaces=ns, n=stName, b=base) + if length: + length = length[0] + already_processed.append('length') + s1 += " if len%(valuestring)s != %(length)s:\n" % {'length' : length, "valuestring" :valuestring} + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd length restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode} + elif 'minInclusive' in restriction_name and 'minInclusive' not in already_processed: + valuestring = 'value' + toencode = '% {"value" : value}' + if 'string' in base: + valuestring = 'len(str(value))' + toencode = '% {"value" : value.encode("utf-8")}' + minInclusive = st.xpath("xs:restriction[@base=$b]/xs:minInclusive/@value", namespaces=ns, n=stName, b=base) + if minInclusive: + minInclusive = minInclusive[0] + already_processed.append('minInclusive') + s1 += " if %(valuestring)s <= %(minInclusive)s:\n" % {'minInclusive' : minInclusive, "valuestring" :valuestring} + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd minInclusive restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode } + elif 'maxInclusive' in restriction_name and 'maxInclusive' not in already_processed: + valuestring = 'value' + toencode = '% {"value" : value}' + if 'string' in base: + valuestring = 'len(str(value))' + toencode = '% {"value" : value.encode("utf-8")}' + maxInclusive = st.xpath("xs:restriction[@base=$b]/xs:maxInclusive/@value", namespaces=ns, n=stName, b=base) + if maxInclusive: + maxInclusive = maxInclusive[0] + already_processed.append('maxInclusive') + s1 += " if %(valuestring)s >= %(maxInclusive)s:\n" % {'maxInclusive' : maxInclusive, "valuestring" :valuestring} + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd maxInclusive restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode } + elif 'minExclusive' in restriction_name and 'minExclusive' not in already_processed: + valuestring = 'value' + toencode = '% {"value" : value}' + if 'string' in base: + valuestring = 'len(str(value))' + toencode = '% {"value" : value.encode("utf-8")}' + minExclusive = st.xpath("xs:restriction[@base=$b]/xs:minExclusive/@value", namespaces=ns, n=stName, b=base) + if minExclusive: + minExclusive = minExclusive[0] + already_processed.append('minExclusive') + s1 += " if %(valuestring)s < %(minExclusive)s:\n" % {'minExclusive' : minExclusive, "valuestring" :valuestring} + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd minExclusive restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode } + elif 'maxExclusive' in restriction_name and 'maxExclusive' not in already_processed: + valuestring = 'value' + toencode = '% {"value" : value}' + if 'string' in base: + valuestring = 'len(str(value))' + toencode = '% {"value" : value.encode("utf-8")}' + maxExclusive = st.xpath("xs:restriction[@base=$b]/xs:maxExclusive/@value", namespaces=ns, n=stName, b=base) + if maxExclusive: + maxExclusive = maxExclusive[0] + already_processed.append('maxExclusive') + s1 += " if %(valuestring)s > %(maxExclusive)s:\n" % {'maxExclusive' : maxExclusive, "valuestring" :valuestring} + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd maxExclusive restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode } + elif 'totalDigits' in restriction_name and 'totalDigits' not in already_processed: + valuestring = '(str(value))' + toencode = '% {"value" : value}' + if 'string' in base: + valuestring = '(value)' + toencode = '% {"value" : value.encode("utf-8")}' + totalDigits = st.xpath("xs:restriction[@base=$b]/xs:totalDigits/@value", namespaces=ns, n=stName, b=base) + if totalDigits: + totalDigits = totalDigits[0] + already_processed.append('totalDigits') + s1 += " if len%(valuestring)s >= %(totalDigits)s:\n" % {'totalDigits' : totalDigits, "valuestring" :valuestring} + s1 += " warnings.warn('Value \"%(val)s\" does not match xsd maxInclusive restriction on %(typename)s' %(express)s )\n" % {"val":'%(value)s' , "typename" : stName, "express": toencode } + if len(s1) == initial_len: + s1 += ' pass\n' + return s1 + else: + # if UseOldSimpleTypeValidators -- generate validator bodies from use code. + retrieved = 0 + if ValidatorBodiesBasePath: + found = 0 + path = '%s%s%s.py' % (ValidatorBodiesBasePath, os.sep, stName, ) if os.path.exists(path): found = 1 - if found: - infile = open(path, 'r') - lines = infile.readlines() - infile.close() - lines1 = [] - for line in lines: - if not line.startswith('##'): - lines1.append(line) - s1 = ''.join(lines1) - retrieved = 1 - if not retrieved: - s1 = ' pass\n' - return s1 + else: + path = '%s%s%s' % (ValidatorBodiesBasePath, os.sep, stName, ) + if os.path.exists(path): + found = 1 + if found: + infile = open(path, 'r') + lines = infile.readlines() + infile.close() + lines1 = [] + for line in lines: + if not line.startswith('##'): + lines1.append(line) + s1 = ''.join(lines1) + retrieved = 1 + if not retrieved: + s1 = ' pass\n' + return s1 # end getValidatorBody @@ -4178,7 +4235,7 @@ def generateValidatorDefs(wrt, element): (typeName, stObj.getBase(), )) else: wrt(' # validate type %s\n' % (typeName, )) - wrt(getValidatorBody(typeName,child.getType(),stObj.getBase())) + wrt(getValidatorBody(typeName, stObj.getBase(), element, child)) attrDefs = element.getAttributeDefs() for key in attrDefs: attrDef = attrDefs[key] @@ -4194,7 +4251,7 @@ def generateValidatorDefs(wrt, element): typeName, stObj.getBase(), )) else: wrt(' # validate type %s\n' % (typeName, )) - wrt(getValidatorBody(typeName,attrDef.getType(),attrDef.getBase())) + wrt(getValidatorBody(typeName, stObj.getBase(), None, None)) # end generateValidatorDefs @@ -4430,9 +4487,10 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings -all_validtion = True +Validate_simpletypes_ = True etree_ = None @@ -6033,7 +6091,8 @@ def parseAndGenerate( processIncludes, options, args, superModule='???'): global DelayedElements, DelayedElements_subclass, \ AlreadyGenerated, SaxDelayedElements, \ - AlreadyGenerated_subclass, UserMethodsPath, UserMethodsModule + AlreadyGenerated_subclass, UserMethodsPath, UserMethodsModule, \ + SchemaLxmlTree DelayedElements = set() DelayedElements_subclass = set() AlreadyGenerated = set() @@ -6058,13 +6117,14 @@ def parseAndGenerate( if processIncludes: import process_includes outfile = StringIO.StringIO() - process_includes.process_include_files( + doc = process_includes.process_include_files( infile, outfile, inpath=xschemaFileName, catalogpath=catalogFilename, fixtypenames=FixTypeNames) outfile.seek(0) infile = outfile + SchemaLxmlTree = doc.getroot() parser.parse(infile) root = dh.getRoot() root.annotate() @@ -6257,7 +6317,7 @@ def main(): ExternalEncoding, MemberSpecs, NoQuestions, \ ExportWrite, ExportEtree, ExportLiteral, \ FixTypeNames, SingleFileOutput, OutputDirectory, \ - ModuleSuffix + ModuleSuffix, UseOldSimpleTypeValidators outputText = True args = sys.argv[1:] try: @@ -6273,7 +6333,7 @@ def main(): 'no-questions', 'session=', 'fix-type-names=', 'version', 'export=', 'one-file-per-xsd', 'output-directory=', - 'module-suffix=' + 'module-suffix=', 'use-old-simpletype-validators', ]) except getopt.GetoptError: usage() @@ -6392,6 +6452,8 @@ def main(): err_msg('*** Option use-getter-setter must ' '"old" or "new" or "none".\n') sys.exit(1) + elif option[0] == '--use-old-simpletype-validators': + UseOldSimpleTypeValidators = True elif option[0] in ('-u', '--user-methods'): UserMethodsPath = option[1] elif option[0] == '--no-process-includes': @@ -6444,7 +6506,7 @@ def main(): usage() else: xschemaFileName = args[0] - xsdFileName.append(xschemaFileName) + XsdFileName.append(xschemaFileName) silent = not outputText TEMPLATE_MAIN = fixSilence(TEMPLATE_MAIN, silent) TEMPLATE_SUBCLASS_FOOTER = fixSilence(TEMPLATE_SUBCLASS_FOOTER, silent) diff --git a/generateDS.txt b/generateDS.txt index d8e2df5..ad40547 100644 --- a/generateDS.txt +++ b/generateDS.txt @@ -3,7 +3,7 @@ generateDS -- Generate Data Structures from XML Schema ====================================================== :author: Dave Kuhlman -:contact: dkuhlman@davekuhlman.org +:contact: dkuhlman (at) davekuhlman (dot) org :address: http://www.davekuhlman.org @@ -12,7 +12,7 @@ generateDS -- Generate Data Structures from XML Schema .. version -:revision: 2.13b +:revision: 2.14a .. version @@ -253,6 +253,11 @@ Here is the usage message displayed by ``generateDS.py``:: module. Default="???" --validator-bodies=path Path to a directory containing files that provide bodies (implementations) of validator methods. + --use-old-simpletype-validators + Use the old style simpleType validator functions + stored in a specified directory, instead of the + new style validators generated directly from the + XML schema. See option --validator-bodies. --use-getter-setter Generate getter and setter methods. Values: "old" - Name getters/setters getVar()/setVar(). "new" - Name getters/setters get_var()/set_var(). @@ -442,6 +447,18 @@ validator-bodies=<path> files, lines with "##" in the first two columns are ignored and are not inserted. +use-old-simpletype-validators + ``generateDS.py`` is capable of generating validator bodies -- + the code that validates data content in an XML instance + docuement and writes out warning messages if that data does not + satisfy the facets in the ``xs:restriction`` in the + ``xs:simpleType`` defintion in the XML schema. Use this option + if you want to use your own validation bodies/code defined in a + specified directory . See option ``--validator-bodies`` for + information on that. *Without* this option + (``--use-old-simpletype-validators``), the validator code will + be generated directly from the XML schema, which is the default. + use-getter-setter ``generateDS.py`` now generates getter and setter methods (for variable "abc", for example) with the names get_abc() and @@ -477,7 +494,12 @@ no-process-includes Do not process included XML Schema files. By default, generateDS.py will insert content from files referenced by ``<include ... />`` elements into the XML Schema to be processed. - See section `Include file processing`_. + See section `Include file processing`_. Note that include + processing, which is performed in ``process_includes.py`` is + required for generating validator bodies from the XML schema, + because the Lxml ElementTree produced in ``process_includes.py`` + is needed to generate the validator code. So, using this option + also turns off automatic generation of validator code. silence Normally, the code generated with generateDS echoes the diff --git a/gui/generateds_gui.py b/gui/generateds_gui.py index 3e2bc3f..d0e31e8 100755 --- a/gui/generateds_gui.py +++ b/gui/generateds_gui.py @@ -31,7 +31,7 @@ from libgenerateDS.gui import generateds_gui_session # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.13b' +VERSION = '2.14a' ##VERSION## diff --git a/librarytemplate_howto.html b/librarytemplate_howto.html index db0373e..fe92475 100644 --- a/librarytemplate_howto.html +++ b/librarytemplate_howto.html @@ -217,7 +217,7 @@ ul.auto-toc { <col class="field-name" /> <col class="field-body" /> <tbody valign="top"> -<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.13a</td> +<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.14a</td> </tr> </tbody> </table> @@ -226,7 +226,7 @@ ul.auto-toc { <col class="field-name" /> <col class="field-body" /> <tbody valign="top"> -<tr class="field"><th class="field-name">date:</th><td class="field-body">September 09, 2014</td> +<tr class="field"><th class="field-name">date:</th><td class="field-body">October 08, 2014</td> </tr> </tbody> </table> @@ -380,7 +380,7 @@ this command for your needs. For example, you may need to use <div class="footer"> <hr class="footer" /> <a class="reference external" href="librarytemplate_howto.txt">View document source</a>. -Generated on: 2014-09-09 19:14 UTC. +Generated on: 2014-10-08 22:22 UTC. Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source. </div> diff --git a/librarytemplate_howto.txt b/librarytemplate_howto.txt index ed399ce..1c3c521 100644 --- a/librarytemplate_howto.txt +++ b/librarytemplate_howto.txt @@ -8,7 +8,7 @@ How to package a generateDS.py generated library .. version -:revision: 2.13b +:revision: 2.14a .. version diff --git a/process_includes.py b/process_includes.py index 8ea7785..166239b 100755 --- a/process_includes.py +++ b/process_includes.py @@ -30,7 +30,7 @@ from lxml import etree # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.13b' +VERSION = '2.14a' ##VERSION## CatalogDict = {} @@ -59,7 +59,8 @@ def process_include_files( 'force': False, 'fixtypenames': fixtypenames, }) - prep_schema_doc(infile, outfile, inpath, options) + doc = prep_schema_doc(infile, outfile, inpath, options) + return doc def get_all_root_file_paths(infile, inpath='', catalogpath=None): diff --git a/setup.py b/setup.py index e73b0d4..6f85b8b 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup(name="generateDS", # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## - version="2.13b", + version="2.14a", ##VERSION## author="Dave Kuhlman", author_email="dkuhlman@davekuhlman.org", diff --git a/tests/OnePer/oneperType00_1One.py b/tests/OnePer/oneperType00_1One.py index eb028c4..3691790 100644 --- a/tests/OnePer/oneperType00_1One.py +++ b/tests/OnePer/oneperType00_1One.py @@ -30,6 +30,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/OnePer/oneperType00_2One.py b/tests/OnePer/oneperType00_2One.py index eb028c4..3691790 100644 --- a/tests/OnePer/oneperType00_2One.py +++ b/tests/OnePer/oneperType00_2One.py @@ -30,6 +30,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/OnePer/oneperType01_1One.py b/tests/OnePer/oneperType01_1One.py index 96afe49..af63e67 100644 --- a/tests/OnePer/oneperType01_1One.py +++ b/tests/OnePer/oneperType01_1One.py @@ -30,6 +30,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/OnePer/oneperType01_2One.py b/tests/OnePer/oneperType01_2One.py index 96afe49..af63e67 100644 --- a/tests/OnePer/oneperType01_2One.py +++ b/tests/OnePer/oneperType01_2One.py @@ -30,6 +30,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/OnePer/oneperType02_1One.py b/tests/OnePer/oneperType02_1One.py index 63667bb..b2a8871 100644 --- a/tests/OnePer/oneperType02_1One.py +++ b/tests/OnePer/oneperType02_1One.py @@ -30,6 +30,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/OnePer/oneperType02_2One.py b/tests/OnePer/oneperType02_2One.py index 63667bb..b2a8871 100644 --- a/tests/OnePer/oneperType02_2One.py +++ b/tests/OnePer/oneperType02_2One.py @@ -30,6 +30,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/OnePer/oneperType03_1One.py b/tests/OnePer/oneperType03_1One.py index c3102f4..ef4bbbb 100644 --- a/tests/OnePer/oneperType03_1One.py +++ b/tests/OnePer/oneperType03_1One.py @@ -30,6 +30,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/OnePer/oneperType03_2One.py b/tests/OnePer/oneperType03_2One.py index c3102f4..ef4bbbb 100644 --- a/tests/OnePer/oneperType03_2One.py +++ b/tests/OnePer/oneperType03_2One.py @@ -30,6 +30,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/abstract_type1_sup.py b/tests/abstract_type1_sup.py index 7474797..5b2555f 100644 --- a/tests/abstract_type1_sup.py +++ b/tests/abstract_type1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/abstract_type2_sup.py b/tests/abstract_type2_sup.py index 7474797..5b2555f 100644 --- a/tests/abstract_type2_sup.py +++ b/tests/abstract_type2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/annotations1_sup.py b/tests/annotations1_sup.py index ba6a380..98b240a 100644 --- a/tests/annotations1_sup.py +++ b/tests/annotations1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/annotations2_sup.py b/tests/annotations2_sup.py index ba6a380..98b240a 100644 --- a/tests/annotations2_sup.py +++ b/tests/annotations2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/anonymous_type.xsd b/tests/anonymous_type.xsd index 271664f..a9bb07f 100644 --- a/tests/anonymous_type.xsd +++ b/tests/anonymous_type.xsd @@ -14,6 +14,8 @@ <xs:element name="FooType"> <xs:simpleType> <xs:restriction base="xs:string"> + <xs:minLength value="10"/> + <xs:maxLength value="19"/> </xs:restriction> </xs:simpleType> </xs:element> @@ -26,6 +28,8 @@ <xs:element name="BarType"> <xs:simpleType> <xs:restriction base="xs:string"> + <xs:minLength value="20"/> + <xs:maxLength value="29"/> </xs:restriction> </xs:simpleType> </xs:element> @@ -38,6 +42,8 @@ <xs:element name="BazType"> <xs:simpleType> <xs:restriction base="xs:string"> + <xs:minLength value="30"/> + <xs:maxLength value="39"/> </xs:restriction> </xs:simpleType> </xs:element> diff --git a/tests/anonymous_type1_sup.py b/tests/anonymous_type1_sup.py index 21f333e..3d0bc3a 100644 --- a/tests/anonymous_type1_sup.py +++ b/tests/anonymous_type1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -762,6 +767,7 @@ class FooType1(GeneratedsSuper): def __init__(self, FooType=None): self.original_tagname_ = None self.FooType = FooType + self.validate_FooTypeType(self.FooType) def factory(*args_, **kwargs_): if FooType1.subclass: return FooType1.subclass(*args_, **kwargs_) @@ -772,7 +778,11 @@ class FooType1(GeneratedsSuper): def set_FooType(self, FooType): self.FooType = FooType def validate_FooTypeType(self, value): # Validate type FooTypeType, a restriction on xs:string. - pass + if value is not None and Validate_simpletypes_: + if len(value) < 10: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on FooTypeType' % {"value" : value.encode("utf-8")} ) + if len(value) > 19: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on FooTypeType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.FooType is not None @@ -847,6 +857,7 @@ class BarType2(GeneratedsSuper): def __init__(self, BarType=None): self.original_tagname_ = None self.BarType = BarType + self.validate_BarTypeType(self.BarType) def factory(*args_, **kwargs_): if BarType2.subclass: return BarType2.subclass(*args_, **kwargs_) @@ -857,7 +868,11 @@ class BarType2(GeneratedsSuper): def set_BarType(self, BarType): self.BarType = BarType def validate_BarTypeType(self, value): # Validate type BarTypeType, a restriction on xs:string. - pass + if value is not None and Validate_simpletypes_: + if len(value) < 20: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on BarTypeType' % {"value" : value.encode("utf-8")} ) + if len(value) > 29: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on BarTypeType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.BarType is not None @@ -932,6 +947,7 @@ class BazType3(GeneratedsSuper): def __init__(self, BazType=None): self.original_tagname_ = None self.BazType = BazType + self.validate_BazTypeType(self.BazType) def factory(*args_, **kwargs_): if BazType3.subclass: return BazType3.subclass(*args_, **kwargs_) @@ -942,7 +958,11 @@ class BazType3(GeneratedsSuper): def set_BazType(self, BazType): self.BazType = BazType def validate_BazTypeType(self, value): # Validate type BazTypeType, a restriction on xs:string. - pass + if value is not None and Validate_simpletypes_: + if len(value) < 30: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on BazTypeType' % {"value" : value.encode("utf-8")} ) + if len(value) > 39: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on BazTypeType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.BazType is not None diff --git a/tests/anonymous_type2_sup.py b/tests/anonymous_type2_sup.py index 21f333e..3d0bc3a 100644 --- a/tests/anonymous_type2_sup.py +++ b/tests/anonymous_type2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -762,6 +767,7 @@ class FooType1(GeneratedsSuper): def __init__(self, FooType=None): self.original_tagname_ = None self.FooType = FooType + self.validate_FooTypeType(self.FooType) def factory(*args_, **kwargs_): if FooType1.subclass: return FooType1.subclass(*args_, **kwargs_) @@ -772,7 +778,11 @@ class FooType1(GeneratedsSuper): def set_FooType(self, FooType): self.FooType = FooType def validate_FooTypeType(self, value): # Validate type FooTypeType, a restriction on xs:string. - pass + if value is not None and Validate_simpletypes_: + if len(value) < 10: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on FooTypeType' % {"value" : value.encode("utf-8")} ) + if len(value) > 19: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on FooTypeType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.FooType is not None @@ -847,6 +857,7 @@ class BarType2(GeneratedsSuper): def __init__(self, BarType=None): self.original_tagname_ = None self.BarType = BarType + self.validate_BarTypeType(self.BarType) def factory(*args_, **kwargs_): if BarType2.subclass: return BarType2.subclass(*args_, **kwargs_) @@ -857,7 +868,11 @@ class BarType2(GeneratedsSuper): def set_BarType(self, BarType): self.BarType = BarType def validate_BarTypeType(self, value): # Validate type BarTypeType, a restriction on xs:string. - pass + if value is not None and Validate_simpletypes_: + if len(value) < 20: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on BarTypeType' % {"value" : value.encode("utf-8")} ) + if len(value) > 29: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on BarTypeType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.BarType is not None @@ -932,6 +947,7 @@ class BazType3(GeneratedsSuper): def __init__(self, BazType=None): self.original_tagname_ = None self.BazType = BazType + self.validate_BazTypeType(self.BazType) def factory(*args_, **kwargs_): if BazType3.subclass: return BazType3.subclass(*args_, **kwargs_) @@ -942,7 +958,11 @@ class BazType3(GeneratedsSuper): def set_BazType(self, BazType): self.BazType = BazType def validate_BazTypeType(self, value): # Validate type BazTypeType, a restriction on xs:string. - pass + if value is not None and Validate_simpletypes_: + if len(value) < 30: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on BazTypeType' % {"value" : value.encode("utf-8")} ) + if len(value) > 39: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on BazTypeType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.BazType is not None diff --git a/tests/anysimpletype1_sup.py b/tests/anysimpletype1_sup.py index 8965b08..d1d826b 100644 --- a/tests/anysimpletype1_sup.py +++ b/tests/anysimpletype1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/anysimpletype2_sup.py b/tests/anysimpletype2_sup.py index 8965b08..d1d826b 100644 --- a/tests/anysimpletype2_sup.py +++ b/tests/anysimpletype2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/anywildcard1_sup.py b/tests/anywildcard1_sup.py index 6fe4929..5fad0db 100644 --- a/tests/anywildcard1_sup.py +++ b/tests/anywildcard1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/anywildcard2_sup.py b/tests/anywildcard2_sup.py index 6fe4929..5fad0db 100644 --- a/tests/anywildcard2_sup.py +++ b/tests/anywildcard2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/attr_groups1_sup.py b/tests/attr_groups1_sup.py index 75755fe..ec108a2 100644 --- a/tests/attr_groups1_sup.py +++ b/tests/attr_groups1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/attr_groups2_sup.py b/tests/attr_groups2_sup.py index 75755fe..ec108a2 100644 --- a/tests/attr_groups2_sup.py +++ b/tests/attr_groups2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/extensions1_sup.py b/tests/extensions1_sup.py index 56df5a9..4b81152 100644 --- a/tests/extensions1_sup.py +++ b/tests/extensions1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -1011,6 +1016,7 @@ class simpleFactoidType(GeneratedsSuper): def __init__(self, relation=None): self.original_tagname_ = None self.relation = relation + self.validate_RelationType(self.relation) def factory(*args_, **kwargs_): if simpleFactoidType.subclass: return simpleFactoidType.subclass(*args_, **kwargs_) @@ -1021,7 +1027,15 @@ class simpleFactoidType(GeneratedsSuper): def set_relation(self, relation): self.relation = relation def validate_RelationType(self, value): # Validate type RelationType, a restriction on RelationType2. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['down', 'add'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on RelationType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.relation is not None @@ -1097,6 +1111,7 @@ class mixedFactoidType(GeneratedsSuper): def __init__(self, relation=None, valueOf_=None, mixedclass_=None, content_=None): self.original_tagname_ = None self.relation = relation + self.validate_RelationType(self.relation) self.valueOf_ = valueOf_ if mixedclass_ is None: self.mixedclass_ = MixedContainer @@ -1119,7 +1134,15 @@ class mixedFactoidType(GeneratedsSuper): def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_ def validate_RelationType(self, value): # Validate type RelationType, a restriction on RelationType2. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['down', 'add'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on RelationType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.relation is not None or diff --git a/tests/extensions2_sup.py b/tests/extensions2_sup.py index 56df5a9..4b81152 100644 --- a/tests/extensions2_sup.py +++ b/tests/extensions2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -1011,6 +1016,7 @@ class simpleFactoidType(GeneratedsSuper): def __init__(self, relation=None): self.original_tagname_ = None self.relation = relation + self.validate_RelationType(self.relation) def factory(*args_, **kwargs_): if simpleFactoidType.subclass: return simpleFactoidType.subclass(*args_, **kwargs_) @@ -1021,7 +1027,15 @@ class simpleFactoidType(GeneratedsSuper): def set_relation(self, relation): self.relation = relation def validate_RelationType(self, value): # Validate type RelationType, a restriction on RelationType2. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['down', 'add'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on RelationType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.relation is not None @@ -1097,6 +1111,7 @@ class mixedFactoidType(GeneratedsSuper): def __init__(self, relation=None, valueOf_=None, mixedclass_=None, content_=None): self.original_tagname_ = None self.relation = relation + self.validate_RelationType(self.relation) self.valueOf_ = valueOf_ if mixedclass_ is None: self.mixedclass_ = MixedContainer @@ -1119,7 +1134,15 @@ class mixedFactoidType(GeneratedsSuper): def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_ def validate_RelationType(self, value): # Validate type RelationType, a restriction on RelationType2. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['down', 'add'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on RelationType' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.relation is not None or diff --git a/tests/mapcleanname1_sup.py b/tests/mapcleanname1_sup.py index 9776f19..0d05b13 100644 --- a/tests/mapcleanname1_sup.py +++ b/tests/mapcleanname1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/mapcleanname2_sup.py b/tests/mapcleanname2_sup.py index 9776f19..0d05b13 100644 --- a/tests/mapcleanname2_sup.py +++ b/tests/mapcleanname2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/out1_sup.py b/tests/out1_sup.py index 0ce418c..3890019 100644 --- a/tests/out1_sup.py +++ b/tests/out1_sup.py @@ -28,6 +28,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -1449,6 +1454,7 @@ class programmer(person): self.ellong = ellong self.elparam = elparam self.elarraytypes = elarraytypes + self.validate_ArrayTypes(self.elarraytypes) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if programmer.subclass: @@ -1496,7 +1502,15 @@ class programmer(person): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_ArrayTypes(self, value): # Validate type ArrayTypes, a restriction on xs:NMTOKEN. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on ArrayTypes' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.email is not None or diff --git a/tests/out2_sup.py b/tests/out2_sup.py index 0ce418c..3890019 100644 --- a/tests/out2_sup.py +++ b/tests/out2_sup.py @@ -28,6 +28,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -1449,6 +1454,7 @@ class programmer(person): self.ellong = ellong self.elparam = elparam self.elarraytypes = elarraytypes + self.validate_ArrayTypes(self.elarraytypes) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if programmer.subclass: @@ -1496,7 +1502,15 @@ class programmer(person): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_ArrayTypes(self, value): # Validate type ArrayTypes, a restriction on xs:NMTOKEN. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on ArrayTypes' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.email is not None or diff --git a/tests/people_procincl1_sup.py b/tests/people_procincl1_sup.py index c2d2220..1c35379 100644 --- a/tests/people_procincl1_sup.py +++ b/tests/people_procincl1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -2520,6 +2525,7 @@ class programmer(person): self.ellong = ellong self.elparam = elparam self.elarraytypes = elarraytypes + self.validate_ArrayTypes(self.elarraytypes) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if programmer.subclass: @@ -2565,7 +2571,15 @@ class programmer(person): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_ArrayTypes(self, value): # Validate type ArrayTypes, a restriction on xs:NMTOKEN. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on ArrayTypes' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.email is not None or diff --git a/tests/people_procincl2_sup.py b/tests/people_procincl2_sup.py index c2d2220..1c35379 100644 --- a/tests/people_procincl2_sup.py +++ b/tests/people_procincl2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -2520,6 +2525,7 @@ class programmer(person): self.ellong = ellong self.elparam = elparam self.elarraytypes = elarraytypes + self.validate_ArrayTypes(self.elarraytypes) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if programmer.subclass: @@ -2565,7 +2571,15 @@ class programmer(person): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_ArrayTypes(self, value): # Validate type ArrayTypes, a restriction on xs:NMTOKEN. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on ArrayTypes' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.email is not None or diff --git a/tests/prefix_classname1_sup.py b/tests/prefix_classname1_sup.py index 96730d2..404810c 100644 --- a/tests/prefix_classname1_sup.py +++ b/tests/prefix_classname1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -1307,6 +1312,7 @@ class tomato_programmer(tomato_person): self.ellong = ellong self.elparam = elparam self.elarraytypes = elarraytypes + self.validate_ArrayTypes(self.elarraytypes) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if tomato_programmer.subclass: @@ -1354,7 +1360,15 @@ class tomato_programmer(tomato_person): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_ArrayTypes(self, value): # Validate type ArrayTypes, a restriction on xs:NMTOKEN. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on ArrayTypes' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.email is not None or diff --git a/tests/prefix_classname2_sup.py b/tests/prefix_classname2_sup.py index 96730d2..404810c 100644 --- a/tests/prefix_classname2_sup.py +++ b/tests/prefix_classname2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -1307,6 +1312,7 @@ class tomato_programmer(tomato_person): self.ellong = ellong self.elparam = elparam self.elarraytypes = elarraytypes + self.validate_ArrayTypes(self.elarraytypes) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if tomato_programmer.subclass: @@ -1354,7 +1360,15 @@ class tomato_programmer(tomato_person): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_ArrayTypes(self, value): # Validate type ArrayTypes, a restriction on xs:NMTOKEN. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on ArrayTypes' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.email is not None or diff --git a/tests/recursive_simpletype1_sup.py b/tests/recursive_simpletype1_sup.py index 956f2f6..b793ade 100644 --- a/tests/recursive_simpletype1_sup.py +++ b/tests/recursive_simpletype1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/recursive_simpletype2_sup.py b/tests/recursive_simpletype2_sup.py index 956f2f6..b793ade 100644 --- a/tests/recursive_simpletype2_sup.py +++ b/tests/recursive_simpletype2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/simplecontent_restriction1_sup.py b/tests/simplecontent_restriction1_sup.py index 3c59aa9..817e86e 100644 --- a/tests/simplecontent_restriction1_sup.py +++ b/tests/simplecontent_restriction1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/simplecontent_restriction2_sup.py b/tests/simplecontent_restriction2_sup.py index 3c59aa9..817e86e 100644 --- a/tests/simplecontent_restriction2_sup.py +++ b/tests/simplecontent_restriction2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/simpletype_memberspecs1_sup.py b/tests/simpletype_memberspecs1_sup.py index 8dae63a..6bdaf95 100644 --- a/tests/simpletype_memberspecs1_sup.py +++ b/tests/simpletype_memberspecs1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/simpletype_memberspecs2_sup.py b/tests/simpletype_memberspecs2_sup.py index 8dae63a..6bdaf95 100644 --- a/tests/simpletype_memberspecs2_sup.py +++ b/tests/simpletype_memberspecs2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/simpletypes_other1_sup.py b/tests/simpletypes_other1_sup.py index 84e2ae7..a51ea60 100644 --- a/tests/simpletypes_other1_sup.py +++ b/tests/simpletypes_other1_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/simpletypes_other2_sup.py b/tests/simpletypes_other2_sup.py index 84e2ae7..a51ea60 100644 --- a/tests/simpletypes_other2_sup.py +++ b/tests/simpletypes_other2_sup.py @@ -29,6 +29,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False diff --git a/tests/test.py b/tests/test.py index 5e965bc..90ee2b6 100755 --- a/tests/test.py +++ b/tests/test.py @@ -331,8 +331,8 @@ class GenTest(unittest.TestCase): cmd = 'diff %s1_sub.py %s2_sub.py' % (t_, t_, ) result, err = self.execute(cmd) self.check_result(result, err, ()) - cmdTempl = 'python tests/%s2_sup.py tests/ipo.xml > tests/%s2_out.xml' - cmd = cmdTempl % (t_, t_, ) + cmdTempl = 'python tests/%s2_sup.py tests/%s.xml > tests/%s2_out.xml' + cmd = cmdTempl % (t_, t_, t_, ) result, _ = self.execute(cmd, cwd='..') cmd = 'diff %s1_out.xml %s2_out.xml' % (t_, t_, ) result, err = self.execute(cmd) @@ -550,6 +550,36 @@ class GenTest(unittest.TestCase): result, err = self.execute(cmd) self.check_result(result, err, ()) + def test_025_validate_simpletypes(self): + cmdTempl = ( + 'python generateDS.py --no-dates --no-versions ' + '--member-specs=list -f ' + '-o tests/%s2_sup.py -s tests/%s2_sub.py ' + '--super=%s2_sup ' + 'tests/%s.xsd' + ) + t_ = 'validate_simpletypes' + cmd = cmdTempl % (t_, t_, t_, t_, ) + result, _ = self.execute(cmd, cwd='..') + cmd = 'diff %s1_sup.py %s2_sup.py' % (t_, t_, ) + result, err = self.execute(cmd) + self.check_result(result, err, ('sys.stdout.write',)) + cmd = 'diff %s1_sub.py %s2_sub.py' % (t_, t_, ) + result, err = self.execute(cmd) + self.check_result(result, err, ()) + cmdTempl = ( + 'python tests/%s2_sup.py tests/%s.xml > tests/%s2_out.xml ' + '2> tests/%s2_warnings.txt' + ) + cmd = cmdTempl % (t_, t_, t_, t_, ) + result, _ = self.execute(cmd, cwd='..') + cmd = 'diff %s1_out.xml %s2_out.xml' % (t_, t_, ) + result, err = self.execute(cmd) + self.check_result(result, err, ()) + cmd = 'diff %s1_warnings.txt %s2_warnings.txt' % (t_, t_, ) + result, err = self.execute(cmd) + self.check_result(result, err, ()) + def check_result(self, result, err, ignore_strings): self.failUnlessEqual(len(result), 0) self.failUnlessEqual(len(err), 0) diff --git a/tests/to_etree.xsd b/tests/to_etree.xsd index 71d2860..1324971 100644 --- a/tests/to_etree.xsd +++ b/tests/to_etree.xsd @@ -337,4 +337,3 @@ </xs:complexType> </xs:schema> - diff --git a/tests/to_etree1_sup.py b/tests/to_etree1_sup.py index 8d7435a..4fe09cd 100644 --- a/tests/to_etree1_sup.py +++ b/tests/to_etree1_sup.py @@ -31,6 +31,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -924,6 +929,7 @@ class personType(GeneratedsSuper): self.promoter = promoter self.description = description self.range_ = range_ + self.validate_RangeType(self.range_) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if personType.subclass: @@ -970,7 +976,8 @@ class personType(GeneratedsSuper): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_RangeType(self, value): # Validate type RangeType, a restriction on xs:integer. - pass + if value is not None and Validate_simpletypes_: + pass def hasContent_(self): if ( self.name is not None or @@ -1212,6 +1219,7 @@ class programmerType(personType): self.ellong = ellong self.elparam = elparam self.elarraytypes = elarraytypes + self.validate_ArrayTypes(self.elarraytypes) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if programmerType.subclass: @@ -1261,7 +1269,15 @@ class programmerType(personType): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_ArrayTypes(self, value): # Validate type ArrayTypes, a restriction on xs:NMTOKEN. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on ArrayTypes' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.email is not None or @@ -1532,7 +1548,8 @@ class paramType(GeneratedsSuper): def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_ def validate_FlowType(self, value): # Validate type FlowType, a restriction on xs:integer. - pass + if value is not None and Validate_simpletypes_: + pass def hasContent_(self): if ( self.valueOf_ @@ -1624,6 +1641,7 @@ class python_programmerType(programmerType): self.gui_developer = _cast(bool, gui_developer) self.favorite_editor = favorite_editor self.flowvalue = flowvalue + self.validate_FlowType(self.flowvalue) self.drcs = drcs def factory(*args_, **kwargs_): if python_programmerType.subclass: @@ -1645,7 +1663,8 @@ class python_programmerType(programmerType): def set_gui_developer(self, gui_developer): self.gui_developer = gui_developer def validate_FlowType(self, value): # Validate type FlowType, a restriction on xs:integer. - pass + if value is not None and Validate_simpletypes_: + pass def hasContent_(self): if ( self.favorite_editor is not None or diff --git a/tests/to_etree2_sup.py b/tests/to_etree2_sup.py index 8d7435a..4fe09cd 100644 --- a/tests/to_etree2_sup.py +++ b/tests/to_etree2_sup.py @@ -31,6 +31,11 @@ import getopt import re as re_ import base64 import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + etree_ = None Verbose_import_ = False @@ -924,6 +929,7 @@ class personType(GeneratedsSuper): self.promoter = promoter self.description = description self.range_ = range_ + self.validate_RangeType(self.range_) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if personType.subclass: @@ -970,7 +976,8 @@ class personType(GeneratedsSuper): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_RangeType(self, value): # Validate type RangeType, a restriction on xs:integer. - pass + if value is not None and Validate_simpletypes_: + pass def hasContent_(self): if ( self.name is not None or @@ -1212,6 +1219,7 @@ class programmerType(personType): self.ellong = ellong self.elparam = elparam self.elarraytypes = elarraytypes + self.validate_ArrayTypes(self.elarraytypes) self.extensiontype_ = extensiontype_ def factory(*args_, **kwargs_): if programmerType.subclass: @@ -1261,7 +1269,15 @@ class programmerType(personType): def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_ def validate_ArrayTypes(self, value): # Validate type ArrayTypes, a restriction on xs:NMTOKEN. - pass + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on ArrayTypes' % {"value" : value.encode("utf-8")} ) def hasContent_(self): if ( self.email is not None or @@ -1532,7 +1548,8 @@ class paramType(GeneratedsSuper): def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_ def validate_FlowType(self, value): # Validate type FlowType, a restriction on xs:integer. - pass + if value is not None and Validate_simpletypes_: + pass def hasContent_(self): if ( self.valueOf_ @@ -1624,6 +1641,7 @@ class python_programmerType(programmerType): self.gui_developer = _cast(bool, gui_developer) self.favorite_editor = favorite_editor self.flowvalue = flowvalue + self.validate_FlowType(self.flowvalue) self.drcs = drcs def factory(*args_, **kwargs_): if python_programmerType.subclass: @@ -1645,7 +1663,8 @@ class python_programmerType(programmerType): def set_gui_developer(self, gui_developer): self.gui_developer = gui_developer def validate_FlowType(self, value): # Validate type FlowType, a restriction on xs:integer. - pass + if value is not None and Validate_simpletypes_: + pass def hasContent_(self): if ( self.favorite_editor is not None or diff --git a/tests/validate_simpletypes.xml b/tests/validate_simpletypes.xml new file mode 100644 index 0000000..a4d15e9 --- /dev/null +++ b/tests/validate_simpletypes.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<container> + <sample1> + <token_enum_value>float</token_enum_value> + <integer_range_incl_value>2</integer_range_incl_value> + <integer_range_excl_value>7</integer_range_excl_value> + <min_max_length_value>abc def ghi</min_max_length_value> + <length_value>0123456789</length_value> + <totaldigits_value>12.456</totaldigits_value> + <anonymous_float_value>2.2</anonymous_float_value> + </sample1> + <sample2_bad> + <token_enum_value>floatxx</token_enum_value> + <integer_range_incl_value>22</integer_range_incl_value> + <integer_range_excl_value>-40</integer_range_excl_value> + <min_max_length_value>mno pqr</min_max_length_value> + <length_value>012345</length_value> + <totaldigits_value>12.456789</totaldigits_value> + <anonymous_float_value>0.2</anonymous_float_value> + </sample2_bad> + <sample3_bad> + <integer_range_incl_value>-50</integer_range_incl_value> + <min_max_length_value>asdf asdf asdf adf asdf asdf</min_max_length_value> + <length_value>01234567890</length_value> + <totaldigits_value>12345678.45678901</totaldigits_value> + <anonymous_float_value>6.6</anonymous_float_value> + </sample3_bad> +</container> diff --git a/tests/validate_simpletypes.xsd b/tests/validate_simpletypes.xsd new file mode 100644 index 0000000..35b3598 --- /dev/null +++ b/tests/validate_simpletypes.xsd @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <xs:element name="container" type="containerType"/> + + <xs:complexType name="containerType"> + <xs:sequence> + <xs:element name="sample1" type="simpleOneType" maxOccurs="unbounded"/> + <xs:element name="sample2_bad" type="simpleOneType" maxOccurs="unbounded"/> + <xs:element name="sample3_bad" type="simpleOneType" maxOccurs="unbounded"/> + <xs:element name="sample2" type="simpleTwoType" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="simpleOneType" mixed="0"> + <xs:sequence> + <xs:element name="token_enum_value" type="token_enum_st"/> + <xs:element name="token_enum_value" type="token_enum_st"/> + <xs:element name="integer_range_incl_value" type="integer_range_incl_st"/> + <xs:element name="integer_range_excl_value" type="integer_range_excl_st"/> + <xs:element name="min_max_length_value" type="min_max_length_st"/> + <xs:element name="length_value" type="length_st"/> + <xs:element name="totaldigits_value" type="totaldigits_st"/> + <!-- Test for use of anonymous simple type. --> + <xs:element name="anonymous_float_value"> + <xs:simpleType> + <xs:restriction base="xs:float"> + <xs:minInclusive value="1.1"/> + <xs:maxInclusive value="4.4"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + </xs:sequence> + </xs:complexType> + <!-- Test for use of an anonymous simple type inside an anonymous complexType. --> + <xs:element name="simpleTwoType"> + <xs:complexType> + <xs:sequence> + <xs:element name="Foo"> + <xs:complexType> + <xs:all> + <xs:element name="FooType"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="12"/> + <xs:maxLength value="24"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + </xs:all> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:simpleType name="token_enum_st"> + <xs:restriction base="xs:NMTOKEN"> + <xs:enumeration value="float"/> + <xs:enumeration value="int"/> + <xs:enumeration value="Name"/> + <xs:enumeration value="token"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="integer_range_incl_st"> + <xs:restriction base="xs:integer"> + <xs:minInclusive value="-5"/> + <xs:maxInclusive value="10"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="integer_range_excl_st"> + <xs:restriction base="xs:integer"> + <xs:minExclusive value="-5"/> + <xs:maxExclusive value="10"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="min_max_length_st"> + <xs:restriction base="xs:string"> + <xs:minLength value="10"/> + <xs:maxLength value="20"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="length_st"> + <xs:restriction base="xs:string"> + <xs:length value="10"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="totaldigits_st"> + <xs:restriction base="xs:float"> + <xs:totalDigits value="15"/> + <xs:fractionDigits value="5"/> + </xs:restriction> + </xs:simpleType> +</xs:schema> diff --git a/tests/validate_simpletypes1_out.xml b/tests/validate_simpletypes1_out.xml new file mode 100644 index 0000000..70c8feb --- /dev/null +++ b/tests/validate_simpletypes1_out.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" ?> +<container> + <sample1> + <token_enum_value>float</token_enum_value> + <token_enum_value>float</token_enum_value> + <integer_range_incl_value>2</integer_range_incl_value> + <integer_range_excl_value>7</integer_range_excl_value> + <min_max_length_value>abc def ghi</min_max_length_value> + <length_value>0123456789</length_value> + <totaldigits_value>12.456</totaldigits_value> + <anonymous_float_value>2.2</anonymous_float_value> + </sample1> + <sample2_bad> + <token_enum_value>floatxx</token_enum_value> + <token_enum_value>floatxx</token_enum_value> + <integer_range_incl_value>22</integer_range_incl_value> + <integer_range_excl_value>-40</integer_range_excl_value> + <min_max_length_value>mno pqr</min_max_length_value> + <length_value>012345</length_value> + <totaldigits_value>12.456789000000001</totaldigits_value> + <anonymous_float_value>0.2</anonymous_float_value> + </sample2_bad> + <sample3_bad> + <integer_range_incl_value>-50</integer_range_incl_value> + <min_max_length_value>asdf asdf asdf adf asdf asdf</min_max_length_value> + <length_value>01234567890</length_value> + <totaldigits_value>12345678.456789009273052</totaldigits_value> + <anonymous_float_value>6.6</anonymous_float_value> + </sample3_bad> +</container> diff --git a/tests/validate_simpletypes1_sub.py b/tests/validate_simpletypes1_sub.py new file mode 100644 index 0000000..6b50bce --- /dev/null +++ b/tests/validate_simpletypes1_sub.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/validate_simpletypes2_sup.py') +# ('-s', 'tests/validate_simpletypes2_sub.py') +# ('--super', 'validate_simpletypes2_sup') +# +# Command line arguments: +# tests/validate_simpletypes.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --member-specs="list" -f -o "tests/validate_simpletypes2_sup.py" -s "tests/validate_simpletypes2_sub.py" --super="validate_simpletypes2_sup" tests/validate_simpletypes.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys + +import validate_simpletypes2_sup as supermod + +etree_ = None +Verbose_import_ = False +( + XMLParser_import_none, XMLParser_import_lxml, + XMLParser_import_elementtree +) = range(3) +XMLParser_import_library = None +try: + # lxml + from lxml import etree as etree_ + XMLParser_import_library = XMLParser_import_lxml + if Verbose_import_: + print("running with lxml.etree") +except ImportError: + try: + # cElementTree from Python 2.5+ + import xml.etree.cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree on Python 2.5+") + except ImportError: + try: + # ElementTree from Python 2.5+ + import xml.etree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree on Python 2.5+") + except ImportError: + try: + # normal cElementTree install + import cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree") + except ImportError: + try: + # normal ElementTree install + import elementtree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree") + except ImportError: + raise ImportError( + "Failed to import ElementTree from any known place") + + +def parsexml_(*args, **kwargs): + if (XMLParser_import_library == XMLParser_import_lxml and + 'parser' not in kwargs): + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + kwargs['parser'] = etree_.ETCompatXMLParser() + doc = etree_.parse(*args, **kwargs) + return doc + +# +# Globals +# + +ExternalEncoding = 'ascii' + +# +# Data representation classes +# + + +class containerTypeSub(supermod.containerType): + def __init__(self, sample1=None, sample2_bad=None, sample3_bad=None, sample2=None): + super(containerTypeSub, self).__init__(sample1, sample2_bad, sample3_bad, sample2, ) +supermod.containerType.subclass = containerTypeSub +# end class containerTypeSub + + +class simpleOneTypeSub(supermod.simpleOneType): + def __init__(self, token_enum_value=None, integer_range_incl_value=None, integer_range_excl_value=None, min_max_length_value=None, length_value=None, totaldigits_value=None, anonymous_float_value=None): + super(simpleOneTypeSub, self).__init__(token_enum_value, integer_range_incl_value, integer_range_excl_value, min_max_length_value, length_value, totaldigits_value, anonymous_float_value, ) +supermod.simpleOneType.subclass = simpleOneTypeSub +# end class simpleOneTypeSub + + +class simpleTwoTypeSub(supermod.simpleTwoType): + def __init__(self, Foo=None): + super(simpleTwoTypeSub, self).__init__(Foo, ) +supermod.simpleTwoType.subclass = simpleTwoTypeSub +# end class simpleTwoTypeSub + + +class FooType1Sub(supermod.FooType1): + def __init__(self, FooType=None): + super(FooType1Sub, self).__init__(FooType, ) +supermod.FooType1.subclass = FooType1Sub +# end class FooType1Sub + + +def get_root_tag(node): + tag = supermod.Tag_pattern_.match(node.tag).groups()[-1] + rootClass = None + rootClass = supermod.GDSClassesMapping.get(tag) + if rootClass is None and hasattr(supermod, tag): + rootClass = getattr(supermod, tag) + return tag, rootClass + + +def parse(inFilename, silence=False): + doc = parsexml_(inFilename) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='', + pretty_print=True) + return rootObj + + +def parseEtree(inFilename, silence=False): + doc = parsexml_(inFilename) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) + if not silence: + content = etree_.tostring( + rootElement, pretty_print=True, + xml_declaration=True, encoding="utf-8") + sys.stdout.write(content) + sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + doc = parsexml_(StringIO(inString)) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='') + return rootObj + + +def parseLiteral(inFilename, silence=False): + doc = parsexml_(inFilename) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('#from validate_simpletypes2_sup import *\n\n') + sys.stdout.write('import validate_simpletypes2_sup as model_\n\n') + sys.stdout.write('rootObj = model_.rootClass(\n') + rootObj.exportLiteral(sys.stdout, 0, name_=rootTag) + sys.stdout.write(')\n') + return rootObj + + +USAGE_TEXT = """ +Usage: python ???.py <infilename> +""" + + +def usage(): + print USAGE_TEXT + sys.exit(1) + + +def main(): + args = sys.argv[1:] + if len(args) != 1: + usage() + infilename = args[0] + parse(infilename) + + +if __name__ == '__main__': + #import pdb; pdb.set_trace() + main() diff --git a/tests/validate_simpletypes1_sup.py b/tests/validate_simpletypes1_sup.py new file mode 100644 index 0000000..77d9886 --- /dev/null +++ b/tests/validate_simpletypes1_sup.py @@ -0,0 +1,1396 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/validate_simpletypes2_sup.py') +# ('-s', 'tests/validate_simpletypes2_sub.py') +# ('--super', 'validate_simpletypes2_sup') +# +# Command line arguments: +# tests/validate_simpletypes.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --member-specs="list" -f -o "tests/validate_simpletypes2_sup.py" -s "tests/validate_simpletypes2_sub.py" --super="validate_simpletypes2_sup" tests/validate_simpletypes.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys +import getopt +import re as re_ +import base64 +import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + + +etree_ = None +Verbose_import_ = False +( + XMLParser_import_none, XMLParser_import_lxml, + XMLParser_import_elementtree +) = range(3) +XMLParser_import_library = None +try: + # lxml + from lxml import etree as etree_ + XMLParser_import_library = XMLParser_import_lxml + if Verbose_import_: + print("running with lxml.etree") +except ImportError: + try: + # cElementTree from Python 2.5+ + import xml.etree.cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree on Python 2.5+") + except ImportError: + try: + # ElementTree from Python 2.5+ + import xml.etree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree on Python 2.5+") + except ImportError: + try: + # normal cElementTree install + import cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree") + except ImportError: + try: + # normal ElementTree install + import elementtree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree") + except ImportError: + raise ImportError( + "Failed to import ElementTree from any known place") + + +def parsexml_(*args, **kwargs): + if (XMLParser_import_library == XMLParser_import_lxml and + 'parser' not in kwargs): + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + kwargs['parser'] = etree_.ETCompatXMLParser() + doc = etree_.parse(*args, **kwargs) + return doc + +# +# User methods +# +# Calls to the methods in these classes are generated by generateDS.py. +# You can replace these methods by re-implementing the following class +# in a module named generatedssuper.py. + +try: + from generatedssuper import GeneratedsSuper +except ImportError, exp: + + class GeneratedsSuper(object): + tzoff_pattern = re_.compile(r'(\+|-)((0\d|1[0-3]):[0-5]\d|14:00)$') + class _FixedOffsetTZ(datetime_.tzinfo): + def __init__(self, offset, name): + self.__offset = datetime_.timedelta(minutes=offset) + self.__name = name + def utcoffset(self, dt): + return self.__offset + def tzname(self, dt): + return self.__name + def dst(self, dt): + return None + def gds_format_string(self, input_data, input_name=''): + return input_data + def gds_validate_string(self, input_data, node, input_name=''): + if not input_data: + return '' + else: + return input_data + def gds_format_base64(self, input_data, input_name=''): + return base64.b64encode(input_data) + def gds_validate_base64(self, input_data, node, input_name=''): + return input_data + def gds_format_integer(self, input_data, input_name=''): + return '%d' % input_data + def gds_validate_integer(self, input_data, node, input_name=''): + return input_data + def gds_format_integer_list(self, input_data, input_name=''): + return '%s' % ' '.join(input_data) + def gds_validate_integer_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + try: + float(value) + except (TypeError, ValueError): + raise_parse_error(node, 'Requires sequence of integers') + return values + def gds_format_float(self, input_data, input_name=''): + return ('%.15f' % input_data).rstrip('0') + def gds_validate_float(self, input_data, node, input_name=''): + return input_data + def gds_format_float_list(self, input_data, input_name=''): + return '%s' % ' '.join(input_data) + def gds_validate_float_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + try: + float(value) + except (TypeError, ValueError): + raise_parse_error(node, 'Requires sequence of floats') + return values + def gds_format_double(self, input_data, input_name=''): + return '%e' % input_data + def gds_validate_double(self, input_data, node, input_name=''): + return input_data + def gds_format_double_list(self, input_data, input_name=''): + return '%s' % ' '.join(input_data) + def gds_validate_double_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + try: + float(value) + except (TypeError, ValueError): + raise_parse_error(node, 'Requires sequence of doubles') + return values + def gds_format_boolean(self, input_data, input_name=''): + return ('%s' % input_data).lower() + def gds_validate_boolean(self, input_data, node, input_name=''): + return input_data + def gds_format_boolean_list(self, input_data, input_name=''): + return '%s' % ' '.join(input_data) + def gds_validate_boolean_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + if value not in ('true', '1', 'false', '0', ): + raise_parse_error( + node, + 'Requires sequence of booleans ' + '("true", "1", "false", "0")') + return values + def gds_validate_datetime(self, input_data, node, input_name=''): + return input_data + def gds_format_datetime(self, input_data, input_name=''): + if input_data.microsecond == 0: + _svalue = '%04d-%02d-%02dT%02d:%02d:%02d' % ( + input_data.year, + input_data.month, + input_data.day, + input_data.hour, + input_data.minute, + input_data.second, + ) + else: + _svalue = '%04d-%02d-%02dT%02d:%02d:%02d.%s' % ( + input_data.year, + input_data.month, + input_data.day, + input_data.hour, + input_data.minute, + input_data.second, + ('%f' % (float(input_data.microsecond) / 1000000))[2:], + ) + if input_data.tzinfo is not None: + tzoff = input_data.tzinfo.utcoffset(input_data) + if tzoff is not None: + total_seconds = tzoff.seconds + (86400 * tzoff.days) + if total_seconds == 0: + _svalue += 'Z' + else: + if total_seconds < 0: + _svalue += '-' + total_seconds *= -1 + else: + _svalue += '+' + hours = total_seconds // 3600 + minutes = (total_seconds - (hours * 3600)) // 60 + _svalue += '{0:02d}:{1:02d}'.format(hours, minutes) + return _svalue + @classmethod + def gds_parse_datetime(cls, input_data): + tz = None + if input_data[-1] == 'Z': + tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC') + input_data = input_data[:-1] + else: + results = GeneratedsSuper.tzoff_pattern.search(input_data) + if results is not None: + tzoff_parts = results.group(2).split(':') + tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1]) + if results.group(1) == '-': + tzoff *= -1 + tz = GeneratedsSuper._FixedOffsetTZ( + tzoff, results.group(0)) + input_data = input_data[:-6] + time_parts = input_data.split('.') + if len(time_parts) > 1: + micro_seconds = int(float('0.' + time_parts[1]) * 1000000) + input_data = '%s.%s' % (time_parts[0], micro_seconds, ) + dt = datetime_.datetime.strptime( + input_data, '%Y-%m-%dT%H:%M:%S.%f') + else: + dt = datetime_.datetime.strptime( + input_data, '%Y-%m-%dT%H:%M:%S') + dt = dt.replace(tzinfo=tz) + return dt + def gds_validate_date(self, input_data, node, input_name=''): + return input_data + def gds_format_date(self, input_data, input_name=''): + _svalue = '%04d-%02d-%02d' % ( + input_data.year, + input_data.month, + input_data.day, + ) + try: + if input_data.tzinfo is not None: + tzoff = input_data.tzinfo.utcoffset(input_data) + if tzoff is not None: + total_seconds = tzoff.seconds + (86400 * tzoff.days) + if total_seconds == 0: + _svalue += 'Z' + else: + if total_seconds < 0: + _svalue += '-' + total_seconds *= -1 + else: + _svalue += '+' + hours = total_seconds // 3600 + minutes = (total_seconds - (hours * 3600)) // 60 + _svalue += '{0:02d}:{1:02d}'.format(hours, minutes) + except AttributeError: + pass + return _svalue + @classmethod + def gds_parse_date(cls, input_data): + tz = None + if input_data[-1] == 'Z': + tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC') + input_data = input_data[:-1] + else: + results = GeneratedsSuper.tzoff_pattern.search(input_data) + if results is not None: + tzoff_parts = results.group(2).split(':') + tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1]) + if results.group(1) == '-': + tzoff *= -1 + tz = GeneratedsSuper._FixedOffsetTZ( + tzoff, results.group(0)) + input_data = input_data[:-6] + dt = datetime_.datetime.strptime(input_data, '%Y-%m-%d') + dt = dt.replace(tzinfo=tz) + return dt.date() + def gds_validate_time(self, input_data, node, input_name=''): + return input_data + def gds_format_time(self, input_data, input_name=''): + if input_data.microsecond == 0: + _svalue = '%02d:%02d:%02d' % ( + input_data.hour, + input_data.minute, + input_data.second, + ) + else: + _svalue = '%02d:%02d:%02d.%s' % ( + input_data.hour, + input_data.minute, + input_data.second, + ('%f' % (float(input_data.microsecond) / 1000000))[2:], + ) + if input_data.tzinfo is not None: + tzoff = input_data.tzinfo.utcoffset(input_data) + if tzoff is not None: + total_seconds = tzoff.seconds + (86400 * tzoff.days) + if total_seconds == 0: + _svalue += 'Z' + else: + if total_seconds < 0: + _svalue += '-' + total_seconds *= -1 + else: + _svalue += '+' + hours = total_seconds // 3600 + minutes = (total_seconds - (hours * 3600)) // 60 + _svalue += '{0:02d}:{1:02d}'.format(hours, minutes) + return _svalue + @classmethod + def gds_parse_time(cls, input_data): + tz = None + if input_data[-1] == 'Z': + tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC') + input_data = input_data[:-1] + else: + results = GeneratedsSuper.tzoff_pattern.search(input_data) + if results is not None: + tzoff_parts = results.group(2).split(':') + tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1]) + if results.group(1) == '-': + tzoff *= -1 + tz = GeneratedsSuper._FixedOffsetTZ( + tzoff, results.group(0)) + input_data = input_data[:-6] + if len(input_data.split('.')) > 1: + dt = datetime_.datetime.strptime(input_data, '%H:%M:%S.%f') + else: + dt = datetime_.datetime.strptime(input_data, '%H:%M:%S') + dt = dt.replace(tzinfo=tz) + return dt.time() + def gds_str_lower(self, instring): + return instring.lower() + def get_path_(self, node): + path_list = [] + self.get_path_list_(node, path_list) + path_list.reverse() + path = '/'.join(path_list) + return path + Tag_strip_pattern_ = re_.compile(r'\{.*\}') + def get_path_list_(self, node, path_list): + if node is None: + return + tag = GeneratedsSuper.Tag_strip_pattern_.sub('', node.tag) + if tag: + path_list.append(tag) + self.get_path_list_(node.getparent(), path_list) + def get_class_obj_(self, node, default_class=None): + class_obj1 = default_class + if 'xsi' in node.nsmap: + classname = node.get('{%s}type' % node.nsmap['xsi']) + if classname is not None: + names = classname.split(':') + if len(names) == 2: + classname = names[1] + class_obj2 = globals().get(classname) + if class_obj2 is not None: + class_obj1 = class_obj2 + return class_obj1 + def gds_build_any(self, node, type_name=None): + return None + @classmethod + def gds_reverse_node_mapping(cls, mapping): + return dict(((v, k) for k, v in mapping.iteritems())) + + +# +# If you have installed IPython you can uncomment and use the following. +# IPython is available from http://ipython.scipy.org/. +# + +## from IPython.Shell import IPShellEmbed +## args = '' +## ipshell = IPShellEmbed(args, +## banner = 'Dropping into IPython', +## exit_msg = 'Leaving Interpreter, back to program.') + +# Then use the following line where and when you want to drop into the +# IPython shell: +# ipshell('<some message> -- Entering ipshell.\nHit Ctrl-D to exit') + +# +# Globals +# + +ExternalEncoding = 'ascii' +Tag_pattern_ = re_.compile(r'({.*})?(.*)') +String_cleanup_pat_ = re_.compile(r"[\n\r\s]+") +Namespace_extract_pat_ = re_.compile(r'{(.*)}(.*)') + +# +# Support/utility functions. +# + + +def showIndent(outfile, level, pretty_print=True): + if pretty_print: + for idx in range(level): + outfile.write(' ') + + +def quote_xml(inStr): + if not inStr: + return '' + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + return s1 + + +def quote_attrib(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + if '"' in s1: + if "'" in s1: + s1 = '"%s"' % s1.replace('"', """) + else: + s1 = "'%s'" % s1 + else: + s1 = '"%s"' % s1 + return s1 + + +def quote_python(inStr): + s1 = inStr + if s1.find("'") == -1: + if s1.find('\n') == -1: + return "'%s'" % s1 + else: + return "'''%s'''" % s1 + else: + if s1.find('"') != -1: + s1 = s1.replace('"', '\\"') + if s1.find('\n') == -1: + return '"%s"' % s1 + else: + return '"""%s"""' % s1 + + +def get_all_text_(node): + if node.text is not None: + text = node.text + else: + text = '' + for child in node: + if child.tail is not None: + text += child.tail + return text + + +def find_attr_value_(attr_name, node): + attrs = node.attrib + attr_parts = attr_name.split(':') + value = None + if len(attr_parts) == 1: + value = attrs.get(attr_name) + elif len(attr_parts) == 2: + prefix, name = attr_parts + namespace = node.nsmap.get(prefix) + if namespace is not None: + value = attrs.get('{%s}%s' % (namespace, name, )) + return value + + +class GDSParseError(Exception): + pass + + +def raise_parse_error(node, msg): + if XMLParser_import_library == XMLParser_import_lxml: + msg = '%s (element %s/line %d)' % ( + msg, node.tag, node.sourceline, ) + else: + msg = '%s (element %s)' % (msg, node.tag, ) + raise GDSParseError(msg) + + +class MixedContainer: + # Constants for category: + CategoryNone = 0 + CategoryText = 1 + CategorySimple = 2 + CategoryComplex = 3 + # Constants for content_type: + TypeNone = 0 + TypeText = 1 + TypeString = 2 + TypeInteger = 3 + TypeFloat = 4 + TypeDecimal = 5 + TypeDouble = 6 + TypeBoolean = 7 + TypeBase64 = 8 + def __init__(self, category, content_type, name, value): + self.category = category + self.content_type = content_type + self.name = name + self.value = value + def getCategory(self): + return self.category + def getContenttype(self, content_type): + return self.content_type + def getValue(self): + return self.value + def getName(self): + return self.name + def export(self, outfile, level, name, namespace, pretty_print=True): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + outfile.write(self.value) + elif self.category == MixedContainer.CategorySimple: + self.exportSimple(outfile, level, name) + else: # category == MixedContainer.CategoryComplex + self.value.export(outfile, level, namespace, name, pretty_print) + def exportSimple(self, outfile, level, name): + if self.content_type == MixedContainer.TypeString: + outfile.write('<%s>%s</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeInteger or \ + self.content_type == MixedContainer.TypeBoolean: + outfile.write('<%s>%d</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeFloat or \ + self.content_type == MixedContainer.TypeDecimal: + outfile.write('<%s>%f</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeDouble: + outfile.write('<%s>%g</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeBase64: + outfile.write('<%s>%s</%s>' % ( + self.name, base64.b64encode(self.value), self.name)) + def to_etree(self, element): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + if len(element) > 0: + if element[-1].tail is None: + element[-1].tail = self.value + else: + element[-1].tail += self.value + else: + if element.text is None: + element.text = self.value + else: + element.text += self.value + elif self.category == MixedContainer.CategorySimple: + subelement = etree_.SubElement(element, '%s' % self.name) + subelement.text = self.to_etree_simple() + else: # category == MixedContainer.CategoryComplex + self.value.to_etree(element) + def to_etree_simple(self): + if self.content_type == MixedContainer.TypeString: + text = self.value + elif (self.content_type == MixedContainer.TypeInteger or + self.content_type == MixedContainer.TypeBoolean): + text = '%d' % self.value + elif (self.content_type == MixedContainer.TypeFloat or + self.content_type == MixedContainer.TypeDecimal): + text = '%f' % self.value + elif self.content_type == MixedContainer.TypeDouble: + text = '%g' % self.value + elif self.content_type == MixedContainer.TypeBase64: + text = '%s' % base64.b64encode(self.value) + return text + def exportLiteral(self, outfile, level, name): + if self.category == MixedContainer.CategoryText: + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % ( + self.category, self.content_type, self.name, self.value)) + elif self.category == MixedContainer.CategorySimple: + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % ( + self.category, self.content_type, self.name, self.value)) + else: # category == MixedContainer.CategoryComplex + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s",\n' % ( + self.category, self.content_type, self.name,)) + self.value.exportLiteral(outfile, level + 1) + showIndent(outfile, level) + outfile.write(')\n') + + +class MemberSpec_(object): + def __init__(self, name='', data_type='', container=0): + self.name = name + self.data_type = data_type + self.container = container + def set_name(self, name): self.name = name + def get_name(self): return self.name + def set_data_type(self, data_type): self.data_type = data_type + def get_data_type_chain(self): return self.data_type + def get_data_type(self): + if isinstance(self.data_type, list): + if len(self.data_type) > 0: + return self.data_type[-1] + else: + return 'xs:string' + else: + return self.data_type + def set_container(self, container): self.container = container + def get_container(self): return self.container + + +def _cast(typ, value): + if typ is None or value is None: + return value + return typ(value) + +# +# Data representation classes. +# + + +class containerType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('sample1', 'simpleOneType', 1), + MemberSpec_('sample2_bad', 'simpleOneType', 1), + MemberSpec_('sample3_bad', 'simpleOneType', 1), + MemberSpec_('sample2', 'simpleTwoType', 1), + ] + subclass = None + superclass = None + def __init__(self, sample1=None, sample2_bad=None, sample3_bad=None, sample2=None): + self.original_tagname_ = None + if sample1 is None: + self.sample1 = [] + else: + self.sample1 = sample1 + if sample2_bad is None: + self.sample2_bad = [] + else: + self.sample2_bad = sample2_bad + if sample3_bad is None: + self.sample3_bad = [] + else: + self.sample3_bad = sample3_bad + if sample2 is None: + self.sample2 = [] + else: + self.sample2 = sample2 + def factory(*args_, **kwargs_): + if containerType.subclass: + return containerType.subclass(*args_, **kwargs_) + else: + return containerType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_sample1(self): return self.sample1 + def set_sample1(self, sample1): self.sample1 = sample1 + def add_sample1(self, value): self.sample1.append(value) + def insert_sample1_at(self, index, value): self.sample1.insert(index, value) + def replace_sample1_at(self, index, value): self.sample1[index] = value + def get_sample2_bad(self): return self.sample2_bad + def set_sample2_bad(self, sample2_bad): self.sample2_bad = sample2_bad + def add_sample2_bad(self, value): self.sample2_bad.append(value) + def insert_sample2_bad_at(self, index, value): self.sample2_bad.insert(index, value) + def replace_sample2_bad_at(self, index, value): self.sample2_bad[index] = value + def get_sample3_bad(self): return self.sample3_bad + def set_sample3_bad(self, sample3_bad): self.sample3_bad = sample3_bad + def add_sample3_bad(self, value): self.sample3_bad.append(value) + def insert_sample3_bad_at(self, index, value): self.sample3_bad.insert(index, value) + def replace_sample3_bad_at(self, index, value): self.sample3_bad[index] = value + def get_sample2(self): return self.sample2 + def set_sample2(self, sample2): self.sample2 = sample2 + def add_sample2(self, value): self.sample2.append(value) + def insert_sample2_at(self, index, value): self.sample2.insert(index, value) + def replace_sample2_at(self, index, value): self.sample2[index] = value + def hasContent_(self): + if ( + self.sample1 or + self.sample2_bad or + self.sample3_bad or + self.sample2 + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='containerType', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='containerType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='containerType', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='containerType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='containerType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + for sample1_ in self.sample1: + sample1_.export(outfile, level, namespace_, name_='sample1', pretty_print=pretty_print) + for sample2_bad_ in self.sample2_bad: + sample2_bad_.export(outfile, level, namespace_, name_='sample2_bad', pretty_print=pretty_print) + for sample3_bad_ in self.sample3_bad: + sample3_bad_.export(outfile, level, namespace_, name_='sample3_bad', pretty_print=pretty_print) + for sample2_ in self.sample2: + sample2_.export(outfile, level, namespace_, name_='sample2', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='containerType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('sample1=[\n') + level += 1 + for sample1_ in self.sample1: + showIndent(outfile, level) + outfile.write('model_.simpleOneType(\n') + sample1_.exportLiteral(outfile, level, name_='simpleOneType') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('sample2_bad=[\n') + level += 1 + for sample2_bad_ in self.sample2_bad: + showIndent(outfile, level) + outfile.write('model_.simpleOneType(\n') + sample2_bad_.exportLiteral(outfile, level, name_='simpleOneType') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('sample3_bad=[\n') + level += 1 + for sample3_bad_ in self.sample3_bad: + showIndent(outfile, level) + outfile.write('model_.simpleOneType(\n') + sample3_bad_.exportLiteral(outfile, level, name_='simpleOneType') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('sample2=[\n') + level += 1 + for sample2_ in self.sample2: + showIndent(outfile, level) + outfile.write('model_.simpleTwoType(\n') + sample2_.exportLiteral(outfile, level, name_='simpleTwoType') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'sample1': + obj_ = simpleOneType.factory() + obj_.build(child_) + self.sample1.append(obj_) + obj_.original_tagname_ = 'sample1' + elif nodeName_ == 'sample2_bad': + obj_ = simpleOneType.factory() + obj_.build(child_) + self.sample2_bad.append(obj_) + obj_.original_tagname_ = 'sample2_bad' + elif nodeName_ == 'sample3_bad': + obj_ = simpleOneType.factory() + obj_.build(child_) + self.sample3_bad.append(obj_) + obj_.original_tagname_ = 'sample3_bad' + elif nodeName_ == 'sample2': + obj_ = simpleTwoType.factory() + obj_.build(child_) + self.sample2.append(obj_) + obj_.original_tagname_ = 'sample2' +# end class containerType + + +class simpleOneType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('token_enum_value', ['token_enum_st', 'xs:NMTOKEN'], 0), + MemberSpec_('token_enum_value', ['token_enum_st', 'xs:NMTOKEN'], 0), + MemberSpec_('integer_range_incl_value', ['integer_range_incl_st', 'xs:integer'], 0), + MemberSpec_('integer_range_excl_value', ['integer_range_excl_st', 'xs:integer'], 0), + MemberSpec_('min_max_length_value', ['min_max_length_st', 'xs:string'], 0), + MemberSpec_('length_value', ['length_st', 'xs:string'], 0), + MemberSpec_('totaldigits_value', ['totaldigits_st', 'xs:float'], 0), + MemberSpec_('anonymous_float_value', ['anonymous_float_valueType', 'xs:float'], 0), + ] + subclass = None + superclass = None + def __init__(self, token_enum_value=None, integer_range_incl_value=None, integer_range_excl_value=None, min_max_length_value=None, length_value=None, totaldigits_value=None, anonymous_float_value=None): + self.original_tagname_ = None + self.token_enum_value = token_enum_value + self.validate_token_enum_st(self.token_enum_value) + self.token_enum_value = token_enum_value + self.validate_token_enum_st(self.token_enum_value) + self.integer_range_incl_value = integer_range_incl_value + self.validate_integer_range_incl_st(self.integer_range_incl_value) + self.integer_range_excl_value = integer_range_excl_value + self.validate_integer_range_excl_st(self.integer_range_excl_value) + self.min_max_length_value = min_max_length_value + self.validate_min_max_length_st(self.min_max_length_value) + self.length_value = length_value + self.validate_length_st(self.length_value) + self.totaldigits_value = totaldigits_value + self.validate_totaldigits_st(self.totaldigits_value) + self.anonymous_float_value = anonymous_float_value + self.validate_anonymous_float_valueType(self.anonymous_float_value) + def factory(*args_, **kwargs_): + if simpleOneType.subclass: + return simpleOneType.subclass(*args_, **kwargs_) + else: + return simpleOneType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_token_enum_value(self): return self.token_enum_value + def set_token_enum_value(self, token_enum_value): self.token_enum_value = token_enum_value + def get_token_enum_value(self): return self.token_enum_value + def set_token_enum_value(self, token_enum_value): self.token_enum_value = token_enum_value + def get_integer_range_incl_value(self): return self.integer_range_incl_value + def set_integer_range_incl_value(self, integer_range_incl_value): self.integer_range_incl_value = integer_range_incl_value + def get_integer_range_excl_value(self): return self.integer_range_excl_value + def set_integer_range_excl_value(self, integer_range_excl_value): self.integer_range_excl_value = integer_range_excl_value + def get_min_max_length_value(self): return self.min_max_length_value + def set_min_max_length_value(self, min_max_length_value): self.min_max_length_value = min_max_length_value + def get_length_value(self): return self.length_value + def set_length_value(self, length_value): self.length_value = length_value + def get_totaldigits_value(self): return self.totaldigits_value + def set_totaldigits_value(self, totaldigits_value): self.totaldigits_value = totaldigits_value + def get_anonymous_float_value(self): return self.anonymous_float_value + def set_anonymous_float_value(self, anonymous_float_value): self.anonymous_float_value = anonymous_float_value + def validate_token_enum_st(self, value): + # Validate type token_enum_st, a restriction on xs:NMTOKEN. + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on token_enum_st' % {"value" : value.encode("utf-8")} ) + def validate_integer_range_incl_st(self, value): + # Validate type integer_range_incl_st, a restriction on xs:integer. + if value is not None and Validate_simpletypes_: + if value <= -5: + warnings.warn('Value "%(value)s" does not match xsd minInclusive restriction on integer_range_incl_st' % {"value" : value} ) + if value >= 10: + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on integer_range_incl_st' % {"value" : value} ) + def validate_integer_range_excl_st(self, value): + # Validate type integer_range_excl_st, a restriction on xs:integer. + if value is not None and Validate_simpletypes_: + if value < -5: + warnings.warn('Value "%(value)s" does not match xsd minExclusive restriction on integer_range_excl_st' % {"value" : value} ) + if value > 10: + warnings.warn('Value "%(value)s" does not match xsd maxExclusive restriction on integer_range_excl_st' % {"value" : value} ) + def validate_min_max_length_st(self, value): + # Validate type min_max_length_st, a restriction on xs:string. + if value is not None and Validate_simpletypes_: + if len(value) < 10: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} ) + if len(value) > 20: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} ) + def validate_length_st(self, value): + # Validate type length_st, a restriction on xs:string. + if value is not None and Validate_simpletypes_: + if len(value) != 10: + warnings.warn('Value "%(value)s" does not match xsd length restriction on length_st' % {"value" : value.encode("utf-8")} ) + def validate_totaldigits_st(self, value): + # Validate type totaldigits_st, a restriction on xs:float. + if value is not None and Validate_simpletypes_: + if len(str(value)) >= 15: + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on totaldigits_st' % {"value" : value} ) + def validate_anonymous_float_valueType(self, value): + # Validate type anonymous_float_valueType, a restriction on xs:float. + if value is not None and Validate_simpletypes_: + if value <= 1.1: + warnings.warn('Value "%(value)s" does not match xsd minInclusive restriction on anonymous_float_valueType' % {"value" : value} ) + if value >= 4.4: + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on anonymous_float_valueType' % {"value" : value} ) + def hasContent_(self): + if ( + self.token_enum_value is not None or + self.token_enum_value is not None or + self.integer_range_incl_value is not None or + self.integer_range_excl_value is not None or + self.min_max_length_value is not None or + self.length_value is not None or + self.totaldigits_value is not None or + self.anonymous_float_value is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='simpleOneType', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='simpleOneType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='simpleOneType', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='simpleOneType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='simpleOneType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.token_enum_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%stoken_enum_value>%s</%stoken_enum_value>%s' % (namespace_, self.gds_format_string(quote_xml(self.token_enum_value).encode(ExternalEncoding), input_name='token_enum_value'), namespace_, eol_)) + if self.token_enum_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%stoken_enum_value>%s</%stoken_enum_value>%s' % (namespace_, self.gds_format_string(quote_xml(self.token_enum_value).encode(ExternalEncoding), input_name='token_enum_value'), namespace_, eol_)) + if self.integer_range_incl_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sinteger_range_incl_value>%s</%sinteger_range_incl_value>%s' % (namespace_, self.gds_format_integer(self.integer_range_incl_value, input_name='integer_range_incl_value'), namespace_, eol_)) + if self.integer_range_excl_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sinteger_range_excl_value>%s</%sinteger_range_excl_value>%s' % (namespace_, self.gds_format_integer(self.integer_range_excl_value, input_name='integer_range_excl_value'), namespace_, eol_)) + if self.min_max_length_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%smin_max_length_value>%s</%smin_max_length_value>%s' % (namespace_, self.gds_format_string(quote_xml(self.min_max_length_value).encode(ExternalEncoding), input_name='min_max_length_value'), namespace_, eol_)) + if self.length_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%slength_value>%s</%slength_value>%s' % (namespace_, self.gds_format_string(quote_xml(self.length_value).encode(ExternalEncoding), input_name='length_value'), namespace_, eol_)) + if self.totaldigits_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%stotaldigits_value>%s</%stotaldigits_value>%s' % (namespace_, self.gds_format_float(self.totaldigits_value, input_name='totaldigits_value'), namespace_, eol_)) + if self.anonymous_float_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sanonymous_float_value>%s</%sanonymous_float_value>%s' % (namespace_, self.gds_format_float(self.anonymous_float_value, input_name='anonymous_float_value'), namespace_, eol_)) + def exportLiteral(self, outfile, level, name_='simpleOneType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.token_enum_value is not None: + showIndent(outfile, level) + outfile.write('token_enum_value=%s,\n' % quote_python(self.token_enum_value).encode(ExternalEncoding)) + if self.token_enum_value is not None: + showIndent(outfile, level) + outfile.write('token_enum_value=%s,\n' % quote_python(self.token_enum_value).encode(ExternalEncoding)) + if self.integer_range_incl_value is not None: + showIndent(outfile, level) + outfile.write('integer_range_incl_value=%d,\n' % self.integer_range_incl_value) + if self.integer_range_excl_value is not None: + showIndent(outfile, level) + outfile.write('integer_range_excl_value=%d,\n' % self.integer_range_excl_value) + if self.min_max_length_value is not None: + showIndent(outfile, level) + outfile.write('min_max_length_value=%s,\n' % quote_python(self.min_max_length_value).encode(ExternalEncoding)) + if self.length_value is not None: + showIndent(outfile, level) + outfile.write('length_value=%s,\n' % quote_python(self.length_value).encode(ExternalEncoding)) + if self.totaldigits_value is not None: + showIndent(outfile, level) + outfile.write('totaldigits_value=%f,\n' % self.totaldigits_value) + if self.anonymous_float_value is not None: + showIndent(outfile, level) + outfile.write('anonymous_float_value=%f,\n' % self.anonymous_float_value) + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'token_enum_value': + token_enum_value_ = child_.text + token_enum_value_ = self.gds_validate_string(token_enum_value_, node, 'token_enum_value') + self.token_enum_value = token_enum_value_ + self.validate_token_enum_st(self.token_enum_value) # validate type token_enum_st + elif nodeName_ == 'token_enum_value': + token_enum_value_ = child_.text + token_enum_value_ = self.gds_validate_string(token_enum_value_, node, 'token_enum_value') + self.token_enum_value = token_enum_value_ + self.validate_token_enum_st(self.token_enum_value) # validate type token_enum_st + elif nodeName_ == 'integer_range_incl_value': + sval_ = child_.text + try: + ival_ = int(sval_) + except (TypeError, ValueError), exp: + raise_parse_error(child_, 'requires integer: %s' % exp) + ival_ = self.gds_validate_integer(ival_, node, 'integer_range_incl_value') + self.integer_range_incl_value = ival_ + self.validate_integer_range_incl_st(self.integer_range_incl_value) # validate type integer_range_incl_st + elif nodeName_ == 'integer_range_excl_value': + sval_ = child_.text + try: + ival_ = int(sval_) + except (TypeError, ValueError), exp: + raise_parse_error(child_, 'requires integer: %s' % exp) + ival_ = self.gds_validate_integer(ival_, node, 'integer_range_excl_value') + self.integer_range_excl_value = ival_ + self.validate_integer_range_excl_st(self.integer_range_excl_value) # validate type integer_range_excl_st + elif nodeName_ == 'min_max_length_value': + min_max_length_value_ = child_.text + min_max_length_value_ = self.gds_validate_string(min_max_length_value_, node, 'min_max_length_value') + self.min_max_length_value = min_max_length_value_ + self.validate_min_max_length_st(self.min_max_length_value) # validate type min_max_length_st + elif nodeName_ == 'length_value': + length_value_ = child_.text + length_value_ = self.gds_validate_string(length_value_, node, 'length_value') + self.length_value = length_value_ + self.validate_length_st(self.length_value) # validate type length_st + elif nodeName_ == 'totaldigits_value': + sval_ = child_.text + try: + fval_ = float(sval_) + except (TypeError, ValueError), exp: + raise_parse_error(child_, 'requires float or double: %s' % exp) + fval_ = self.gds_validate_float(fval_, node, 'totaldigits_value') + self.totaldigits_value = fval_ + self.validate_totaldigits_st(self.totaldigits_value) # validate type totaldigits_st + elif nodeName_ == 'anonymous_float_value': + sval_ = child_.text + try: + fval_ = float(sval_) + except (TypeError, ValueError), exp: + raise_parse_error(child_, 'requires float or double: %s' % exp) + fval_ = self.gds_validate_float(fval_, node, 'anonymous_float_value') + self.anonymous_float_value = fval_ + self.validate_anonymous_float_valueType(self.anonymous_float_value) # validate type anonymous_float_valueType +# end class simpleOneType + + +class simpleTwoType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('Foo', 'FooType1', 0), + ] + subclass = None + superclass = None + def __init__(self, Foo=None): + self.original_tagname_ = None + self.Foo = Foo + def factory(*args_, **kwargs_): + if simpleTwoType.subclass: + return simpleTwoType.subclass(*args_, **kwargs_) + else: + return simpleTwoType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_Foo(self): return self.Foo + def set_Foo(self, Foo): self.Foo = Foo + def hasContent_(self): + if ( + self.Foo is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='simpleTwoType', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='simpleTwoType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='simpleTwoType', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='simpleTwoType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='simpleTwoType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.Foo is not None: + self.Foo.export(outfile, level, namespace_, name_='Foo', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='simpleTwoType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.Foo is not None: + showIndent(outfile, level) + outfile.write('Foo=model_.FooType1(\n') + self.Foo.exportLiteral(outfile, level, name_='Foo') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'Foo': + obj_ = FooType1.factory() + obj_.build(child_) + self.Foo = obj_ + obj_.original_tagname_ = 'Foo' +# end class simpleTwoType + + +class FooType1(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('FooType', ['FooTypeType', 'xs:string'], 0), + ] + subclass = None + superclass = None + def __init__(self, FooType=None): + self.original_tagname_ = None + self.FooType = FooType + self.validate_FooTypeType(self.FooType) + def factory(*args_, **kwargs_): + if FooType1.subclass: + return FooType1.subclass(*args_, **kwargs_) + else: + return FooType1(*args_, **kwargs_) + factory = staticmethod(factory) + def get_FooType(self): return self.FooType + def set_FooType(self, FooType): self.FooType = FooType + def validate_FooTypeType(self, value): + # Validate type FooTypeType, a restriction on xs:string. + if value is not None and Validate_simpletypes_: + if len(value) < 12: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on FooTypeType' % {"value" : value.encode("utf-8")} ) + if len(value) > 24: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on FooTypeType' % {"value" : value.encode("utf-8")} ) + def hasContent_(self): + if ( + self.FooType is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='FooType1', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='FooType1') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='FooType1', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='FooType1'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='FooType1', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.FooType is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sFooType>%s</%sFooType>%s' % (namespace_, self.gds_format_string(quote_xml(self.FooType).encode(ExternalEncoding), input_name='FooType'), namespace_, eol_)) + def exportLiteral(self, outfile, level, name_='FooType1'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.FooType is not None: + showIndent(outfile, level) + outfile.write('FooType=%s,\n' % quote_python(self.FooType).encode(ExternalEncoding)) + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'FooType': + FooType_ = child_.text + FooType_ = self.gds_validate_string(FooType_, node, 'FooType') + self.FooType = FooType_ + self.validate_FooTypeType(self.FooType) # validate type FooTypeType +# end class FooType1 + + +GDSClassesMapping = { + 'container': containerType, + 'sample2_bad': simpleOneType, + 'sample1': simpleOneType, + 'sample3_bad': simpleOneType, + 'sample2': simpleTwoType, + 'Foo': FooType1, +} + + +USAGE_TEXT = """ +Usage: python <Parser>.py [ -s ] <in_xml_file> +""" + + +def usage(): + print USAGE_TEXT + sys.exit(1) + + +def get_root_tag(node): + tag = Tag_pattern_.match(node.tag).groups()[-1] + rootClass = GDSClassesMapping.get(tag) + if rootClass is None: + rootClass = globals().get(tag) + return tag, rootClass + + +def parse(inFileName, silence=False): + doc = parsexml_(inFileName) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='', + pretty_print=True) + return rootObj + + +def parseEtree(inFileName, silence=False): + doc = parsexml_(inFileName) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) + if not silence: + content = etree_.tostring( + rootElement, pretty_print=True, + xml_declaration=True, encoding="utf-8") + sys.stdout.write(content) + sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + doc = parsexml_(StringIO(inString)) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='') + return rootObj + + +def parseLiteral(inFileName, silence=False): + doc = parsexml_(inFileName) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('#from validate_simpletypes2_sup import *\n\n') + sys.stdout.write('import validate_simpletypes2_sup as model_\n\n') + sys.stdout.write('rootObj = model_.rootClass(\n') + rootObj.exportLiteral(sys.stdout, 0, name_=rootTag) + sys.stdout.write(')\n') + return rootObj + + +def main(): + args = sys.argv[1:] + if len(args) == 1: + parse(args[0]) + else: + usage() + + +if __name__ == '__main__': + #import pdb; pdb.set_trace() + main() + + +__all__ = [ + "FooType1", + "containerType", + "simpleOneType", + "simpleTwoType" +] diff --git a/tests/validate_simpletypes1_warnings.txt b/tests/validate_simpletypes1_warnings.txt new file mode 100644 index 0000000..39f7751 --- /dev/null +++ b/tests/validate_simpletypes1_warnings.txt @@ -0,0 +1,20 @@ +tests/validate_simpletypes2_sup.py:889: UserWarning: Value "floatxx" does not match xsd enumeration restriction on token_enum_st + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on token_enum_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:896: UserWarning: Value "22" does not match xsd maxInclusive restriction on integer_range_incl_st + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on integer_range_incl_st' % {"value" : value} ) +tests/validate_simpletypes2_sup.py:901: UserWarning: Value "-40" does not match xsd minExclusive restriction on integer_range_excl_st + warnings.warn('Value "%(value)s" does not match xsd minExclusive restriction on integer_range_excl_st' % {"value" : value} ) +tests/validate_simpletypes2_sup.py:908: UserWarning: Value "mno pqr" does not match xsd minLength restriction on min_max_length_st + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:915: UserWarning: Value "012345" does not match xsd length restriction on length_st + warnings.warn('Value "%(value)s" does not match xsd length restriction on length_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:925: UserWarning: Value "0.2" does not match xsd minInclusive restriction on anonymous_float_valueType + warnings.warn('Value "%(value)s" does not match xsd minInclusive restriction on anonymous_float_valueType' % {"value" : value} ) +tests/validate_simpletypes2_sup.py:894: UserWarning: Value "-50" does not match xsd minInclusive restriction on integer_range_incl_st + warnings.warn('Value "%(value)s" does not match xsd minInclusive restriction on integer_range_incl_st' % {"value" : value} ) +tests/validate_simpletypes2_sup.py:910: UserWarning: Value "asdf asdf asdf adf asdf asdf" does not match xsd maxLength restriction on min_max_length_st + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:915: UserWarning: Value "01234567890" does not match xsd length restriction on length_st + warnings.warn('Value "%(value)s" does not match xsd length restriction on length_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:927: UserWarning: Value "6.6" does not match xsd maxInclusive restriction on anonymous_float_valueType + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on anonymous_float_valueType' % {"value" : value} ) diff --git a/tests/validate_simpletypes2_out.xml b/tests/validate_simpletypes2_out.xml new file mode 100644 index 0000000..70c8feb --- /dev/null +++ b/tests/validate_simpletypes2_out.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" ?> +<container> + <sample1> + <token_enum_value>float</token_enum_value> + <token_enum_value>float</token_enum_value> + <integer_range_incl_value>2</integer_range_incl_value> + <integer_range_excl_value>7</integer_range_excl_value> + <min_max_length_value>abc def ghi</min_max_length_value> + <length_value>0123456789</length_value> + <totaldigits_value>12.456</totaldigits_value> + <anonymous_float_value>2.2</anonymous_float_value> + </sample1> + <sample2_bad> + <token_enum_value>floatxx</token_enum_value> + <token_enum_value>floatxx</token_enum_value> + <integer_range_incl_value>22</integer_range_incl_value> + <integer_range_excl_value>-40</integer_range_excl_value> + <min_max_length_value>mno pqr</min_max_length_value> + <length_value>012345</length_value> + <totaldigits_value>12.456789000000001</totaldigits_value> + <anonymous_float_value>0.2</anonymous_float_value> + </sample2_bad> + <sample3_bad> + <integer_range_incl_value>-50</integer_range_incl_value> + <min_max_length_value>asdf asdf asdf adf asdf asdf</min_max_length_value> + <length_value>01234567890</length_value> + <totaldigits_value>12345678.456789009273052</totaldigits_value> + <anonymous_float_value>6.6</anonymous_float_value> + </sample3_bad> +</container> diff --git a/tests/validate_simpletypes2_sub.py b/tests/validate_simpletypes2_sub.py new file mode 100644 index 0000000..6b50bce --- /dev/null +++ b/tests/validate_simpletypes2_sub.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/validate_simpletypes2_sup.py') +# ('-s', 'tests/validate_simpletypes2_sub.py') +# ('--super', 'validate_simpletypes2_sup') +# +# Command line arguments: +# tests/validate_simpletypes.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --member-specs="list" -f -o "tests/validate_simpletypes2_sup.py" -s "tests/validate_simpletypes2_sub.py" --super="validate_simpletypes2_sup" tests/validate_simpletypes.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys + +import validate_simpletypes2_sup as supermod + +etree_ = None +Verbose_import_ = False +( + XMLParser_import_none, XMLParser_import_lxml, + XMLParser_import_elementtree +) = range(3) +XMLParser_import_library = None +try: + # lxml + from lxml import etree as etree_ + XMLParser_import_library = XMLParser_import_lxml + if Verbose_import_: + print("running with lxml.etree") +except ImportError: + try: + # cElementTree from Python 2.5+ + import xml.etree.cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree on Python 2.5+") + except ImportError: + try: + # ElementTree from Python 2.5+ + import xml.etree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree on Python 2.5+") + except ImportError: + try: + # normal cElementTree install + import cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree") + except ImportError: + try: + # normal ElementTree install + import elementtree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree") + except ImportError: + raise ImportError( + "Failed to import ElementTree from any known place") + + +def parsexml_(*args, **kwargs): + if (XMLParser_import_library == XMLParser_import_lxml and + 'parser' not in kwargs): + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + kwargs['parser'] = etree_.ETCompatXMLParser() + doc = etree_.parse(*args, **kwargs) + return doc + +# +# Globals +# + +ExternalEncoding = 'ascii' + +# +# Data representation classes +# + + +class containerTypeSub(supermod.containerType): + def __init__(self, sample1=None, sample2_bad=None, sample3_bad=None, sample2=None): + super(containerTypeSub, self).__init__(sample1, sample2_bad, sample3_bad, sample2, ) +supermod.containerType.subclass = containerTypeSub +# end class containerTypeSub + + +class simpleOneTypeSub(supermod.simpleOneType): + def __init__(self, token_enum_value=None, integer_range_incl_value=None, integer_range_excl_value=None, min_max_length_value=None, length_value=None, totaldigits_value=None, anonymous_float_value=None): + super(simpleOneTypeSub, self).__init__(token_enum_value, integer_range_incl_value, integer_range_excl_value, min_max_length_value, length_value, totaldigits_value, anonymous_float_value, ) +supermod.simpleOneType.subclass = simpleOneTypeSub +# end class simpleOneTypeSub + + +class simpleTwoTypeSub(supermod.simpleTwoType): + def __init__(self, Foo=None): + super(simpleTwoTypeSub, self).__init__(Foo, ) +supermod.simpleTwoType.subclass = simpleTwoTypeSub +# end class simpleTwoTypeSub + + +class FooType1Sub(supermod.FooType1): + def __init__(self, FooType=None): + super(FooType1Sub, self).__init__(FooType, ) +supermod.FooType1.subclass = FooType1Sub +# end class FooType1Sub + + +def get_root_tag(node): + tag = supermod.Tag_pattern_.match(node.tag).groups()[-1] + rootClass = None + rootClass = supermod.GDSClassesMapping.get(tag) + if rootClass is None and hasattr(supermod, tag): + rootClass = getattr(supermod, tag) + return tag, rootClass + + +def parse(inFilename, silence=False): + doc = parsexml_(inFilename) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='', + pretty_print=True) + return rootObj + + +def parseEtree(inFilename, silence=False): + doc = parsexml_(inFilename) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) + if not silence: + content = etree_.tostring( + rootElement, pretty_print=True, + xml_declaration=True, encoding="utf-8") + sys.stdout.write(content) + sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + doc = parsexml_(StringIO(inString)) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='') + return rootObj + + +def parseLiteral(inFilename, silence=False): + doc = parsexml_(inFilename) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('#from validate_simpletypes2_sup import *\n\n') + sys.stdout.write('import validate_simpletypes2_sup as model_\n\n') + sys.stdout.write('rootObj = model_.rootClass(\n') + rootObj.exportLiteral(sys.stdout, 0, name_=rootTag) + sys.stdout.write(')\n') + return rootObj + + +USAGE_TEXT = """ +Usage: python ???.py <infilename> +""" + + +def usage(): + print USAGE_TEXT + sys.exit(1) + + +def main(): + args = sys.argv[1:] + if len(args) != 1: + usage() + infilename = args[0] + parse(infilename) + + +if __name__ == '__main__': + #import pdb; pdb.set_trace() + main() diff --git a/tests/validate_simpletypes2_sup.py b/tests/validate_simpletypes2_sup.py new file mode 100644 index 0000000..77d9886 --- /dev/null +++ b/tests/validate_simpletypes2_sup.py @@ -0,0 +1,1396 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/validate_simpletypes2_sup.py') +# ('-s', 'tests/validate_simpletypes2_sub.py') +# ('--super', 'validate_simpletypes2_sup') +# +# Command line arguments: +# tests/validate_simpletypes.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --member-specs="list" -f -o "tests/validate_simpletypes2_sup.py" -s "tests/validate_simpletypes2_sub.py" --super="validate_simpletypes2_sup" tests/validate_simpletypes.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys +import getopt +import re as re_ +import base64 +import datetime as datetime_ +import warnings + + +Validate_simpletypes_ = True + + +etree_ = None +Verbose_import_ = False +( + XMLParser_import_none, XMLParser_import_lxml, + XMLParser_import_elementtree +) = range(3) +XMLParser_import_library = None +try: + # lxml + from lxml import etree as etree_ + XMLParser_import_library = XMLParser_import_lxml + if Verbose_import_: + print("running with lxml.etree") +except ImportError: + try: + # cElementTree from Python 2.5+ + import xml.etree.cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree on Python 2.5+") + except ImportError: + try: + # ElementTree from Python 2.5+ + import xml.etree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree on Python 2.5+") + except ImportError: + try: + # normal cElementTree install + import cElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with cElementTree") + except ImportError: + try: + # normal ElementTree install + import elementtree.ElementTree as etree_ + XMLParser_import_library = XMLParser_import_elementtree + if Verbose_import_: + print("running with ElementTree") + except ImportError: + raise ImportError( + "Failed to import ElementTree from any known place") + + +def parsexml_(*args, **kwargs): + if (XMLParser_import_library == XMLParser_import_lxml and + 'parser' not in kwargs): + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + kwargs['parser'] = etree_.ETCompatXMLParser() + doc = etree_.parse(*args, **kwargs) + return doc + +# +# User methods +# +# Calls to the methods in these classes are generated by generateDS.py. +# You can replace these methods by re-implementing the following class +# in a module named generatedssuper.py. + +try: + from generatedssuper import GeneratedsSuper +except ImportError, exp: + + class GeneratedsSuper(object): + tzoff_pattern = re_.compile(r'(\+|-)((0\d|1[0-3]):[0-5]\d|14:00)$') + class _FixedOffsetTZ(datetime_.tzinfo): + def __init__(self, offset, name): + self.__offset = datetime_.timedelta(minutes=offset) + self.__name = name + def utcoffset(self, dt): + return self.__offset + def tzname(self, dt): + return self.__name + def dst(self, dt): + return None + def gds_format_string(self, input_data, input_name=''): + return input_data + def gds_validate_string(self, input_data, node, input_name=''): + if not input_data: + return '' + else: + return input_data + def gds_format_base64(self, input_data, input_name=''): + return base64.b64encode(input_data) + def gds_validate_base64(self, input_data, node, input_name=''): + return input_data + def gds_format_integer(self, input_data, input_name=''): + return '%d' % input_data + def gds_validate_integer(self, input_data, node, input_name=''): + return input_data + def gds_format_integer_list(self, input_data, input_name=''): + return '%s' % ' '.join(input_data) + def gds_validate_integer_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + try: + float(value) + except (TypeError, ValueError): + raise_parse_error(node, 'Requires sequence of integers') + return values + def gds_format_float(self, input_data, input_name=''): + return ('%.15f' % input_data).rstrip('0') + def gds_validate_float(self, input_data, node, input_name=''): + return input_data + def gds_format_float_list(self, input_data, input_name=''): + return '%s' % ' '.join(input_data) + def gds_validate_float_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + try: + float(value) + except (TypeError, ValueError): + raise_parse_error(node, 'Requires sequence of floats') + return values + def gds_format_double(self, input_data, input_name=''): + return '%e' % input_data + def gds_validate_double(self, input_data, node, input_name=''): + return input_data + def gds_format_double_list(self, input_data, input_name=''): + return '%s' % ' '.join(input_data) + def gds_validate_double_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + try: + float(value) + except (TypeError, ValueError): + raise_parse_error(node, 'Requires sequence of doubles') + return values + def gds_format_boolean(self, input_data, input_name=''): + return ('%s' % input_data).lower() + def gds_validate_boolean(self, input_data, node, input_name=''): + return input_data + def gds_format_boolean_list(self, input_data, input_name=''): + return '%s' % ' '.join(input_data) + def gds_validate_boolean_list(self, input_data, node, input_name=''): + values = input_data.split() + for value in values: + if value not in ('true', '1', 'false', '0', ): + raise_parse_error( + node, + 'Requires sequence of booleans ' + '("true", "1", "false", "0")') + return values + def gds_validate_datetime(self, input_data, node, input_name=''): + return input_data + def gds_format_datetime(self, input_data, input_name=''): + if input_data.microsecond == 0: + _svalue = '%04d-%02d-%02dT%02d:%02d:%02d' % ( + input_data.year, + input_data.month, + input_data.day, + input_data.hour, + input_data.minute, + input_data.second, + ) + else: + _svalue = '%04d-%02d-%02dT%02d:%02d:%02d.%s' % ( + input_data.year, + input_data.month, + input_data.day, + input_data.hour, + input_data.minute, + input_data.second, + ('%f' % (float(input_data.microsecond) / 1000000))[2:], + ) + if input_data.tzinfo is not None: + tzoff = input_data.tzinfo.utcoffset(input_data) + if tzoff is not None: + total_seconds = tzoff.seconds + (86400 * tzoff.days) + if total_seconds == 0: + _svalue += 'Z' + else: + if total_seconds < 0: + _svalue += '-' + total_seconds *= -1 + else: + _svalue += '+' + hours = total_seconds // 3600 + minutes = (total_seconds - (hours * 3600)) // 60 + _svalue += '{0:02d}:{1:02d}'.format(hours, minutes) + return _svalue + @classmethod + def gds_parse_datetime(cls, input_data): + tz = None + if input_data[-1] == 'Z': + tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC') + input_data = input_data[:-1] + else: + results = GeneratedsSuper.tzoff_pattern.search(input_data) + if results is not None: + tzoff_parts = results.group(2).split(':') + tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1]) + if results.group(1) == '-': + tzoff *= -1 + tz = GeneratedsSuper._FixedOffsetTZ( + tzoff, results.group(0)) + input_data = input_data[:-6] + time_parts = input_data.split('.') + if len(time_parts) > 1: + micro_seconds = int(float('0.' + time_parts[1]) * 1000000) + input_data = '%s.%s' % (time_parts[0], micro_seconds, ) + dt = datetime_.datetime.strptime( + input_data, '%Y-%m-%dT%H:%M:%S.%f') + else: + dt = datetime_.datetime.strptime( + input_data, '%Y-%m-%dT%H:%M:%S') + dt = dt.replace(tzinfo=tz) + return dt + def gds_validate_date(self, input_data, node, input_name=''): + return input_data + def gds_format_date(self, input_data, input_name=''): + _svalue = '%04d-%02d-%02d' % ( + input_data.year, + input_data.month, + input_data.day, + ) + try: + if input_data.tzinfo is not None: + tzoff = input_data.tzinfo.utcoffset(input_data) + if tzoff is not None: + total_seconds = tzoff.seconds + (86400 * tzoff.days) + if total_seconds == 0: + _svalue += 'Z' + else: + if total_seconds < 0: + _svalue += '-' + total_seconds *= -1 + else: + _svalue += '+' + hours = total_seconds // 3600 + minutes = (total_seconds - (hours * 3600)) // 60 + _svalue += '{0:02d}:{1:02d}'.format(hours, minutes) + except AttributeError: + pass + return _svalue + @classmethod + def gds_parse_date(cls, input_data): + tz = None + if input_data[-1] == 'Z': + tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC') + input_data = input_data[:-1] + else: + results = GeneratedsSuper.tzoff_pattern.search(input_data) + if results is not None: + tzoff_parts = results.group(2).split(':') + tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1]) + if results.group(1) == '-': + tzoff *= -1 + tz = GeneratedsSuper._FixedOffsetTZ( + tzoff, results.group(0)) + input_data = input_data[:-6] + dt = datetime_.datetime.strptime(input_data, '%Y-%m-%d') + dt = dt.replace(tzinfo=tz) + return dt.date() + def gds_validate_time(self, input_data, node, input_name=''): + return input_data + def gds_format_time(self, input_data, input_name=''): + if input_data.microsecond == 0: + _svalue = '%02d:%02d:%02d' % ( + input_data.hour, + input_data.minute, + input_data.second, + ) + else: + _svalue = '%02d:%02d:%02d.%s' % ( + input_data.hour, + input_data.minute, + input_data.second, + ('%f' % (float(input_data.microsecond) / 1000000))[2:], + ) + if input_data.tzinfo is not None: + tzoff = input_data.tzinfo.utcoffset(input_data) + if tzoff is not None: + total_seconds = tzoff.seconds + (86400 * tzoff.days) + if total_seconds == 0: + _svalue += 'Z' + else: + if total_seconds < 0: + _svalue += '-' + total_seconds *= -1 + else: + _svalue += '+' + hours = total_seconds // 3600 + minutes = (total_seconds - (hours * 3600)) // 60 + _svalue += '{0:02d}:{1:02d}'.format(hours, minutes) + return _svalue + @classmethod + def gds_parse_time(cls, input_data): + tz = None + if input_data[-1] == 'Z': + tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC') + input_data = input_data[:-1] + else: + results = GeneratedsSuper.tzoff_pattern.search(input_data) + if results is not None: + tzoff_parts = results.group(2).split(':') + tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1]) + if results.group(1) == '-': + tzoff *= -1 + tz = GeneratedsSuper._FixedOffsetTZ( + tzoff, results.group(0)) + input_data = input_data[:-6] + if len(input_data.split('.')) > 1: + dt = datetime_.datetime.strptime(input_data, '%H:%M:%S.%f') + else: + dt = datetime_.datetime.strptime(input_data, '%H:%M:%S') + dt = dt.replace(tzinfo=tz) + return dt.time() + def gds_str_lower(self, instring): + return instring.lower() + def get_path_(self, node): + path_list = [] + self.get_path_list_(node, path_list) + path_list.reverse() + path = '/'.join(path_list) + return path + Tag_strip_pattern_ = re_.compile(r'\{.*\}') + def get_path_list_(self, node, path_list): + if node is None: + return + tag = GeneratedsSuper.Tag_strip_pattern_.sub('', node.tag) + if tag: + path_list.append(tag) + self.get_path_list_(node.getparent(), path_list) + def get_class_obj_(self, node, default_class=None): + class_obj1 = default_class + if 'xsi' in node.nsmap: + classname = node.get('{%s}type' % node.nsmap['xsi']) + if classname is not None: + names = classname.split(':') + if len(names) == 2: + classname = names[1] + class_obj2 = globals().get(classname) + if class_obj2 is not None: + class_obj1 = class_obj2 + return class_obj1 + def gds_build_any(self, node, type_name=None): + return None + @classmethod + def gds_reverse_node_mapping(cls, mapping): + return dict(((v, k) for k, v in mapping.iteritems())) + + +# +# If you have installed IPython you can uncomment and use the following. +# IPython is available from http://ipython.scipy.org/. +# + +## from IPython.Shell import IPShellEmbed +## args = '' +## ipshell = IPShellEmbed(args, +## banner = 'Dropping into IPython', +## exit_msg = 'Leaving Interpreter, back to program.') + +# Then use the following line where and when you want to drop into the +# IPython shell: +# ipshell('<some message> -- Entering ipshell.\nHit Ctrl-D to exit') + +# +# Globals +# + +ExternalEncoding = 'ascii' +Tag_pattern_ = re_.compile(r'({.*})?(.*)') +String_cleanup_pat_ = re_.compile(r"[\n\r\s]+") +Namespace_extract_pat_ = re_.compile(r'{(.*)}(.*)') + +# +# Support/utility functions. +# + + +def showIndent(outfile, level, pretty_print=True): + if pretty_print: + for idx in range(level): + outfile.write(' ') + + +def quote_xml(inStr): + if not inStr: + return '' + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + return s1 + + +def quote_attrib(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + if '"' in s1: + if "'" in s1: + s1 = '"%s"' % s1.replace('"', """) + else: + s1 = "'%s'" % s1 + else: + s1 = '"%s"' % s1 + return s1 + + +def quote_python(inStr): + s1 = inStr + if s1.find("'") == -1: + if s1.find('\n') == -1: + return "'%s'" % s1 + else: + return "'''%s'''" % s1 + else: + if s1.find('"') != -1: + s1 = s1.replace('"', '\\"') + if s1.find('\n') == -1: + return '"%s"' % s1 + else: + return '"""%s"""' % s1 + + +def get_all_text_(node): + if node.text is not None: + text = node.text + else: + text = '' + for child in node: + if child.tail is not None: + text += child.tail + return text + + +def find_attr_value_(attr_name, node): + attrs = node.attrib + attr_parts = attr_name.split(':') + value = None + if len(attr_parts) == 1: + value = attrs.get(attr_name) + elif len(attr_parts) == 2: + prefix, name = attr_parts + namespace = node.nsmap.get(prefix) + if namespace is not None: + value = attrs.get('{%s}%s' % (namespace, name, )) + return value + + +class GDSParseError(Exception): + pass + + +def raise_parse_error(node, msg): + if XMLParser_import_library == XMLParser_import_lxml: + msg = '%s (element %s/line %d)' % ( + msg, node.tag, node.sourceline, ) + else: + msg = '%s (element %s)' % (msg, node.tag, ) + raise GDSParseError(msg) + + +class MixedContainer: + # Constants for category: + CategoryNone = 0 + CategoryText = 1 + CategorySimple = 2 + CategoryComplex = 3 + # Constants for content_type: + TypeNone = 0 + TypeText = 1 + TypeString = 2 + TypeInteger = 3 + TypeFloat = 4 + TypeDecimal = 5 + TypeDouble = 6 + TypeBoolean = 7 + TypeBase64 = 8 + def __init__(self, category, content_type, name, value): + self.category = category + self.content_type = content_type + self.name = name + self.value = value + def getCategory(self): + return self.category + def getContenttype(self, content_type): + return self.content_type + def getValue(self): + return self.value + def getName(self): + return self.name + def export(self, outfile, level, name, namespace, pretty_print=True): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + outfile.write(self.value) + elif self.category == MixedContainer.CategorySimple: + self.exportSimple(outfile, level, name) + else: # category == MixedContainer.CategoryComplex + self.value.export(outfile, level, namespace, name, pretty_print) + def exportSimple(self, outfile, level, name): + if self.content_type == MixedContainer.TypeString: + outfile.write('<%s>%s</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeInteger or \ + self.content_type == MixedContainer.TypeBoolean: + outfile.write('<%s>%d</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeFloat or \ + self.content_type == MixedContainer.TypeDecimal: + outfile.write('<%s>%f</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeDouble: + outfile.write('<%s>%g</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeBase64: + outfile.write('<%s>%s</%s>' % ( + self.name, base64.b64encode(self.value), self.name)) + def to_etree(self, element): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + if len(element) > 0: + if element[-1].tail is None: + element[-1].tail = self.value + else: + element[-1].tail += self.value + else: + if element.text is None: + element.text = self.value + else: + element.text += self.value + elif self.category == MixedContainer.CategorySimple: + subelement = etree_.SubElement(element, '%s' % self.name) + subelement.text = self.to_etree_simple() + else: # category == MixedContainer.CategoryComplex + self.value.to_etree(element) + def to_etree_simple(self): + if self.content_type == MixedContainer.TypeString: + text = self.value + elif (self.content_type == MixedContainer.TypeInteger or + self.content_type == MixedContainer.TypeBoolean): + text = '%d' % self.value + elif (self.content_type == MixedContainer.TypeFloat or + self.content_type == MixedContainer.TypeDecimal): + text = '%f' % self.value + elif self.content_type == MixedContainer.TypeDouble: + text = '%g' % self.value + elif self.content_type == MixedContainer.TypeBase64: + text = '%s' % base64.b64encode(self.value) + return text + def exportLiteral(self, outfile, level, name): + if self.category == MixedContainer.CategoryText: + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % ( + self.category, self.content_type, self.name, self.value)) + elif self.category == MixedContainer.CategorySimple: + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % ( + self.category, self.content_type, self.name, self.value)) + else: # category == MixedContainer.CategoryComplex + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s",\n' % ( + self.category, self.content_type, self.name,)) + self.value.exportLiteral(outfile, level + 1) + showIndent(outfile, level) + outfile.write(')\n') + + +class MemberSpec_(object): + def __init__(self, name='', data_type='', container=0): + self.name = name + self.data_type = data_type + self.container = container + def set_name(self, name): self.name = name + def get_name(self): return self.name + def set_data_type(self, data_type): self.data_type = data_type + def get_data_type_chain(self): return self.data_type + def get_data_type(self): + if isinstance(self.data_type, list): + if len(self.data_type) > 0: + return self.data_type[-1] + else: + return 'xs:string' + else: + return self.data_type + def set_container(self, container): self.container = container + def get_container(self): return self.container + + +def _cast(typ, value): + if typ is None or value is None: + return value + return typ(value) + +# +# Data representation classes. +# + + +class containerType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('sample1', 'simpleOneType', 1), + MemberSpec_('sample2_bad', 'simpleOneType', 1), + MemberSpec_('sample3_bad', 'simpleOneType', 1), + MemberSpec_('sample2', 'simpleTwoType', 1), + ] + subclass = None + superclass = None + def __init__(self, sample1=None, sample2_bad=None, sample3_bad=None, sample2=None): + self.original_tagname_ = None + if sample1 is None: + self.sample1 = [] + else: + self.sample1 = sample1 + if sample2_bad is None: + self.sample2_bad = [] + else: + self.sample2_bad = sample2_bad + if sample3_bad is None: + self.sample3_bad = [] + else: + self.sample3_bad = sample3_bad + if sample2 is None: + self.sample2 = [] + else: + self.sample2 = sample2 + def factory(*args_, **kwargs_): + if containerType.subclass: + return containerType.subclass(*args_, **kwargs_) + else: + return containerType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_sample1(self): return self.sample1 + def set_sample1(self, sample1): self.sample1 = sample1 + def add_sample1(self, value): self.sample1.append(value) + def insert_sample1_at(self, index, value): self.sample1.insert(index, value) + def replace_sample1_at(self, index, value): self.sample1[index] = value + def get_sample2_bad(self): return self.sample2_bad + def set_sample2_bad(self, sample2_bad): self.sample2_bad = sample2_bad + def add_sample2_bad(self, value): self.sample2_bad.append(value) + def insert_sample2_bad_at(self, index, value): self.sample2_bad.insert(index, value) + def replace_sample2_bad_at(self, index, value): self.sample2_bad[index] = value + def get_sample3_bad(self): return self.sample3_bad + def set_sample3_bad(self, sample3_bad): self.sample3_bad = sample3_bad + def add_sample3_bad(self, value): self.sample3_bad.append(value) + def insert_sample3_bad_at(self, index, value): self.sample3_bad.insert(index, value) + def replace_sample3_bad_at(self, index, value): self.sample3_bad[index] = value + def get_sample2(self): return self.sample2 + def set_sample2(self, sample2): self.sample2 = sample2 + def add_sample2(self, value): self.sample2.append(value) + def insert_sample2_at(self, index, value): self.sample2.insert(index, value) + def replace_sample2_at(self, index, value): self.sample2[index] = value + def hasContent_(self): + if ( + self.sample1 or + self.sample2_bad or + self.sample3_bad or + self.sample2 + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='containerType', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='containerType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='containerType', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='containerType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='containerType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + for sample1_ in self.sample1: + sample1_.export(outfile, level, namespace_, name_='sample1', pretty_print=pretty_print) + for sample2_bad_ in self.sample2_bad: + sample2_bad_.export(outfile, level, namespace_, name_='sample2_bad', pretty_print=pretty_print) + for sample3_bad_ in self.sample3_bad: + sample3_bad_.export(outfile, level, namespace_, name_='sample3_bad', pretty_print=pretty_print) + for sample2_ in self.sample2: + sample2_.export(outfile, level, namespace_, name_='sample2', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='containerType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('sample1=[\n') + level += 1 + for sample1_ in self.sample1: + showIndent(outfile, level) + outfile.write('model_.simpleOneType(\n') + sample1_.exportLiteral(outfile, level, name_='simpleOneType') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('sample2_bad=[\n') + level += 1 + for sample2_bad_ in self.sample2_bad: + showIndent(outfile, level) + outfile.write('model_.simpleOneType(\n') + sample2_bad_.exportLiteral(outfile, level, name_='simpleOneType') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('sample3_bad=[\n') + level += 1 + for sample3_bad_ in self.sample3_bad: + showIndent(outfile, level) + outfile.write('model_.simpleOneType(\n') + sample3_bad_.exportLiteral(outfile, level, name_='simpleOneType') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('sample2=[\n') + level += 1 + for sample2_ in self.sample2: + showIndent(outfile, level) + outfile.write('model_.simpleTwoType(\n') + sample2_.exportLiteral(outfile, level, name_='simpleTwoType') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'sample1': + obj_ = simpleOneType.factory() + obj_.build(child_) + self.sample1.append(obj_) + obj_.original_tagname_ = 'sample1' + elif nodeName_ == 'sample2_bad': + obj_ = simpleOneType.factory() + obj_.build(child_) + self.sample2_bad.append(obj_) + obj_.original_tagname_ = 'sample2_bad' + elif nodeName_ == 'sample3_bad': + obj_ = simpleOneType.factory() + obj_.build(child_) + self.sample3_bad.append(obj_) + obj_.original_tagname_ = 'sample3_bad' + elif nodeName_ == 'sample2': + obj_ = simpleTwoType.factory() + obj_.build(child_) + self.sample2.append(obj_) + obj_.original_tagname_ = 'sample2' +# end class containerType + + +class simpleOneType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('token_enum_value', ['token_enum_st', 'xs:NMTOKEN'], 0), + MemberSpec_('token_enum_value', ['token_enum_st', 'xs:NMTOKEN'], 0), + MemberSpec_('integer_range_incl_value', ['integer_range_incl_st', 'xs:integer'], 0), + MemberSpec_('integer_range_excl_value', ['integer_range_excl_st', 'xs:integer'], 0), + MemberSpec_('min_max_length_value', ['min_max_length_st', 'xs:string'], 0), + MemberSpec_('length_value', ['length_st', 'xs:string'], 0), + MemberSpec_('totaldigits_value', ['totaldigits_st', 'xs:float'], 0), + MemberSpec_('anonymous_float_value', ['anonymous_float_valueType', 'xs:float'], 0), + ] + subclass = None + superclass = None + def __init__(self, token_enum_value=None, integer_range_incl_value=None, integer_range_excl_value=None, min_max_length_value=None, length_value=None, totaldigits_value=None, anonymous_float_value=None): + self.original_tagname_ = None + self.token_enum_value = token_enum_value + self.validate_token_enum_st(self.token_enum_value) + self.token_enum_value = token_enum_value + self.validate_token_enum_st(self.token_enum_value) + self.integer_range_incl_value = integer_range_incl_value + self.validate_integer_range_incl_st(self.integer_range_incl_value) + self.integer_range_excl_value = integer_range_excl_value + self.validate_integer_range_excl_st(self.integer_range_excl_value) + self.min_max_length_value = min_max_length_value + self.validate_min_max_length_st(self.min_max_length_value) + self.length_value = length_value + self.validate_length_st(self.length_value) + self.totaldigits_value = totaldigits_value + self.validate_totaldigits_st(self.totaldigits_value) + self.anonymous_float_value = anonymous_float_value + self.validate_anonymous_float_valueType(self.anonymous_float_value) + def factory(*args_, **kwargs_): + if simpleOneType.subclass: + return simpleOneType.subclass(*args_, **kwargs_) + else: + return simpleOneType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_token_enum_value(self): return self.token_enum_value + def set_token_enum_value(self, token_enum_value): self.token_enum_value = token_enum_value + def get_token_enum_value(self): return self.token_enum_value + def set_token_enum_value(self, token_enum_value): self.token_enum_value = token_enum_value + def get_integer_range_incl_value(self): return self.integer_range_incl_value + def set_integer_range_incl_value(self, integer_range_incl_value): self.integer_range_incl_value = integer_range_incl_value + def get_integer_range_excl_value(self): return self.integer_range_excl_value + def set_integer_range_excl_value(self, integer_range_excl_value): self.integer_range_excl_value = integer_range_excl_value + def get_min_max_length_value(self): return self.min_max_length_value + def set_min_max_length_value(self, min_max_length_value): self.min_max_length_value = min_max_length_value + def get_length_value(self): return self.length_value + def set_length_value(self, length_value): self.length_value = length_value + def get_totaldigits_value(self): return self.totaldigits_value + def set_totaldigits_value(self, totaldigits_value): self.totaldigits_value = totaldigits_value + def get_anonymous_float_value(self): return self.anonymous_float_value + def set_anonymous_float_value(self, anonymous_float_value): self.anonymous_float_value = anonymous_float_value + def validate_token_enum_st(self, value): + # Validate type token_enum_st, a restriction on xs:NMTOKEN. + if value is not None and Validate_simpletypes_: + enumerations = ['float', 'int', 'Name', 'token'] + enumeration_respectee = False + for enum in enumerations: + if value == enum: + enumeration_respectee = True + break + if not enumeration_respectee: + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on token_enum_st' % {"value" : value.encode("utf-8")} ) + def validate_integer_range_incl_st(self, value): + # Validate type integer_range_incl_st, a restriction on xs:integer. + if value is not None and Validate_simpletypes_: + if value <= -5: + warnings.warn('Value "%(value)s" does not match xsd minInclusive restriction on integer_range_incl_st' % {"value" : value} ) + if value >= 10: + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on integer_range_incl_st' % {"value" : value} ) + def validate_integer_range_excl_st(self, value): + # Validate type integer_range_excl_st, a restriction on xs:integer. + if value is not None and Validate_simpletypes_: + if value < -5: + warnings.warn('Value "%(value)s" does not match xsd minExclusive restriction on integer_range_excl_st' % {"value" : value} ) + if value > 10: + warnings.warn('Value "%(value)s" does not match xsd maxExclusive restriction on integer_range_excl_st' % {"value" : value} ) + def validate_min_max_length_st(self, value): + # Validate type min_max_length_st, a restriction on xs:string. + if value is not None and Validate_simpletypes_: + if len(value) < 10: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} ) + if len(value) > 20: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} ) + def validate_length_st(self, value): + # Validate type length_st, a restriction on xs:string. + if value is not None and Validate_simpletypes_: + if len(value) != 10: + warnings.warn('Value "%(value)s" does not match xsd length restriction on length_st' % {"value" : value.encode("utf-8")} ) + def validate_totaldigits_st(self, value): + # Validate type totaldigits_st, a restriction on xs:float. + if value is not None and Validate_simpletypes_: + if len(str(value)) >= 15: + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on totaldigits_st' % {"value" : value} ) + def validate_anonymous_float_valueType(self, value): + # Validate type anonymous_float_valueType, a restriction on xs:float. + if value is not None and Validate_simpletypes_: + if value <= 1.1: + warnings.warn('Value "%(value)s" does not match xsd minInclusive restriction on anonymous_float_valueType' % {"value" : value} ) + if value >= 4.4: + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on anonymous_float_valueType' % {"value" : value} ) + def hasContent_(self): + if ( + self.token_enum_value is not None or + self.token_enum_value is not None or + self.integer_range_incl_value is not None or + self.integer_range_excl_value is not None or + self.min_max_length_value is not None or + self.length_value is not None or + self.totaldigits_value is not None or + self.anonymous_float_value is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='simpleOneType', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='simpleOneType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='simpleOneType', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='simpleOneType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='simpleOneType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.token_enum_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%stoken_enum_value>%s</%stoken_enum_value>%s' % (namespace_, self.gds_format_string(quote_xml(self.token_enum_value).encode(ExternalEncoding), input_name='token_enum_value'), namespace_, eol_)) + if self.token_enum_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%stoken_enum_value>%s</%stoken_enum_value>%s' % (namespace_, self.gds_format_string(quote_xml(self.token_enum_value).encode(ExternalEncoding), input_name='token_enum_value'), namespace_, eol_)) + if self.integer_range_incl_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sinteger_range_incl_value>%s</%sinteger_range_incl_value>%s' % (namespace_, self.gds_format_integer(self.integer_range_incl_value, input_name='integer_range_incl_value'), namespace_, eol_)) + if self.integer_range_excl_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sinteger_range_excl_value>%s</%sinteger_range_excl_value>%s' % (namespace_, self.gds_format_integer(self.integer_range_excl_value, input_name='integer_range_excl_value'), namespace_, eol_)) + if self.min_max_length_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%smin_max_length_value>%s</%smin_max_length_value>%s' % (namespace_, self.gds_format_string(quote_xml(self.min_max_length_value).encode(ExternalEncoding), input_name='min_max_length_value'), namespace_, eol_)) + if self.length_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%slength_value>%s</%slength_value>%s' % (namespace_, self.gds_format_string(quote_xml(self.length_value).encode(ExternalEncoding), input_name='length_value'), namespace_, eol_)) + if self.totaldigits_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%stotaldigits_value>%s</%stotaldigits_value>%s' % (namespace_, self.gds_format_float(self.totaldigits_value, input_name='totaldigits_value'), namespace_, eol_)) + if self.anonymous_float_value is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sanonymous_float_value>%s</%sanonymous_float_value>%s' % (namespace_, self.gds_format_float(self.anonymous_float_value, input_name='anonymous_float_value'), namespace_, eol_)) + def exportLiteral(self, outfile, level, name_='simpleOneType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.token_enum_value is not None: + showIndent(outfile, level) + outfile.write('token_enum_value=%s,\n' % quote_python(self.token_enum_value).encode(ExternalEncoding)) + if self.token_enum_value is not None: + showIndent(outfile, level) + outfile.write('token_enum_value=%s,\n' % quote_python(self.token_enum_value).encode(ExternalEncoding)) + if self.integer_range_incl_value is not None: + showIndent(outfile, level) + outfile.write('integer_range_incl_value=%d,\n' % self.integer_range_incl_value) + if self.integer_range_excl_value is not None: + showIndent(outfile, level) + outfile.write('integer_range_excl_value=%d,\n' % self.integer_range_excl_value) + if self.min_max_length_value is not None: + showIndent(outfile, level) + outfile.write('min_max_length_value=%s,\n' % quote_python(self.min_max_length_value).encode(ExternalEncoding)) + if self.length_value is not None: + showIndent(outfile, level) + outfile.write('length_value=%s,\n' % quote_python(self.length_value).encode(ExternalEncoding)) + if self.totaldigits_value is not None: + showIndent(outfile, level) + outfile.write('totaldigits_value=%f,\n' % self.totaldigits_value) + if self.anonymous_float_value is not None: + showIndent(outfile, level) + outfile.write('anonymous_float_value=%f,\n' % self.anonymous_float_value) + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'token_enum_value': + token_enum_value_ = child_.text + token_enum_value_ = self.gds_validate_string(token_enum_value_, node, 'token_enum_value') + self.token_enum_value = token_enum_value_ + self.validate_token_enum_st(self.token_enum_value) # validate type token_enum_st + elif nodeName_ == 'token_enum_value': + token_enum_value_ = child_.text + token_enum_value_ = self.gds_validate_string(token_enum_value_, node, 'token_enum_value') + self.token_enum_value = token_enum_value_ + self.validate_token_enum_st(self.token_enum_value) # validate type token_enum_st + elif nodeName_ == 'integer_range_incl_value': + sval_ = child_.text + try: + ival_ = int(sval_) + except (TypeError, ValueError), exp: + raise_parse_error(child_, 'requires integer: %s' % exp) + ival_ = self.gds_validate_integer(ival_, node, 'integer_range_incl_value') + self.integer_range_incl_value = ival_ + self.validate_integer_range_incl_st(self.integer_range_incl_value) # validate type integer_range_incl_st + elif nodeName_ == 'integer_range_excl_value': + sval_ = child_.text + try: + ival_ = int(sval_) + except (TypeError, ValueError), exp: + raise_parse_error(child_, 'requires integer: %s' % exp) + ival_ = self.gds_validate_integer(ival_, node, 'integer_range_excl_value') + self.integer_range_excl_value = ival_ + self.validate_integer_range_excl_st(self.integer_range_excl_value) # validate type integer_range_excl_st + elif nodeName_ == 'min_max_length_value': + min_max_length_value_ = child_.text + min_max_length_value_ = self.gds_validate_string(min_max_length_value_, node, 'min_max_length_value') + self.min_max_length_value = min_max_length_value_ + self.validate_min_max_length_st(self.min_max_length_value) # validate type min_max_length_st + elif nodeName_ == 'length_value': + length_value_ = child_.text + length_value_ = self.gds_validate_string(length_value_, node, 'length_value') + self.length_value = length_value_ + self.validate_length_st(self.length_value) # validate type length_st + elif nodeName_ == 'totaldigits_value': + sval_ = child_.text + try: + fval_ = float(sval_) + except (TypeError, ValueError), exp: + raise_parse_error(child_, 'requires float or double: %s' % exp) + fval_ = self.gds_validate_float(fval_, node, 'totaldigits_value') + self.totaldigits_value = fval_ + self.validate_totaldigits_st(self.totaldigits_value) # validate type totaldigits_st + elif nodeName_ == 'anonymous_float_value': + sval_ = child_.text + try: + fval_ = float(sval_) + except (TypeError, ValueError), exp: + raise_parse_error(child_, 'requires float or double: %s' % exp) + fval_ = self.gds_validate_float(fval_, node, 'anonymous_float_value') + self.anonymous_float_value = fval_ + self.validate_anonymous_float_valueType(self.anonymous_float_value) # validate type anonymous_float_valueType +# end class simpleOneType + + +class simpleTwoType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('Foo', 'FooType1', 0), + ] + subclass = None + superclass = None + def __init__(self, Foo=None): + self.original_tagname_ = None + self.Foo = Foo + def factory(*args_, **kwargs_): + if simpleTwoType.subclass: + return simpleTwoType.subclass(*args_, **kwargs_) + else: + return simpleTwoType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_Foo(self): return self.Foo + def set_Foo(self, Foo): self.Foo = Foo + def hasContent_(self): + if ( + self.Foo is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='simpleTwoType', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='simpleTwoType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='simpleTwoType', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='simpleTwoType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='simpleTwoType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.Foo is not None: + self.Foo.export(outfile, level, namespace_, name_='Foo', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='simpleTwoType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.Foo is not None: + showIndent(outfile, level) + outfile.write('Foo=model_.FooType1(\n') + self.Foo.exportLiteral(outfile, level, name_='Foo') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'Foo': + obj_ = FooType1.factory() + obj_.build(child_) + self.Foo = obj_ + obj_.original_tagname_ = 'Foo' +# end class simpleTwoType + + +class FooType1(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('FooType', ['FooTypeType', 'xs:string'], 0), + ] + subclass = None + superclass = None + def __init__(self, FooType=None): + self.original_tagname_ = None + self.FooType = FooType + self.validate_FooTypeType(self.FooType) + def factory(*args_, **kwargs_): + if FooType1.subclass: + return FooType1.subclass(*args_, **kwargs_) + else: + return FooType1(*args_, **kwargs_) + factory = staticmethod(factory) + def get_FooType(self): return self.FooType + def set_FooType(self, FooType): self.FooType = FooType + def validate_FooTypeType(self, value): + # Validate type FooTypeType, a restriction on xs:string. + if value is not None and Validate_simpletypes_: + if len(value) < 12: + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on FooTypeType' % {"value" : value.encode("utf-8")} ) + if len(value) > 24: + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on FooTypeType' % {"value" : value.encode("utf-8")} ) + def hasContent_(self): + if ( + self.FooType is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='FooType1', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='FooType1') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='FooType1', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='FooType1'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='FooType1', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.FooType is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%sFooType>%s</%sFooType>%s' % (namespace_, self.gds_format_string(quote_xml(self.FooType).encode(ExternalEncoding), input_name='FooType'), namespace_, eol_)) + def exportLiteral(self, outfile, level, name_='FooType1'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.FooType is not None: + showIndent(outfile, level) + outfile.write('FooType=%s,\n' % quote_python(self.FooType).encode(ExternalEncoding)) + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'FooType': + FooType_ = child_.text + FooType_ = self.gds_validate_string(FooType_, node, 'FooType') + self.FooType = FooType_ + self.validate_FooTypeType(self.FooType) # validate type FooTypeType +# end class FooType1 + + +GDSClassesMapping = { + 'container': containerType, + 'sample2_bad': simpleOneType, + 'sample1': simpleOneType, + 'sample3_bad': simpleOneType, + 'sample2': simpleTwoType, + 'Foo': FooType1, +} + + +USAGE_TEXT = """ +Usage: python <Parser>.py [ -s ] <in_xml_file> +""" + + +def usage(): + print USAGE_TEXT + sys.exit(1) + + +def get_root_tag(node): + tag = Tag_pattern_.match(node.tag).groups()[-1] + rootClass = GDSClassesMapping.get(tag) + if rootClass is None: + rootClass = globals().get(tag) + return tag, rootClass + + +def parse(inFileName, silence=False): + doc = parsexml_(inFileName) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='', + pretty_print=True) + return rootObj + + +def parseEtree(inFileName, silence=False): + doc = parsexml_(inFileName) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) + if not silence: + content = etree_.tostring( + rootElement, pretty_print=True, + xml_declaration=True, encoding="utf-8") + sys.stdout.write(content) + sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + doc = parsexml_(StringIO(inString)) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='') + return rootObj + + +def parseLiteral(inFileName, silence=False): + doc = parsexml_(inFileName) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('#from validate_simpletypes2_sup import *\n\n') + sys.stdout.write('import validate_simpletypes2_sup as model_\n\n') + sys.stdout.write('rootObj = model_.rootClass(\n') + rootObj.exportLiteral(sys.stdout, 0, name_=rootTag) + sys.stdout.write(')\n') + return rootObj + + +def main(): + args = sys.argv[1:] + if len(args) == 1: + parse(args[0]) + else: + usage() + + +if __name__ == '__main__': + #import pdb; pdb.set_trace() + main() + + +__all__ = [ + "FooType1", + "containerType", + "simpleOneType", + "simpleTwoType" +] diff --git a/tests/validate_simpletypes2_warnings.txt b/tests/validate_simpletypes2_warnings.txt new file mode 100644 index 0000000..39f7751 --- /dev/null +++ b/tests/validate_simpletypes2_warnings.txt @@ -0,0 +1,20 @@ +tests/validate_simpletypes2_sup.py:889: UserWarning: Value "floatxx" does not match xsd enumeration restriction on token_enum_st + warnings.warn('Value "%(value)s" does not match xsd enumeration restriction on token_enum_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:896: UserWarning: Value "22" does not match xsd maxInclusive restriction on integer_range_incl_st + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on integer_range_incl_st' % {"value" : value} ) +tests/validate_simpletypes2_sup.py:901: UserWarning: Value "-40" does not match xsd minExclusive restriction on integer_range_excl_st + warnings.warn('Value "%(value)s" does not match xsd minExclusive restriction on integer_range_excl_st' % {"value" : value} ) +tests/validate_simpletypes2_sup.py:908: UserWarning: Value "mno pqr" does not match xsd minLength restriction on min_max_length_st + warnings.warn('Value "%(value)s" does not match xsd minLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:915: UserWarning: Value "012345" does not match xsd length restriction on length_st + warnings.warn('Value "%(value)s" does not match xsd length restriction on length_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:925: UserWarning: Value "0.2" does not match xsd minInclusive restriction on anonymous_float_valueType + warnings.warn('Value "%(value)s" does not match xsd minInclusive restriction on anonymous_float_valueType' % {"value" : value} ) +tests/validate_simpletypes2_sup.py:894: UserWarning: Value "-50" does not match xsd minInclusive restriction on integer_range_incl_st + warnings.warn('Value "%(value)s" does not match xsd minInclusive restriction on integer_range_incl_st' % {"value" : value} ) +tests/validate_simpletypes2_sup.py:910: UserWarning: Value "asdf asdf asdf adf asdf asdf" does not match xsd maxLength restriction on min_max_length_st + warnings.warn('Value "%(value)s" does not match xsd maxLength restriction on min_max_length_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:915: UserWarning: Value "01234567890" does not match xsd length restriction on length_st + warnings.warn('Value "%(value)s" does not match xsd length restriction on length_st' % {"value" : value.encode("utf-8")} ) +tests/validate_simpletypes2_sup.py:927: UserWarning: Value "6.6" does not match xsd maxInclusive restriction on anonymous_float_valueType + warnings.warn('Value "%(value)s" does not match xsd maxInclusive restriction on anonymous_float_valueType' % {"value" : value} ) diff --git a/tutorial/generateds_tutorial.html b/tutorial/generateds_tutorial.html index 4229ff0..4ede248 100644 --- a/tutorial/generateds_tutorial.html +++ b/tutorial/generateds_tutorial.html @@ -219,7 +219,7 @@ They are used by updateversion.py. --> <col class="field-name" /> <col class="field-body" /> <tbody valign="top"> -<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.13a</td> +<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.14a</td> </tr> </tbody> </table> @@ -228,7 +228,7 @@ They are used by updateversion.py. --> <col class="field-name" /> <col class="field-body" /> <tbody valign="top"> -<tr class="field"><th class="field-name">date:</th><td class="field-body">September 09, 2014</td> +<tr class="field"><th class="field-name">date:</th><td class="field-body">October 08, 2014</td> </tr> </tbody> </table> @@ -1210,7 +1210,7 @@ named <tt class="docutils literal">garden_api.py</tt>, you can create an instanc <div class="footer"> <hr class="footer" /> <a class="reference external" href="generateds_tutorial.txt">View document source</a>. -Generated on: 2014-09-09 19:14 UTC. +Generated on: 2014-10-08 22:22 UTC. Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source. </div> diff --git a/tutorial/generateds_tutorial.txt b/tutorial/generateds_tutorial.txt index 46348ce..7f91fd9 100644 --- a/tutorial/generateds_tutorial.txt +++ b/tutorial/generateds_tutorial.txt @@ -11,7 +11,7 @@ generateDS -- Introduction and Tutorial .. version -:revision: 2.13b +:revision: 2.14a .. version diff --git a/tutorial/generateds_tutorial.zip b/tutorial/generateds_tutorial.zip index 157eecae050a3a0201ce0ca0984aaeb93fe97c59..8a4d0465c6f1bb77ab1c106245753ca94932221a 100644 GIT binary patch delta 11063 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 delta 11043 zcmV+;E8Nul`~vy>0vk|E0|XQR000O8Y+)%yRzk-JQvv`00|fv87n8pN7YlTFbX8Od z00Y}l50j9U6n~vlJ#XAF4Bh=JxCBUmoGwi>83<6cS%M}&fo5o@o=&3ALS@mA<XjBo z$Cs4te0b;(EtVzn@$vEL`uZcQI$*%4Gv54!%?55mj${Xu9R<+A!o!d$I_;|up<h>3 zt%uxFtl>sKB77fO-|4`o)<#UJ2K#q9`eONh-YbfS3X#xDf755Zx|Q4-p5^mguBI)N z^BPXR!ihbHliwA`8tTXB4sEXC+p>jIa|V|e7gz7ZQB2b%uw({du4NWQ4Vi~DnW)J} z>B42Om`rqgOu#9InA_ACcMA8n4{+xUhJ^K6PU`uXhG<aK-1;djZ9A7Y^N*6@?Ng50 zFzI)kq?iuif7Wivvs)ljVahU>!qmWS_v$njdbfjP>r4yFX@Vak8zqQ%8n`OM4r~!P zZ73EHe9~R-@f?iTiMe3of|Jte44O!tF#2_W2g$V9=@+i5jD04u29MbDM>-O^=&^W( z8(Y8@lqq`_yC^IPujLfnX3##-n}&KF6MKat^_1^Pf7>;%h$v!F!Zka_WFFR*CeJ4e zKthIPcxaqQo;VwXWnjanVPAw1$x<HntO`$wdP&yak0pO0XH{_s&nJS>r3!S&ENoh4 z_XdyUplER#17G)%3_soyCJc&ZJmXbs(_>0#au~XLvS4ko&utA?Rke{-LKckw#kgSn zVC7l8BlM8|EPm4}Kjo_W2T)4`1QY-O00;otVJSrrMRRXTF8~1Tle+>W1F2CDlktHR zv-ScZ27f?0FNwy%P9pzvlL9%slMFwpyj1B7jQiP(p?GpOxp;&o|8yjn>wHb2=1w}i zajV41{1oVLb|HMbH4-<=*a&CvDXb6BIHT4Xy(m|xS#c>MW#&aZQ%1n@IYvvYY@mJO z`*%0ueLPp0QJ0=2*~^IN9JW!diRxqtgE8YYE`LM&re#?6SdYeL)Z+HOB$YD*@$7sz zMOy?zYRF8)UEk*Xq9`?y5^PhT7viccH$*If5WPST+PF(FT7W@0#rS=`6z+i$AJ*W5 zG6B*r1)vHCR^Twi2_!UudXQ<3kqaFF3|qt;lbBNwU7aGHKY#yTnE6trvcADcAP)h( zE`QKMfw?w#N4$Va6xmz2ssrR81Wq<cAaHSW%t*Y0<S{YYyF`wq%EG`(Sq6}AMO}bM zP9&Q)s(V#{2j@d%OA&Sej}(9du%M}^zTn{@cR@#Csu>Xi$z#fD22=oE>71*!$vUXR znh^;xa0sMC5_AZs;q=Hj?s>4_`V?{p@P8;T^c>tZEwQl$oUrI#XY`2WSr%QHVC&!o zWHofK5%HYEGWQwUjJ%G#@VN~_DRMvy!0W*M!pf>PMs>JoVw4*Mlf=_L^#yjc)b|Tt z+!>iTnhd6sFSD7+U;4lOpbz!(3N-eBgDj7z#<Wx+W|Ho_C*bNf&-=FCV7U^hBY%#q zj61Ow5;_~m6_WH)><fu9WJB;Wd`Oe99W%$#`Cxj!iQh-#P^%#mk|=2enXCsx?#j^- z7cn|Ts--F7OT`&h028it6{hGH!WHCmc(J=ouN?9hgXzU4@;?DIVWCl}$EuSN08J1y zfza?W2<-@jiROjOmsG3(vjw=REPrx%JsnJ+ZsLXNTW=EerX!BG^-P)P;7iCEh9+0@ zcmYZ^Q%iXtWAB1-c{Z3n+r;HHK@fcqgo8kcZ7SkH8i*>3LV@VcD^uz;Y^;<+@oPYF z)Tfo+Zo#`f8~2$MM&>axFhx--e3Clso+EZWI^3rtUt&G!<?9dc_ys#O1b^&P`WS|z zcFaJO5nr(9a=vuvy+HJORQR=UTZG%<9XzfQ{C${~qJV(7o4Bkbt0(Gf<#BRyHkf|h zqmjH*G&{+DRE~?kPsoV;=uXzTg491!5PL<~hqR6l*i_>O=Kt$HQTvu*3`G}+Xn=eM zR86V!a8gSji6Za_b+Mu06Mw?756homyO>~=!a*SUa}bWPyok_~5DZGcHSt~9<eU-f z(FH>62_lAJNv~Bo(#H{k=i#b=@H3Pl1ZHIz6)^<%;ZhbEmLVK^7mQwyE)aU>h#tWa zQXrf$!x0wFvB+J7MU@dJ3Ar8%GI`3F_4z8q>;f?ZAjC`rvc+2XN`HHl0;8M7%4tJ0 z@D9(ncu-pS8DxIGjFSkSg%s+81zW}CGEC)zp3keofFD&L$OTXkLX=63890UKeLC>Q zf)f^;KyU)U{Yc=11&3jKCMHKPwI5%OKEn(`9A|49Dn3VCd(@&IR|X|4D6%-m2p>rt zS}VQ4;Lc_~p$T!w0)MhYAZcAmw0OQiJbUy5BNGH=vjPk1D<f)9E^#=9o?z}NG13J) z3_v_Ckh-!;%J5z$RYS@rXNY2tqP+2-2%GuGg|JWrL)on>kf`jJ#u(+N41N+p<zw&K z-snRU^X#2tP(3-HUh&`p7G3SIj=)lEk#hGEE8+CqWk#0vb$>Et6R39!if{7-I0%vL zN*8xPq(WD>OZW>(rAzjQ90$uaq+USCxD-p3<cli7WHHhDPDoCs4Q1*!@P{l|$T`Fm zxy)i^+8`l2|3y~;=A{m1%;qeL0sDBy{SE5nUh+M>da^Aogw#9(8at@t=G7a(Vce8v zYXR&M0k9A?7JssrphC`cRUTa9Sb}_8)SJ#B^Y5@yQlTCmMnK2$|GIMb*gKA9ucikr zXJJCb#vROVkZG-=85M%C&Jkzxq>8{K_3&wAp?S&!w>*$udsTyks|E#!R)eS*L@<M6 zib29J1_j+>(80p7qjV&&bQBz0IucFkC^)oqBzj6m!GHdxBeA7)6!eykaw~9tHe?x3 z_QT?BF1z)eR$1ruMpaOdltA+0xLNyBE4U5c0uLQ$AYOx=i@DZmqrF9yas88+gXEam zo(z%#gD-#@w96hXfXrOpzKW9sgs!JH$R$w&N@o^qE(z7Z3NpzyufZo4=1Q6_)9jNu zMKy+M-ha8ytAykX;@Co|MtIPF1C2`wCWuOWt?V>#{9s0Vm-^lc15k=c%}fA#*a{DV zad4@@iyeG?jyF1CQQECD42YEFl-+kfaQIldT|uqQF469_B*G#P?18|0e#>}_Iu`C5 z=@qeUO}&=ec7N|tDQ=<_t7+oo(<c<^PoGYQHh*O0zR$e`2RBPpKmsq5_&2Z|J-nek zSpPSVS*P;T!}>RCm$FCrV*J&$sxfMTL(P^oV4W>%=wc{hmafh%&;t3v?rx@B83-oa zW8n2*TF3F%d{mXqaFjqr{1##%*fAw^hqVnmhBU+7nE7-W?uH81)LZ%}#X*)-(EtZ$ zbAR#!`0Gny<2P)<AYl(AT!?j;P$y9cx5U`r(4RKJ0B%NyklliXEfNMy!X&<X<aF5h z^C1%E7LQJSJGyh%tb)vmPq6yaXRe(k<ldGwA#C<+K*2GD$j}9G6z~nZksCCeAn)&S zVjr!jZ{xGQjadsjqAFJyT1M>zi6pbN$bZ1SfE@;B8`fs}lx-e4cRl+Xq#gpi0QwRf z);kz0-@+Y)T)@bQJ&?0z*q#j02V%NmPTR473ou#@Fz`_sV1P%Sb{&6ETO%^}wJ+c> zmR65YXZ+}efrAM`0T~7)?&XFP-E@(DB!v&rq3cCJ>(Tf0Y{*q%x18GMw93!`8h_VE z#rP?}G{AMKn={B>u|XsMy^_hDwX9Yjhr$nzxdpkcjpu?OynDAt=!c~Nw`>TZ6msSm zbGsJhjEzVt?C%IHc~YNNrzx<bxiYOqq$(h#U!s>-(?D+kSVi%Ia-q6_3c-ucTw1Bx z!4lRUycn|8xVBkyo3Mum=x}KyGk-w|7>dn}4bI>|ifE~Aqjs~@D}g^{LqR{FC2HE| zNH5y75jEyb-C<jOp|5wiUzy>+)?%mHKu)KwEs)&Ue4j;u$CMPrJ3O_NQAz;B+e!L% z!p^jh;zD60w60nF(WuV66j7NA5s%jg{#CR%EW!}?)zyJ~`tB>Rb+8pgh<_P#sJO(O zGd8G$q2fMHF3aU80K1dvk_#yyDOCdLg$C{6fiB#hDHM7MJK<`nyrbz9Ij2?vMtiJ` z3UEQIQB&qSRgeLbu1eUG{5k@GM~H@0m%tq;i%oyC7FlO=@I221Ig4^1M>Yd>O$2ZV zPR?I{cy~&MhzbNvYR;(_0DoY_j$jzLZl&RRpJX1>2gZE>IN}HVZuDRxkF9jyn8PI3 zz{QF*)^+BT@#4Tw*f_avDoQCd7}v_m-=Q(q!Vjm~E#^fcNs5777=tu;ps|N+DUjx_ zNgNKL)#7)N3s73h0*ly%>hYCEvw~p3j;5yB%mU|w6wEH#`D2L{l7Gk8K{4`I;u|)* zpFxN`B5bTR&DuPfu+bp=t{WKrRQwUA;<cD*@YzjW6i5=M%-r70@bf6c!N?NJQDezg zfuGS?s~vX)b}eL{9D<BZXi7AGk_*caNX1l4#^PPM(l!e6Fm#P`R#ca(1V-`52@5GC z|9~LH2b8TG$N>xF)qks37|qgUQr(0362d^7@a1&l4^RQF)q&qoS#aC-+m8^Y&gACg zeCiowG|Dw?Pza1l7CbxmM`0gn+YJb;;MLB|72_!kt<A{qnXj4dn4v*a2lBp%Z>bW- zBR}M44Nj5*$dsMBK_85jMH|KfCF=;zf3`;fqbGC#EV$>rW`8B@8$<$z{ChJBc}&1# z@w~=@<=JFp-+ChKXzwbT-9fI|8avKZM~-Q@5+W7s4+A6NBh;$kV7r!c*wAm4)5OD0 z@6iR?glCOmFT}qt*Nr4n^Xrum_#qNurRw&2hYS)!EgKwQLm)3-(U(Bj0Qk+Y_D1vx zs|=z%$<YxeRez8%63I|>U^m8~+=kk%d03!6IkgqIPH{R(5I^@R6=)tQw@|8U!R@2> zw7zq=rQ;^|n-OtY$XVQ($^3wz3`;$Rt#yf^r!N1oUfIwUf)3OkD*d?9c27Y&=#*$% zmF$nkqP|C|#1TDhs^3KR&4Z~E0!AvpviAw^KIIw>Zhxq26B}2upn@7yT_n-A=KL^M zc}XrCwNJz}bi_4|llV5%1yxn)3zGB=#M2>5I3uB=fD!~wL1wB6Pb8B8lCj$u8=$Rr zjSxR+TUEG?@0k+<Yb?@etYV-i(YAAp_Cqha7xVI47iijKvnJ!-V%i9vj|_do4-SUB zCTQ{+7Jm*x2K8_2q!FV~S!oE`LUzK9x6MYCE9mT%xc{!{+x;^9KWaGFmI8jj@&(d~ zgPr>gfORBE86pH3$_@`W&k{i1(DEc?P+NRKVXN|7I}cl*C9|N{N<1PsWc(*+{jI+x zw_W$yIPm2@E`H}KtMO&haJI8?rbjWj#0hCTynjN4KebakE$4W6(7(euPCCBK&vS`X ze{cXgM6SIHm@6~LU57T7%CO+e6m4aVb=uPu1%nf=7Bn$c6P;Fl<(^1;xzzGVBDNxe zHW?q$-h)TZ_tV(VIgxI)^cOp<;})b4G=qgUcX7(Dz}}0r6*gP)Co}~|F?K*LTi6<x zlz(fmt6^_y8eFi<SARi~x5rt~o%4AO!Tb>5+Qwh4)2L!t!rPd%2~u5bxxM=;<e@P( zet&13A0{)8lnfC!v}8&~&broL9Qyw=;1eZXI-y)f<y3>bm-sT8e(R40dsTa`=TJ-- z)7RsueM=v5D9~zk*M)uNBnXQ)8PJ`{2!E)6&rwC~9zdt>Sje!RxeY3MXHIQfRmi&0 z?8;Gertit>-Upr?xSsQD-Nc{P3jk#zCX(4oq*;eVztn1p4Safmg@8;!z(q;}Yiy2y zxhu~zaJ`RoYinFG3^p|$hXrD+u7gu5r~u&XD=4SA0~(i2a6$<!4)AopRp7!Nkbh7A z%54ALwTbmMZ|6od^92)&&EA%i4jNVhcfGr>oi<I;rUYS!blUFYqzN-9#b#!Qmg%Pr zZP6C)!jId1Ss<f(bmxumvBzodiqj_4p4-F*haPP~sQ>n@3Uh;7MBn}nIwv(HD-squ zIEs0us3T^~Wnv@tPiY-U8}irtN`E<{<`s47l(W>i$LK=q(#-(d*$FohjKp)}6HX8| z1}8smQmj-oB;cD(?hjf<xbeEco5-@t=UNul%JAukqSb4=)h4L;AaLVdb_+NTRfMUA z?BfJ(8Yb#qC8zZeSe&&|%%HIfo+V)K=w|xfWkM|$;45tgh1cVF(Mu1QHGi%V>Q1vg zK5N7f-TD#L?l82Z2522c;=39rmnhXfN+QJ%Zef-n0XcoSQruRq6YL{{wfc&_G|F`d z{2v*5rslc^Qiu-ogB3T<Wm(TxV@FGu)ZwbzFLjz^MUW!`vUlbhzl;7qQ9LgjnR97? z-@fr|W|OwrDG&R-9=Z@2I)AHAZmP4@WxfN)VIVhm9K)gd#@&F~26=Fu-Yb<(>z!9) zc-I~K!ZA!#bPRPsdu{Hi0y`+pU6p$(YsZG11YQ;AF0qWp<v$)AsDq(^$Bw=ED$c6l z{%L#g&ber>z8Vl+X7xxXciY|B(m(yA4$i$(0y-tLg@HS@KCO@J+<zPo_X_s1ZyXY@ zpMV*1qtsMDd`B4;n8_-U#c<2+9%@lZwh1e6OvYy-`#UTk+d7;#8fxtjZ{Dd+pS~wr z;P=o-nLLzyd+H!!ykTR3M!fC+MA69eYjbyS<m${S=>YQ7{r?u&fHO^SR!iEd9@%mY zPdJsyE^)L1d|KL?7JmUc1+ChE!O5_~2!;Oz3vnPg**Bs!5ToLb&HreVKBeC%<KymW z9N`|l9V6b;VZc)xd~a7&XUpu!Mztc!SwJNmv&K>KcmlY!#jsbNcf>b*Z8~@38ul#I zBG(XJQK{(v+Pl){wyh)n9e)K{PfF4yDal9DsH1okS#~^??SGC%$LTm34n#sS5(-cO zQWE>2e|z6v@4`t+c8{s1jU^oK*td9ZkKgXjlqmO`nlC~Iz+T;vxy07{N*$t%K|;Tq zp&1^itaE`_vX#~q2w*0%=7^q~^JpeY|7IgM2_!%aB&(cpk#I@|-<t&OCrj5rf^xuO z(PkX?Xf`y8B!BKx#y$bDE{@8&iH~MpOfObo-my(O=Nv?Z?kVVk=V@eC_EK3iz`c>B zWA^Y^Uce!L3Vd2Zn1Sf+ig+im|7y@qGg)4!)@X^<w!0!@G+F58*sM^3P$bB=T4z~_ zF;b-Xkvq}~z2Df4p(RYkwjD@k3C>NB*a^50g_T1Hs(+l8*rE5e+<|e;l4*Mgt9=lD z%`V8fv76}+DA1ckH=}c>$p3Cz*c}rCXgt|n<APA4Kvrg8e43F0#QhHm0bnfKxY1Ob zw?p3!phestvKx^8@N)~`!~iSq0=HT@VJ<Q?!*!MtV3tIhOOQvbuyw87@k@b5`oo4n zDGF?*9DmtCBOs0FZS)oM0abceYQqwnGb;cKJZfcuyChyv%_BS}#rP97?29$(ZWdfJ z^7MX=`w;6z(BQqvWDTkfHK@4jugSF^lyO;Gp<XW6YIwESDsY{^JesXNtw>ergpVU9 zKN6pBTDl=~fQ0SQTxo1PZyUbZK4l^#H2?|QPk&cueSyM^>GEJd2-T1Jra}o`>BE*g z)M@Pw-ef5xO;yrZmdYP_rnWbAKc@@W2K<mAcIw{`e~qpq|0;J4Ki;6mHA9h6*aH}r z`!vIWAFu0yp6_{-&erTErhb&f4V1M8##hFu!}fcpV!gw6d4uW=^y6@>(h%WXM_djB zq<_$*zSS<$3a^gsVaNaipCJ0HIB=IUc!02kiiHmJ>O(ITs}Gm!SN}Rz1BauN7w|k^ zB}@JtQ!exGYM-KCFgn}g2F$b1&w&sb7t+KGHj^x0^PkZLn6xx+T`GCO=PU~5#1puI zdyt}aQ{h?g1YqnuY?onR)MmhDtUOFJ!hfMXs5|l13uGte96t6&BOJ+o_*Kyhzj8*X z84Dih4~C(`Fh~Q3VJr^t7{<QS(W|yuf}L)M)Mv`S!{^tllpPeDBggW{p@$M7(X}4m zngGDghH@WOQNptvVaSS)fdL(%{Ok!hT<E5L-Zc$Cns1_vB)MQZF)kA#djranJ%2>Q zk~-laLI<26;KXwfF;PfQ8k-$EkOHwxopa0(L<pfbh<ej8e%!g6u|q7B3@#sdQAICf z?Ircro<9w+-JF402~Of=iA4f~Q7O3+(EJiX-V2T6ay=Eco|Dx{8(O{jfM6m{sc^0# zZ#6t~Vqwjq{DP%J4$rpZN&C%~E`Q$NIMh}wbpeN}m>^R-X3l0JYZx>`iYJuCf~kr| zYG3aQiVBU4ZQ+Brx3{Elb_pMphlj@Q$g^QTi5G)f_|rkVq6EWrz|bkSmp<`bYM*sG z(j5v;=?foXmaDViDkI@mo^>+5+%X6?tqOj<0XtHVhJUzF)ZeRFL4r&1(tqrC4Y_Oy zc*O@LwT%gTZFUdhONUF!F#$S+#wQjrhoeGW6Y{9~xjFy?#*R|bwa{{%*%8Q;(GnZc z32b)AqV4S<ZvY}8Mi=({RUi>1{DBjdfq~Xl_rOmVr3pu%@=gburr7sVz3-Czj$vcv z4W&|)?-*DkaQJm0zgnPtfPZ3LB>}kS5Ukb5_+Az?=s6_;AQDLnhkX)Nfa_=33XTE% zp21mw`HIxYoo3)CnX6`cU(J;y687<}@Q>jh2p+C9t2-0H0$Vy@k!pUB%<VT&w1wDe z7LZvewFW;HIci;ui{)G~$}rp=1Od+VV=r1LwpjLtVec$n7Hjwg(tjB(lDPNFz*6Pj ztwaP!=ho>D5eN5#`C49rju-r4A*+lZEzX3lA$5QRwETPYkA6rVL`SZ=NHc>gJ90@k zwnMEockrmC10>iT+JD^AKCeT25BxWN8Sr;UF|;aOVmD!P<7|p7M%F}CI_ZdXfT{Sc zv?OAIxJWW7DBDX1HGkd>xLjS$q9R7ozW|o2zl-2G*G7#SSHxjrx!OaovD^pQ;$kO! zuvrGF>WAc!&O4gBjp-1bE>;V;yq)EO6I?c0Gwx)?=sN=+qOLYDDrwo2;f$!wvf&Rw zc3_}_y(CBpYiQdTCY<(4CJC6}=Q2w)FYjGU6Zc_~D48Ol+kf;Tp7I|Ue-FM1@NG}) zn8ccXiAg$GEVi^#$WZ-JcI6}FoI)%Qo*hDQ49sm%vPP77WiyM!74Eq$d8JrV=iTcD zHo96ttlEyut}9c<!`cnielEYVV#x@v4oG&`;y57<x$~SHP^Ga|YMt7xCMp2<p|f<c zcKj$h)t4X&?SGtKr1DDIu|S}eH(6-wbuD_6yD5-}ZwB?sg93IS4zIPzUK4i7HB~W; zfI-uc0s@1x!Fi~Jf2c==QSz+KY(HF!HSb}#zpjcUs5{php^0BMMkT2WtQKlqpJ>2< zQ-jYegcg0hNAwb0Xv;;#Zq)8a`sSy(rJs~!15#727JsCtP>Pl*Eq|TD0s@620eo(y z1v|9Qq-_<KJYKGHiC>@@Q}`bZj1n*%gw4u}OO7gv(GwWM()%7zH}QV2MRD45G%N3T zx0)OE!iVA0UHcMZ8@hB5&|Ej(x|_crmjHf9ndJOw3BoMzHwIfu;Xi^M+-w`LOr~sO zO_u(LiGSff8t0XZI(n%NeA`@ZQhjI?CTgk>8^3`v>Z=IMAC@xbYN#7&sa-YII&HGH zvnq|%@2o~^-MFtR?bYwAR)ekU&DUf{8~+6Koqe8#Iz0LQ_}%0SE!6kNlheO_p@lm7 z;qcwbtK;n#$}>5%g_SkbNazO3*|LNJ!EqXsOn<eMNa$uDxqAf#F_{n$673DiB|`26 z>54&vWO2(3hT95+53@Y*(*mkx#Co~eRh%<{z<!Kgfq1zF(Mc@Dfd7sFmZ|<FWHo>y z3rc}rwmw^s?NVwBNm?a>y4syxls4ypn8zgt(#XckH;DC+#(*i~2b*l1oC2#eRO802 z#DBtI7YDpJ!cnZr>)00rKT$hY0*$J9VH^P6AUJR0v|##olcJI!L{Rm@bWusV189V9 zl+$P#8$6cw3^{h5AvQOZdk<Gd5Lr7W7j4c-XIKyqqs0QSPMCX{vU5?Gfr#A!i`}JE zUK9+|EMcRCj^;JRc>&_6tDFs+)-%Xt$$z+L+4;x2^vg4CO}#Dlc{u9vwAjBDCzBPC zc=H&G);-$Y-P`%;^~otdZ|$`K?UJe~LF%JC%${Z7quFv~79OeO-i4bWCh-G1UbB#8 zei7fo6BSLnFFPAI%r5@>3h?aKMqfWz%lc6sD>R0y?TpesI~plaJ9%s3E$MEpE`RY@ zs+t~;BNEq|Jrczo(K5@sPfdEU7GR^Lxu<2p&?PHwtzqapof?FQtNUzEOl$3w?Y_c| zEX4-A%Kl(57jf>7e=Ckj=Ivd0Tv^wY(hjpcSyqo33)pYe92S$t1RM9j&YCu~wb^oB ztz_3!x(Q^b$L+Gy9V<JjE)Z8@jDMG|WML&(*fw@S=N$Z5k#8h$20D-=X$9UY+*^45 z>6@G&&VQM2mgEDx?jL=dSqW^KSg~({#ubUV5a~ygj0qLk!2ug**(lA(hH6+gMSGO0 zk-8jjc6{(QSwD)}gdc&CDPzb_1%NO=j@(5sCoN&$m0aM=+o`_O_;t0_A%E-mmEBXB zGXC0}B&!v%>|0W2XhG68a6k+Y1jU|$n1fK~00@WN2}{gcZQ^LffQ&&5xIv-@XaG%) zy*Lzib>QZ1kT`f0WmyfaW8G5C2?JAX*@GVZZf8~GJ8H+<iPLMgRt3R>;6e3Hqwe6% zm)ch{S;gU->^cm;4fmezKYx9)|KuB}sJ&}xWW2vg^x&iMqi75bS$1mqy|j5be&`sK zgK2mWf(I}7G0xAjBA(K#aQQ{FQ0huwooPyd#>8m3+)dFDSh~DW@;G6QOSf1cfG+WY zf$9KVb^XVKpxjV$mV-jaV_W8HvKc)Hp$oE<11uK)68uw4x=umAOg^iJVH&O+JiesV zJC7K~<c{XzKIa19j8Vw?@b(yc<_r))Oli?xVH3xBp0V9aPlhHmvy=Jbq&TMN(fH{f zlN%>30X~ySCm#WQlW8X#7w?;<o6xn9wk@RXN?!QMqoj!K$GE>2lba_Ve;DN##V~yM z@V6WIja`z83jKPj)*J;02bOX7sQN|^6Nn^f=rm6(BJ}|9U3>UgZg2?+^QDFdCoCU^ z@%UmqwAu(k9>R>7u?BgK^?mB}qm1Pj#Sp|s<KxK@cA_W3{!S&#nTIG{rB5N-rK=ui zd1R5Dsly+niet{GaGWZce+*dSAnZlOEJ=Fw=zAqBDg_zL+D>eKU1|<!lR!913=#e< z`q|m9Oil2BOFj{Gb<8phWB{4M^}=G|<QyMGhz>rmMEEbPX;16ZJ(m^Ht$qN>-=eF& zewzS3E@NLui#_!uK$X-N216vL{J`J(lS1sReRyYx>e-<D1>n@?54Q+$dgQwH;k}AC zWEdaSlg20@7nn-$&p40qlk4|J;KHBw9G>B41LB6~ll>@{H}s(t7!N@Gsan&$O`?nG z6=d1U)9Ls!TFyS<!(;W>V0@8htE-|v_&C}l01h;G!~;S_i#N1SlglYA1i(0O0F(PE zDGBY_uW;(fE93K%Eh;2`Jb(LoY!Op0tU)qKSZ<rkEkvK&&uPycWmU`yoiEb^Sp!Wa zbc4be)v8Yqdc8r_(3n%W1Di!o@eEgdK);BP03sn>dG%IgM)|vvk>sXn>HiG%zr;}W z9K_WG|G(G#ds*WFezPTuB!9aPe@-=5l;3SIXJSJ4Y2(|5B=oR<&}|BY>(?-&a7`so zI{xCRK?&52U|>4&+4TMC;mhOc<oKtF8Xvozt^Wq^i|8WW7vSTwXV1X)3!hn%o-?-+ zE~5M@=~?i;2$ckOHC^iA#<$6`59rnsoEMZt;5qe>`t|zb-u^Gb&#L!6>X6~@4#GW4 z9-=PkF+EBEA%psVx@$xa`TF|iDHuWmvLzCFikjSX3Im!>S&@4n;Z^gqKf`}8Tw|Go zhC+RAgV6neE(mf!GC->ZF7HZx9Sg~#s%7Q;zrn95s8g1W*G)|!QJ>x?&KRIUWE&5W z>ao~uH2cP^5d-85A~Go3C?<x2JPqQAxxv2(f7U`ft(#YW#8-HPunMap)=5@L*M3Jb z3IIxNM+Wi)o}INF!q65TfN7>F<p9-CiP8dqbOjEonNIGMDAZwd@8M%AxHpPM5CA-) za_^&0QJ%&{XAk`o@*P%0fTHj4G58KCXKjQr)jM2Op1W~8hXw$KMO6674IGB>nhv%= z)farVeFTPo5A5t&?H>NF-Zk#h^NDqFiB&yAs5q7<2nAXvN|>my?PUr%<SYDz6`K2h z^ojo&guyy^UaNG-ZQG`^@_;ce<m=tK+h1m+)dIrn)0dU<!Oy|zI?b+%q##B-<@~u8 z7J?HuaFm=^L)C1wzJr-150V>*H>$oe>xAE222rzrDvKarN&+z-vn71A$R1mY7PIVX zy}`Nd7M23Bxm>skQ{%?@bsQk30VP|#y>{$|2~di1q(rZFLil-7TrHxtWFo4pd4$I^ zh!;V(h(Y`kCBVqbgVZ5hvAi2n*de$L@;L<(id+yna)CbAN!HlpSYKuV4!j(j*yVJ8 zGRjwfDT40sbobMUbvW9e($QX3o(GQhCvdb&l|VeO%PGS&{?62xr~}<eLRk-8wLzd( z<&NQ81h-A83}URy9eQ26C?>VzUagj&XE@ysFMQ12<h5U-1V}HJ$f*Ds+gNUO{q<UB zA>&R8M16XX>DT!oV~eLQcE`I<ch!%EWC;p?mG9>o$=jN~#X>bhXk4x~P6{A%Z#eH5 z;4%bhDcK^$H=N7P3mTcMZm5s-I$i)Q7T&S%IIn1M@dbo$!K3ySO`sjYwd=$z&I!F; zP@5Ir*1`@yOeTL-?C{~khw;1PpMDx2y?wp&&*y)6|HH}a!#5q+;cwx|tJ6vN_C<Jq z^!Cl<@Mv=SIoRRd@$>E2;qcwb@tfn#*x^LIvH?3x-W~pUeDdne%P++a8^`(5rbIR9 zps3|dL3Ov!Fh+GmnkgKxBSG+G=Yc7>0{a@C|MTYhqt2<*F|H5F#X(8R&S89C|Ngr_ z)l`DRcKo6M);WUrF)}X0A|-PUZBMU%<1_&%zkzCkbTNa329SjOQWtE*h<+sws2yJ& z)J39n`G%Z`UGhy!hJ+C(wi^MwWpo+cW*FTt;v|kENa8r!>l#e>jUrMN9A2`^xoPxt zEQOac(oN_IY2e63Y?TzU%HN0(#$izHMV{Le^m#!Y4*VM9>~!{qmP)|fEN4o8w<a0v zaTHuMn_=l6&I?Jda5&PXHUoTp-EzrSFDZSLBScql#Aw%a;(LFB<*dM6S1%{W&~Z-` zOSi#NqU>(JtaLLal14?Vv5BKuy5u^PP!)bwEoR%}N|!z3atgTih?+Lhf)sD6rqN$5 zmdT}B;Kh0no<*=}VZ5q6BPptXq4R$vMNp_C5o~+R$!vO{^n(Mto;8&hLc%oLoRXBM z*GxE@4)Jo<u}UsV><|&0okI~^sYzChAc9_<7BL*3P(p9nmC3#ZCaW;eO}G{yCW6#C zAbUlqdkVQHhsnMN)5DFBS@RhsMRD0}(_JFDjYSAp=Bv1Ra{$w;^a}WYA5fWQQr-v- zyiYa@^_e|*rGamVNrKiu5#*q^=TkQ?h0dB9e##c}f_D{<V2J0#3PoYGxQW&{AXM$B ziZt9vbdfL)JBT}$w6Jp9Qn0)lLXwZT^4JK6-E{|gv<u8pq2e7`ok$UhB-iE5s1t`T z4k0{7(LpKX94g@@;>EmwPo><=7?Kf4yQTrkb(*6fW73aOb`lc{1O?tCU{2>BK|U~5 zvCh_LDUeg#P7N&OGpueU8u^7u13jdYDUf%SBS>5|)*O!iRe{G>3n<rH9d`UzxOZZ1 zbqqMh*Z!kJjnx+4EiSZklS<$OSn5CGim>4q`rem|VNM{21SFt;{1RczRTI3^s^4SG z@g@xPC8L1139{v|I%^-YipKcikK0GJj(5Dc)-1e;a>Y;*%1VEE;ihVzPAPA`EfI9c zf2X&L8p|wAEa=dZGfI}Z%4dc?!=r+U)FELktb_bt5G1BM_cm^+fXy+((R1t%Dw_g# zVY!W(RL#I4y1|`)hIBh+5#l_9{FNvc<leP#=etfNyRCX{y1x1HR>`41Ch?6aDMh6V zK{gl%CfG1b_aV6O$!Pam^}lfM+x@*K;rq#v{S4ID>s~rsxS&)k@%P_7=UXrca%$X1 zySY*nsTz3>P(dX^tdwRkQO#gK^!PY1i*T0B*YGdA^j+`;FHlPZ1d|}T7_(n842KA8 zVJSscLdOV`bGbGG+fb8nG82=(x(W^1VJSrrMRRXTF8~1TlhwI0laZAZlaIUxlOVbz z2|zLc07GwNWiONex+s%%x*7q0laRVs0m+l-x>*7pYm))I6q8VE3X@^GKmtQ-lL5RG zlefD_0k4w0UIGGylL5RFlXJXA0)T~+0lXBG&%8wf28NRXycClvy-EVUhLZuj6qAa* dN&!Wa)xBK<Pn7_Z!2%SMNxm%xT)6-M005h->hk~q -- GitLab