diff --git a/README b/README index 6cead5c651ca88655cb61b6a346f8d5e4cf29862..702e796bb629a7c2f991fe39e08d1f1eca4cb29b 100644 --- a/README +++ b/README @@ -141,7 +141,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Change history -------------- -Version2.18a (08/13/2015) +Version2.17a (08/17/2015) +- Modified setup.py so that process_includes.py is installed where + it can be imported. +- Changed default settings for export -- Default is now to generate + only the normal export methods, instead of both normal and + literal. See command line option --export. - Fix to regex pattern used to capture "<![CDATA[ ... ]]>". The old pattern was dropping ending characters when the content contained HTML/XML markup. Thanks to Adrian Cook for this fix. @@ -150,14 +155,9 @@ Version2.18a (08/13/2015) be used to clean up special characters and other patterns in names. There are some notes in the document; search for "cleanup-name" in generateDS.html. Thanks to Fedor Tyurin for - this fix. - -Version 2.17a (05/28/2015) -- Modified setup.py so that process_includes.py is installed where - it can be imported. -- Changed default settings for export -- Default is now to generate - only the normal export methods, instead of both normal and - literal. See command line option --export. + suggesting and implementing this enhancement. +- Added unit test for enhanced cleanupName. Added documentation to + generateDS.txt. Version 2.16a (05/28/2015) - Added new command line option ("--preserve-cdata-tags") that diff --git a/generateDS.html b/generateDS.html index 0c8c03f890de485c2bc33852bbdd71b50a0406c1..a81211b4c29d78ae79a8658a91e663a375b4f0ae 100644 --- a/generateDS.html +++ b/generateDS.html @@ -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.16a</td> +<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.17a</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">August 13, 2015</td> +<tr class="field"><th class="field-name">date:</th><td class="field-body">August 17, 2015</td> </tr> </tbody> </table> @@ -269,120 +269,122 @@ to process the contents of an XML document.</td> <li><a class="reference internal" href="#packaging-your-code" id="id14">4 Packaging your code</a></li> <li><a class="reference internal" href="#the-command-line-interface-how-to-use-it" id="id15">5 The command line interface -- How to use it</a><ul class="auto-toc"> <li><a class="reference internal" href="#running-generateds-py" id="id16">5.1 Running <tt class="docutils literal">generateDS.py</tt></a></li> -<li><a class="reference internal" href="#name-conflicts" id="id17">5.2 Name conflicts</a><ul class="auto-toc"> -<li><a class="reference internal" href="#conflicts-with-python-keywords" id="id18">5.2.1 Conflicts with Python keywords</a></li> -<li><a class="reference internal" href="#conflicts-between-child-elements-and-attributes" id="id19">5.2.2 Conflicts between child elements and attributes</a></li> +<li><a class="reference internal" href="#command-line-options" id="id17">5.2 Command line options</a></li> +<li><a class="reference internal" href="#name-conflicts-etc" id="id18">5.3 Name conflicts etc.</a><ul class="auto-toc"> +<li><a class="reference internal" href="#conflicts-with-python-keywords" id="id19">5.3.1 Conflicts with Python keywords</a></li> +<li><a class="reference internal" href="#conflicts-between-child-elements-and-attributes" id="id20">5.3.2 Conflicts between child elements and attributes</a></li> +<li><a class="reference internal" href="#cleaning-up-names-with-special-characters-etc" id="id21">5.3.3 Cleaning up names with special characters etc.</a></li> </ul> </li> </ul> </li> -<li><a class="reference internal" href="#the-graphical-user-interface-how-to-use-it" id="id20">6 The graphical user interface -- How to use it</a></li> -<li><a class="reference internal" href="#common-problems" id="id21">7 Common problems</a><ul class="auto-toc"> -<li><a class="reference internal" href="#namespace-prefix-mis-match" id="id22">7.1 Namespace prefix mis-match</a></li> +<li><a class="reference internal" href="#the-graphical-user-interface-how-to-use-it" id="id22">6 The graphical user interface -- How to use it</a></li> +<li><a class="reference internal" href="#common-problems" id="id23">7 Common problems</a><ul class="auto-toc"> +<li><a class="reference internal" href="#namespace-prefix-mis-match" id="id24">7.1 Namespace prefix mis-match</a></li> </ul> </li> -<li><a class="reference internal" href="#supported-features-of-xml-schema" id="id23">8 Supported features of XML Schema</a><ul class="auto-toc"> -<li><a class="reference internal" href="#attributes-no-nested-children" id="id24">8.1 Attributes + no nested children</a></li> -<li><a class="reference internal" href="#mixed-content" id="id25">8.2 Mixed content</a></li> -<li><a class="reference internal" href="#anyattribute" id="id26">8.3 anyAttribute</a></li> -<li><a class="reference internal" href="#element-extensions" id="id27">8.4 Element extensions</a></li> -<li><a class="reference internal" href="#attribute-groups" id="id28">8.5 Attribute groups</a></li> -<li><a class="reference internal" href="#substitution-groups" id="id29">8.6 Substitution groups</a></li> -<li><a class="reference internal" href="#primitive-types" id="id30">8.7 Primitive types</a></li> -<li><a class="reference internal" href="#simpletype" id="id31">8.8 simpleType</a></li> -<li><a class="reference internal" href="#list-values-optional-values-maxoccurs-etc" id="id32">8.9 List values, optional values, maxOccurs, etc.</a></li> -<li><a class="reference internal" href="#simpletype-and-validators" id="id33">8.10 simpleType and validators</a><ul class="auto-toc"> -<li><a class="reference internal" href="#generating-validator-bodies-from-xml-schema" id="id34">8.10.1 Generating validator bodies from XML schema</a></li> -<li><a class="reference internal" href="#user-written-validator-bodies" id="id35">8.10.2 User written validator bodies</a></li> -<li><a class="reference internal" href="#turning-off-validation-of-simpletype-data" id="id36">8.10.3 Turning off validation of <tt class="docutils literal">simpleType</tt> data</a></li> -<li><a class="reference internal" href="#additional-notes-on-simpletype-validation" id="id37">8.10.4 Additional notes on <tt class="docutils literal">simpleType</tt> validation</a></li> +<li><a class="reference internal" href="#supported-features-of-xml-schema" id="id25">8 Supported features of XML Schema</a><ul class="auto-toc"> +<li><a class="reference internal" href="#attributes-no-nested-children" id="id26">8.1 Attributes + no nested children</a></li> +<li><a class="reference internal" href="#mixed-content" id="id27">8.2 Mixed content</a></li> +<li><a class="reference internal" href="#anyattribute" id="id28">8.3 anyAttribute</a></li> +<li><a class="reference internal" href="#element-extensions" id="id29">8.4 Element extensions</a></li> +<li><a class="reference internal" href="#attribute-groups" id="id30">8.5 Attribute groups</a></li> +<li><a class="reference internal" href="#substitution-groups" id="id31">8.6 Substitution groups</a></li> +<li><a class="reference internal" href="#primitive-types" id="id32">8.7 Primitive types</a></li> +<li><a class="reference internal" href="#simpletype" id="id33">8.8 simpleType</a></li> +<li><a class="reference internal" href="#list-values-optional-values-maxoccurs-etc" id="id34">8.9 List values, optional values, maxOccurs, etc.</a></li> +<li><a class="reference internal" href="#simpletype-and-validators" id="id35">8.10 simpleType and validators</a><ul class="auto-toc"> +<li><a class="reference internal" href="#generating-validator-bodies-from-xml-schema" id="id36">8.10.1 Generating validator bodies from XML schema</a></li> +<li><a class="reference internal" href="#user-written-validator-bodies" id="id37">8.10.2 User written validator bodies</a></li> +<li><a class="reference internal" href="#turning-off-validation-of-simpletype-data" id="id38">8.10.3 Turning off validation of <tt class="docutils literal">simpleType</tt> data</a></li> +<li><a class="reference internal" href="#additional-notes-on-simpletype-validation" id="id39">8.10.4 Additional notes on <tt class="docutils literal">simpleType</tt> validation</a></li> </ul> </li> -<li><a class="reference internal" href="#include-file-processing" id="id38">8.11 Include file processing</a></li> -<li><a class="reference internal" href="#abstract-types" id="id39">8.12 Abstract types</a></li> +<li><a class="reference internal" href="#include-file-processing" id="id40">8.11 Include file processing</a></li> +<li><a class="reference internal" href="#abstract-types" id="id41">8.12 Abstract types</a></li> </ul> </li> -<li><a class="reference internal" href="#the-xml-schema-input-to-generateds" id="id40">9 The XML schema input to generateDS</a><ul class="auto-toc"> -<li><a class="reference internal" href="#additional-constructions" id="id41">9.1 Additional constructions</a><ul class="auto-toc"> -<li><a class="reference internal" href="#complextype-at-top-level" id="id42">9.1.1 <complexType> at top-level</a></li> -<li><a class="reference internal" href="#use-of-ref-instead-of-name-and-type-attributes" id="id43">9.1.2 Use of "ref" instead of "name" and "type" attributes</a></li> -<li><a class="reference internal" href="#extension-types" id="id44">9.1.3 Extension types</a></li> -<li><a class="reference internal" href="#elements-containing-mixed-content" id="id45">9.1.4 Elements containing mixed content</a></li> +<li><a class="reference internal" href="#the-xml-schema-input-to-generateds" id="id42">9 The XML schema input to generateDS</a><ul class="auto-toc"> +<li><a class="reference internal" href="#additional-constructions" id="id43">9.1 Additional constructions</a><ul class="auto-toc"> +<li><a class="reference internal" href="#complextype-at-top-level" id="id44">9.1.1 <complexType> at top-level</a></li> +<li><a class="reference internal" href="#use-of-ref-instead-of-name-and-type-attributes" id="id45">9.1.2 Use of "ref" instead of "name" and "type" attributes</a></li> +<li><a class="reference internal" href="#extension-types" id="id46">9.1.3 Extension types</a></li> +<li><a class="reference internal" href="#elements-containing-mixed-content" id="id47">9.1.4 Elements containing mixed content</a></li> </ul> </li> </ul> </li> -<li><a class="reference internal" href="#id2" id="id46">10 XMLBehaviors</a><ul class="auto-toc"> -<li><a class="reference internal" href="#the-xmlbehaviors-input-file" id="id47">10.1 The XMLBehaviors input file</a></li> -<li><a class="reference internal" href="#implementing-other-sources-for-implementation-bodies" id="id48">10.2 Implementing other sources for implementation bodies</a></li> +<li><a class="reference internal" href="#id2" id="id48">10 XMLBehaviors</a><ul class="auto-toc"> +<li><a class="reference internal" href="#the-xmlbehaviors-input-file" id="id49">10.1 The XMLBehaviors input file</a></li> +<li><a class="reference internal" href="#implementing-other-sources-for-implementation-bodies" id="id50">10.2 Implementing other sources for implementation bodies</a></li> </ul> </li> -<li><a class="reference internal" href="#additional-features" id="id49">11 Additional features</a><ul class="auto-toc"> -<li><a class="reference internal" href="#xsd-list-element-support" id="id50">11.1 xsd:list element support</a></li> -<li><a class="reference internal" href="#xsd-enumeration-support" id="id51">11.2 xsd:enumeration support</a></li> -<li><a class="reference internal" href="#xsd-union-support" id="id52">11.3 xsd:union support</a></li> -<li><a class="reference internal" href="#extended-xsd-choice-support" id="id53">11.4 Extended xsd:choice support</a></li> -<li><a class="reference internal" href="#arity-minoccurs-maxoccurs-etc" id="id54">11.5 Arity, minOccurs, maxOccurs, etc</a></li> -<li><a class="reference internal" href="#more-thorough-content-type-and-base-type-resolution" id="id55">11.6 More thorough content type and base type resolution</a></li> -<li><a class="reference internal" href="#making-top-level-simpletypes-available-from-xschemahandler" id="id56">11.7 Making top level simpleTypes available from XschemaHandler</a></li> -<li><a class="reference internal" href="#namespaces-inserting-namespace-definition-in-exported-documents" id="id57">11.8 Namespaces -- inserting namespace definition in exported documents</a></li> -<li><a class="reference internal" href="#support-for-xs-any" id="id58">11.9 Support for xs:any</a></li> -<li><a class="reference internal" href="#generating-lxml-element-tree" id="id59">11.10 Generating Lxml Element tree</a><ul class="auto-toc"> -<li><a class="reference internal" href="#mapping-generateds-objects-to-lxml-elements-and-back" id="id60">11.10.1 Mapping generateDS objects to Lxml Elements and back</a></li> +<li><a class="reference internal" href="#additional-features" id="id51">11 Additional features</a><ul class="auto-toc"> +<li><a class="reference internal" href="#xsd-list-element-support" id="id52">11.1 xsd:list element support</a></li> +<li><a class="reference internal" href="#xsd-enumeration-support" id="id53">11.2 xsd:enumeration support</a></li> +<li><a class="reference internal" href="#xsd-union-support" id="id54">11.3 xsd:union support</a></li> +<li><a class="reference internal" href="#extended-xsd-choice-support" id="id55">11.4 Extended xsd:choice support</a></li> +<li><a class="reference internal" href="#arity-minoccurs-maxoccurs-etc" id="id56">11.5 Arity, minOccurs, maxOccurs, etc</a></li> +<li><a class="reference internal" href="#more-thorough-content-type-and-base-type-resolution" id="id57">11.6 More thorough content type and base type resolution</a></li> +<li><a class="reference internal" href="#making-top-level-simpletypes-available-from-xschemahandler" id="id58">11.7 Making top level simpleTypes available from XschemaHandler</a></li> +<li><a class="reference internal" href="#namespaces-inserting-namespace-definition-in-exported-documents" id="id59">11.8 Namespaces -- inserting namespace definition in exported documents</a></li> +<li><a class="reference internal" href="#support-for-xs-any" id="id60">11.9 Support for xs:any</a></li> +<li><a class="reference internal" href="#generating-lxml-element-tree" id="id61">11.10 Generating Lxml Element tree</a><ul class="auto-toc"> +<li><a class="reference internal" href="#mapping-generateds-objects-to-lxml-elements-and-back" id="id62">11.10.1 Mapping generateDS objects to Lxml Elements and back</a></li> </ul> </li> -<li><a class="reference internal" href="#specifying-names-for-anonymous-nested-type-definitions" id="id61">11.11 Specifying names for anonymous nested type definitions</a></li> +<li><a class="reference internal" href="#specifying-names-for-anonymous-nested-type-definitions" id="id63">11.11 Specifying names for anonymous nested type definitions</a></li> </ul> </li> -<li><a class="reference internal" href="#how-to-use-the-generated-source-code" id="id62">12 How to use the generated source code</a><ul class="auto-toc"> -<li><a class="reference internal" href="#the-parsing-functions" id="id63">12.1 The parsing functions</a></li> -<li><a class="reference internal" href="#recognizing-the-top-level-element" id="id64">12.2 Recognizing the top level element</a></li> -<li><a class="reference internal" href="#the-export-methods" id="id65">12.3 The export methods</a><ul class="auto-toc"> -<li><a class="reference internal" href="#method-export" id="id66">12.3.1 Method export</a></li> -<li><a class="reference internal" href="#method-exportliteral" id="id67">12.3.2 Method <tt class="docutils literal">exportLiteral</tt></a><ul class="auto-toc"> -<li><a class="reference internal" href="#what-it-does" id="id68">12.3.2.1 What It Does</a></li> -<li><a class="reference internal" href="#why-you-might-care" id="id69">12.3.2.2 Why You Might Care</a></li> -<li><a class="reference internal" href="#how-to-use-it" id="id70">12.3.2.3 How to use it</a></li> +<li><a class="reference internal" href="#how-to-use-the-generated-source-code" id="id64">12 How to use the generated source code</a><ul class="auto-toc"> +<li><a class="reference internal" href="#the-parsing-functions" id="id65">12.1 The parsing functions</a></li> +<li><a class="reference internal" href="#recognizing-the-top-level-element" id="id66">12.2 Recognizing the top level element</a></li> +<li><a class="reference internal" href="#the-export-methods" id="id67">12.3 The export methods</a><ul class="auto-toc"> +<li><a class="reference internal" href="#method-export" id="id68">12.3.1 Method export</a></li> +<li><a class="reference internal" href="#method-exportliteral" id="id69">12.3.2 Method <tt class="docutils literal">exportLiteral</tt></a><ul class="auto-toc"> +<li><a class="reference internal" href="#what-it-does" id="id70">12.3.2.1 What It Does</a></li> +<li><a class="reference internal" href="#why-you-might-care" id="id71">12.3.2.2 Why You Might Care</a></li> +<li><a class="reference internal" href="#how-to-use-it" id="id72">12.3.2.3 How to use it</a></li> </ul> </li> -<li><a class="reference internal" href="#exporting-compact-xml-documents" id="id71">12.3.3 Exporting compact XML documents</a></li> +<li><a class="reference internal" href="#exporting-compact-xml-documents" id="id73">12.3.3 Exporting compact XML documents</a></li> </ul> </li> -<li><a class="reference internal" href="#building-instances" id="id72">12.4 Building instances</a></li> -<li><a class="reference internal" href="#using-the-subclass-module" id="id73">12.5 Using the subclass module</a></li> -<li><a class="reference internal" href="#elements-with-attributes-but-no-nested-children" id="id74">12.6 Elements with attributes but no nested children</a></li> -<li><a class="reference internal" href="#id4" id="id75">12.7 Mixed content</a></li> -<li><a class="reference internal" href="#id6" id="id76">12.8 anyAttribute</a></li> -<li><a class="reference internal" href="#user-methods" id="id77">12.9 User Methods</a></li> -<li><a class="reference internal" href="#overridable-methods" id="id78">12.10 Overridable methods</a></li> -<li><a class="reference internal" href="#the-element-name-to-class-name-dictionary" id="id79">12.11 The element name to class name dictionary</a></li> +<li><a class="reference internal" href="#building-instances" id="id74">12.4 Building instances</a></li> +<li><a class="reference internal" href="#using-the-subclass-module" id="id75">12.5 Using the subclass module</a></li> +<li><a class="reference internal" href="#elements-with-attributes-but-no-nested-children" id="id76">12.6 Elements with attributes but no nested children</a></li> +<li><a class="reference internal" href="#id4" id="id77">12.7 Mixed content</a></li> +<li><a class="reference internal" href="#id6" id="id78">12.8 anyAttribute</a></li> +<li><a class="reference internal" href="#user-methods" id="id79">12.9 User Methods</a></li> +<li><a class="reference internal" href="#overridable-methods" id="id80">12.10 Overridable methods</a></li> +<li><a class="reference internal" href="#the-element-name-to-class-name-dictionary" id="id81">12.11 The element name to class name dictionary</a></li> </ul> </li> -<li><a class="reference internal" href="#one-per-generating-separate-files-from-imported-included-schemas" id="id80">13 "One Per" -- generating separate files from imported/included schemas</a></li> -<li><a class="reference internal" href="#how-to-modify-the-generated-code" id="id81">14 How to modify the generated code</a><ul class="auto-toc"> -<li><a class="reference internal" href="#adding-features-to-class-definitions" id="id82">14.1 Adding features to class definitions</a></li> +<li><a class="reference internal" href="#one-per-generating-separate-files-from-imported-included-schemas" id="id82">13 "One Per" -- generating separate files from imported/included schemas</a></li> +<li><a class="reference internal" href="#how-to-modify-the-generated-code" id="id83">14 How to modify the generated code</a><ul class="auto-toc"> +<li><a class="reference internal" href="#adding-features-to-class-definitions" id="id84">14.1 Adding features to class definitions</a></li> </ul> </li> -<li><a class="reference internal" href="#examples-and-demonstrations" id="id83">15 Examples and demonstrations</a><ul class="auto-toc"> -<li><a class="reference internal" href="#django-generating-models-and-forms" id="id84">15.1 Django -- Generating Models and Forms</a><ul class="auto-toc"> -<li><a class="reference internal" href="#how-to-generate-django-models-and-forms" id="id85">15.1.1 How to generate Django models and forms</a></li> -<li><a class="reference internal" href="#how-it-works" id="id86">15.1.2 How it works</a></li> +<li><a class="reference internal" href="#examples-and-demonstrations" id="id85">15 Examples and demonstrations</a><ul class="auto-toc"> +<li><a class="reference internal" href="#django-generating-models-and-forms" id="id86">15.1 Django -- Generating Models and Forms</a><ul class="auto-toc"> +<li><a class="reference internal" href="#how-to-generate-django-models-and-forms" id="id87">15.1.1 How to generate Django models and forms</a></li> +<li><a class="reference internal" href="#how-it-works" id="id88">15.1.2 How it works</a></li> </ul> </li> </ul> </li> -<li><a class="reference internal" href="#sample-code-and-extensions" id="id87">16 Sample code and extensions</a><ul class="auto-toc"> -<li><a class="reference internal" href="#capturing-xs-date-elements-as-dates" id="id88">16.1 Capturing xs:date elements as dates</a></li> +<li><a class="reference internal" href="#sample-code-and-extensions" id="id89">16 Sample code and extensions</a><ul class="auto-toc"> +<li><a class="reference internal" href="#capturing-xs-date-elements-as-dates" id="id90">16.1 Capturing xs:date elements as dates</a></li> </ul> </li> -<li><a class="reference internal" href="#limitations-of-generateds" id="id89">17 Limitations of generateDS</a><ul class="auto-toc"> -<li><a class="reference internal" href="#xml-schema-limitations" id="id90">17.1 XML Schema limitations</a></li> -<li><a class="reference internal" href="#large-documents" id="id91">17.2 Large documents</a></li> +<li><a class="reference internal" href="#limitations-of-generateds" id="id91">17 Limitations of generateDS</a><ul class="auto-toc"> +<li><a class="reference internal" href="#xml-schema-limitations" id="id92">17.1 XML Schema limitations</a></li> +<li><a class="reference internal" href="#large-documents" id="id93">17.2 Large documents</a></li> </ul> </li> -<li><a class="reference internal" href="#includes-the-xml-schema-include-element" id="id92">18 Includes -- The XML schema include element</a></li> -<li><a class="reference internal" href="#acknowledgments" id="id93">19 Acknowledgments</a></li> -<li><a class="reference internal" href="#see-also" id="id94">20 See also</a></li> +<li><a class="reference internal" href="#includes-the-xml-schema-include-element" id="id94">18 Includes -- The XML schema include element</a></li> +<li><a class="reference internal" href="#acknowledgments" id="id95">19 Acknowledgments</a></li> +<li><a class="reference internal" href="#see-also" id="id96">20 See also</a></li> </ul> </div> <div class="section" id="introduction"> @@ -616,11 +618,12 @@ Options: Example: "write etree" Default: "write" --preserve-cdata-tags Preserve CDATA tags. Default: False - --cleanup-name-dict=<replacement-map> - Specifies replacement pairs when cleaning up - names. - Example: "{':': 'colon', '-': 'dash', '.': 'dot'}" - Default: "{':': '_', '-': '_', '.': '_'}" + --cleanup-name-list=<replacement-map> + Specifies list of 2-tuples used for cleaning + names. First element is a regular expression + search pattern and second is a replacement. + Example: "[('[-:.]', '_'), ('^__', 'Special')]" + Default: "[('[-:.]', '_')]" -q, --no-questions Do not ask questions, for example, force overwrite. --session=mysession.session @@ -644,6 +647,9 @@ creates (with force over-write) sample_lib.py from sample_api.xsd. creates sample_lib.py superclass and sample_app1.py subclass modules; also generates member specifications in each class (in a dictionary). </pre> +</div> +<div class="section" id="command-line-options"> +<h2><a class="toc-backref" href="#id17">5.2 Command line options</a></h2> <p>The following command line options are recognized by <tt class="docutils literal">generateDS.py</tt>:</p> <dl class="docutils"> <dt>o <filename></dt> @@ -859,11 +865,25 @@ default is: <tt class="docutils literal"><span class="pre">--export="write< are dropped while parsing an XML instance document. If this option is included, the generated code will preserve those tags and will write them out during export. The default is False.</dd> -<dt>cleanup-name-dict=<replacement-map></dt> -<dd>Specifies replacement pairs to be used when cleaning up names. -Must be a string representation of a Python dictionary. -Example: <tt class="docutils literal"><span class="pre">{':':</span> 'colon', <span class="pre">'-':</span> 'dash', <span class="pre">'.':</span> 'dot'}</tt>. -Default when omitted: <tt class="docutils literal"><span class="pre">{':':</span> '_', <span class="pre">'-':</span> '_', <span class="pre">'.':</span> '_'}</tt>.</dd> +<dt>cleanup-name-list=<replacement-map></dt> +<dd><p class="first">Specifies replacement pairs to be used when cleaning up names. +Must be a string representation of a Python list of 2-tuples. +The values of each pair (2-tuple) must be strings. The first +item of each pair is a pattern and must be a valid Python +regular expression (see +<a class="reference external" href="https://docs.python.org/2/library/re.html#module-re">https://docs.python.org/2/library/re.html#module-re</a>) The second +item of each pair is a string that will replace anything matched +by the pattern. Also see <a class="reference internal" href="#cleaning-up-names-with-special-characters-etc">Cleaning up names with special characters etc.</a></p> +<p>The intension is to enable us to replace +special characters in names that would cause the generation of +invalid Python names, for example the names of generated +classes. However, since a string replacement is +performed, you can replace any single character or sequence of +characters by any other single character or sequence of +characters. Example: +<tt class="docutils literal"><span class="pre">[(':',</span> <span class="pre">'colon'),</span> <span class="pre">('-',</span> <span class="pre">'dash'),</span> <span class="pre">('.',</span> <span class="pre">'dot')]</span></tt>.</p> +<p class="last">The default when omitted is <tt class="docutils literal"><span class="pre">[('[-:.]',</span> <span class="pre">'_')]</span></tt>.</p> +</dd> <dt>q, no-questions</dt> <dd>Do not ask questions. For example, if the "-f" command line option is omitted and the ouput file exists, then generateDS.py @@ -898,10 +918,10 @@ $ generateDS.py --fix-type-names="type1;type2:type2Repl" exit.</dd> </dl> </div> -<div class="section" id="name-conflicts"> -<h2><a class="toc-backref" href="#id17">5.2 Name conflicts</a></h2> +<div class="section" id="name-conflicts-etc"> +<h2><a class="toc-backref" href="#id18">5.3 Name conflicts etc.</a></h2> <div class="section" id="conflicts-with-python-keywords"> -<h3><a class="toc-backref" href="#id18">5.2.1 Conflicts with Python keywords</a></h3> +<h3><a class="toc-backref" href="#id19">5.3.1 Conflicts with Python keywords</a></h3> <p>In some cases the element and attribute names in an XML document will conflict with Python keywords. There are two solutions to fixing and avoiding name conflicts:</p> @@ -941,7 +961,7 @@ itself.</p> </ul> </div> <div class="section" id="conflicts-between-child-elements-and-attributes"> -<h3><a class="toc-backref" href="#id19">5.2.2 Conflicts between child elements and attributes</a></h3> +<h3><a class="toc-backref" href="#id20">5.3.2 Conflicts between child elements and attributes</a></h3> <p>In some cases the name of a child element and the name of an attribute will be the same. (I believe, but am not sure, that this is allowed by XML Schema.) Since generateDS.py treats both @@ -950,10 +970,48 @@ this is a name conflict. Therefore, where such conflicts exist, generateDS.py modifies the name of the attribute by adding "_attr" to its name.</p> </div> +<div class="section" id="cleaning-up-names-with-special-characters-etc"> +<h3><a class="toc-backref" href="#id21">5.3.3 Cleaning up names with special characters etc.</a></h3> +<p><tt class="docutils literal">generateDS.py</tt> attempts to clean up names that contain special +characters. For example, a complexType whose name contains a dash +would generate a Python class with an invalid name. But, you can +use this facility to make other changes to names as well.</p> +<p>The command line option <tt class="docutils literal"><span class="pre">--cleanup-name-list</span></tt> specifies +replacement pairs to be used when cleaning up (and modifying) names. +The value of this option must be a string representation of a Python +list of 2-tuples. The values of each pair (2-tuple) must be +strings. The first item of each pair is a pattern and must be a +valid Python regular expression (see +<a class="reference external" href="https://docs.python.org/2/library/re.html#module-re">https://docs.python.org/2/library/re.html#module-re</a>) The second item +of each pair is a string that will replace anything matched by the +pattern. The intension is to enable us to replace special +characters in names that would cause the generation of invalid +Python names, for example the names of generated classes. However, +since a string replacement is performed, you can replace any single +character or sequence of characters by any other single character or +sequence of characters.</p> +<p>For example, the following option, in addition to performing the +default replacements of "-", ":", and "." by an underscore, would +also replace the string "Type" when it occurs at the end of a name, +by "Class":</p> +<pre class="literal-block"> +--cleanup-name-list="[('[-:.]', '_'), ('Type$', 'Class')]" +</pre> +<p>This would cause the name "big-data-Type" to become "big_data_Class".</p> +<p>The default when this option is omitted is <tt class="docutils literal"><span class="pre">[('[-:.]',</span> <span class="pre">'_')]</span></tt>.</p> +<p>The order of replacements performed is the same as the order of the +tuples in the list. So, replacements performed by pattern +replacement pairs (2-tuples) later in the list (to the right) will +be performed after those earlier (to the left), and may overwrite +earlier replacements.</p> +<p>See the notes on the command line option <tt class="docutils literal"><span class="pre">--cleanup-name-list</span></tt> for +more on this. Or, run <tt class="docutils literal">$ generateDS.py <span class="pre">--help</span></tt>.</p> +</div> </div> </div> <div class="section" id="the-graphical-user-interface-how-to-use-it"> -<h1><a class="toc-backref" href="#id20">6 The graphical user interface -- How to use it</a></h1> +<h1><a class="toc-backref" href="#id22">6 The graphical user interface -- How to use it</a></h1> +<p><strong>Note:</strong> The graphical user interface is no longer supported.</p> <p>Here are a few notes on how to use the GUI front-end.</p> <ul> <li><p class="first"><tt class="docutils literal">generateds_gui.py</tt> is installed when you do the standard @@ -1022,9 +1080,9 @@ files.</p> </ul> </div> <div class="section" id="common-problems"> -<h1><a class="toc-backref" href="#id21">7 Common problems</a></h1> +<h1><a class="toc-backref" href="#id23">7 Common problems</a></h1> <div class="section" id="namespace-prefix-mis-match"> -<h2><a class="toc-backref" href="#id22">7.1 Namespace prefix mis-match</a></h2> +<h2><a class="toc-backref" href="#id24">7.1 Namespace prefix mis-match</a></h2> <p><tt class="docutils literal">generateDS.py</tt> is not very intelligent about detecting what prefix is used in the schema file for the XML Schema namespace. When this problem occurs, you may see the following when running @@ -1043,7 +1101,7 @@ generateDS.py -a "xsd:" --super=mylib -o mylib.py -s myapp.py somesche </div> </div> <div class="section" id="supported-features-of-xml-schema"> -<h1><a class="toc-backref" href="#id23">8 Supported features of XML Schema</a></h1> +<h1><a class="toc-backref" href="#id25">8 Supported features of XML Schema</a></h1> <p>The following constructs, among others, in XML Schema are supported:</p> <ul class="simple"> @@ -1058,14 +1116,14 @@ Schema document.</li> and structures. Also see the section on <a class="reference internal" href="#the-xml-schema-input-to-generateds">The XML Schema Input to generateDS</a>.</p> <div class="section" id="attributes-no-nested-children"> -<h2><a class="toc-backref" href="#id24">8.1 Attributes + no nested children</a></h2> +<h2><a class="toc-backref" href="#id26">8.1 Attributes + no nested children</a></h2> <p>Element definitions that contain attributes but <em>no</em> nested child elements provide access to their data content through getter and setter methods <tt class="docutils literal">getValueOf_</tt> and <tt class="docutils literal">setValueOf_</tt> and member variable <tt class="docutils literal">valueOf_</tt>.</p> </div> <div class="section" id="mixed-content"> -<h2><a class="toc-backref" href="#id25">8.2 Mixed content</a></h2> +<h2><a class="toc-backref" href="#id27">8.2 Mixed content</a></h2> <p>Elements that are defined to contain both text and nested child elements have "mixed content". <tt class="docutils literal">generateDS.py</tt> provides access to mixed content, but the generated data structures (classes) are @@ -1078,7 +1136,7 @@ elements, character data is captured in a member variable <tt class="docutils literal">getValueOf_</tt> and <tt class="docutils literal">setValueOf_</tt>.</p> </div> <div class="section" id="anyattribute"> -<h2><a class="toc-backref" href="#id26">8.3 anyAttribute</a></h2> +<h2><a class="toc-backref" href="#id28">8.3 anyAttribute</a></h2> <p><tt class="docutils literal">generateDS.py</tt> supports <tt class="docutils literal">anyAttribute</tt>. For example, if an element is defined as follows:</p> <pre class="literal-block"> @@ -1098,7 +1156,7 @@ as well as code for parsing and export. <tt class="docutils literal">generateDS. <tt class="docutils literal">processContents</tt>. See section <a class="reference internal" href="#id5">anyAttribute</a> for more details.</p> </div> <div class="section" id="element-extensions"> -<h2><a class="toc-backref" href="#id27">8.4 Element extensions</a></h2> +<h2><a class="toc-backref" href="#id29">8.4 Element extensions</a></h2> <p><tt class="docutils literal">generateDS.py</tt> now generates subclasses for extensions, that is when an element definition contains something like this:</p> <pre class="literal-block"> @@ -1117,7 +1175,7 @@ its superclass has been generated. Therefore, the order in which classes are generated may be different from what you expect.</p> </div> <div class="section" id="attribute-groups"> -<h2><a class="toc-backref" href="#id28">8.5 Attribute groups</a></h2> +<h2><a class="toc-backref" href="#id30">8.5 Attribute groups</a></h2> <p><tt class="docutils literal">generateDS.py</tt> now handles definition and use of attribute groups. For example: the use of something like the following:</p> <pre class="literal-block"> @@ -1141,7 +1199,7 @@ groups. For example: the use of something like the following:</p> groups themselves can contain references to other attribute groups.</p> </div> <div class="section" id="substitution-groups"> -<h2><a class="toc-backref" href="#id29">8.6 Substitution groups</a></h2> +<h2><a class="toc-backref" href="#id31">8.6 Substitution groups</a></h2> <p><tt class="docutils literal">generateDS.py</tt> now handles a limited range of substitution groups, but, there is an important <strong>limitation</strong>, in particular <tt class="docutils literal">generateDS.py</tt> handles substitution groups that involve complex @@ -1152,7 +1210,7 @@ does not provide the needed information to handle substitution groups.</p> </div> <div class="section" id="primitive-types"> -<h2><a class="toc-backref" href="#id30">8.7 Primitive types</a></h2> +<h2><a class="toc-backref" href="#id32">8.7 Primitive types</a></h2> <p><tt class="docutils literal">generateDS.py</tt> supports some, but not all, simple types defined in "XML Schema Part 0: Primer Second Edition" ( <a class="reference external" href="http://www.w3.org/TR/xmlschema-0/">http://www.w3.org/TR/xmlschema-0/</a>. See section "Simple Types" and @@ -1179,7 +1237,7 @@ validation.</li> </ul> </div> <div class="section" id="simpletype"> -<h2><a class="toc-backref" href="#id31">8.8 simpleType</a></h2> +<h2><a class="toc-backref" href="#id33">8.8 simpleType</a></h2> <p><tt class="docutils literal">generateDS.py</tt> generates minimal support for members defined as <tt class="docutils literal">simpleType</tt>. However, the code generated by <tt class="docutils literal">generateDS.py</tt> does <strong>not</strong> enforce restrictions. For notes on how to enforce @@ -1218,7 +1276,7 @@ generate valid code:</p> </pre> </div> <div class="section" id="list-values-optional-values-maxoccurs-etc"> -<h2><a class="toc-backref" href="#id32">8.9 List values, optional values, maxOccurs, etc.</a></h2> +<h2><a class="toc-backref" href="#id34">8.9 List values, optional values, maxOccurs, etc.</a></h2> <p>For elements defined with <tt class="docutils literal"><span class="pre">maxOccurs="unbounded"</span></tt>, <tt class="docutils literal">generateDS.py</tt> generates code that processes a list of elements.</p> <p>For elements defined with <tt class="docutils literal"><span class="pre">minOccurs="0"</span></tt> and <tt class="docutils literal"><span class="pre">maxOccurs="1"</span></tt>, @@ -1226,9 +1284,9 @@ generate valid code:</p> that element has a (non-None) value.</p> </div> <div class="section" id="simpletype-and-validators"> -<h2><a class="toc-backref" href="#id33">8.10 simpleType and validators</a></h2> +<h2><a class="toc-backref" href="#id35">8.10 simpleType and validators</a></h2> <div class="section" id="generating-validator-bodies-from-xml-schema"> -<h3><a class="toc-backref" href="#id34">8.10.1 Generating validator bodies from XML schema</a></h3> +<h3><a class="toc-backref" href="#id36">8.10.1 Generating validator bodies from XML schema</a></h3> <p>If you do <em>not</em> use the <tt class="docutils literal"><span class="pre">--use-old-simpletype-validators</span></tt> command line option, then <tt class="docutils literal">generateDS.py</tt> will generate validation code directly from the restrictions specified inside the <tt class="docutils literal">simpleType</tt> @@ -1269,7 +1327,7 @@ float for floats, etc.</li> </ul> </div> <div class="section" id="user-written-validator-bodies"> -<h3><a class="toc-backref" href="#id35">8.10.2 User written validator bodies</a></h3> +<h3><a class="toc-backref" href="#id37">8.10.2 User written validator bodies</a></h3> <p>This is the older, more manual method. In order to generate code that uses this method, use command line option <tt class="docutils literal"><span class="pre">--use-old-simpletype-validators</span></tt>.</p> @@ -1386,7 +1444,7 @@ So, for example, the following works:</p> </ul> </div> <div class="section" id="turning-off-validation-of-simpletype-data"> -<h3><a class="toc-backref" href="#id36">8.10.3 Turning off validation of <tt class="docutils literal">simpleType</tt> data</a></h3> +<h3><a class="toc-backref" href="#id38">8.10.3 Turning off validation of <tt class="docutils literal">simpleType</tt> data</a></h3> <p>If you do not want validation performed on <tt class="docutils literal">simpleType</tt> data, you have these options:</p> <ol class="arabic simple"> @@ -1403,7 +1461,7 @@ and off.</li> </ol> </div> <div class="section" id="additional-notes-on-simpletype-validation"> -<h3><a class="toc-backref" href="#id37">8.10.4 Additional notes on <tt class="docutils literal">simpleType</tt> validation</a></h3> +<h3><a class="toc-backref" href="#id39">8.10.4 Additional notes on <tt class="docutils literal">simpleType</tt> validation</a></h3> <p>Don't forget that <tt class="docutils literal">xmllint</tt> can also be used to perform validation against the XML scheme. This validation includes checking against <tt class="docutils literal">simpleType</tt> restrictions. See @@ -1411,7 +1469,7 @@ checking against <tt class="docutils literal">simpleType</tt> restrictions. See </div> </div> <div class="section" id="include-file-processing"> -<h2><a class="toc-backref" href="#id38">8.11 Include file processing</a></h2> +<h2><a class="toc-backref" href="#id40">8.11 Include file processing</a></h2> <p>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. This behavior can be turned off by using the "--no-process-includes" @@ -1425,7 +1483,7 @@ via FTP and HTTP internet protocols as well as from the local file system.</p> </div> <div class="section" id="abstract-types"> -<h2><a class="toc-backref" href="#id39">8.12 Abstract types</a></h2> +<h2><a class="toc-backref" href="#id41">8.12 Abstract types</a></h2> <p><tt class="docutils literal">generateDS.py</tt> has support for abstract types. For more on this, see: <a class="reference external" href="http://www.w3.org/TR/xmlschema-0/#abstract">XML Schema Part 0: Primer Second Edition: Abstract Elements and Types -- @@ -1433,7 +1491,7 @@ http://www.w3.org/TR/xmlschema-0/#abstract</a>.</p> </div> </div> <div class="section" id="the-xml-schema-input-to-generateds"> -<h1><a class="toc-backref" href="#id40">9 The XML schema input to generateDS</a></h1> +<h1><a class="toc-backref" href="#id42">9 The XML schema input to generateDS</a></h1> <p><strong>Note:</strong> Quite a bit of work has been done on <tt class="docutils literal">generateDS.py</tt> since this section was written. So, it accepts and processes more of features in XML Schema than earlier. The best advice is to @@ -1553,11 +1611,11 @@ order to define a member data item that takes an instance or list of instances of a Python class.</li> </ul> <div class="section" id="additional-constructions"> -<h2><a class="toc-backref" href="#id41">9.1 Additional constructions</a></h2> +<h2><a class="toc-backref" href="#id43">9.1 Additional constructions</a></h2> <p>Here are a few additional constructions that <tt class="docutils literal">generateDS.py</tt> understands.</p> <div class="section" id="complextype-at-top-level"> -<h3><a class="toc-backref" href="#id42">9.1.1 <complexType> at top-level</a></h3> +<h3><a class="toc-backref" href="#id44">9.1.1 <complexType> at top-level</a></h3> <p>You can use the <complexType> element at top level (instead of <element>) to define an element. So, for example, instead of:</p> <pre class="literal-block"> @@ -1581,7 +1639,7 @@ understands.</p> </pre> </div> <div class="section" id="use-of-ref-instead-of-name-and-type-attributes"> -<h3><a class="toc-backref" href="#id43">9.1.2 Use of "ref" instead of "name" and "type" attributes</a></h3> +<h3><a class="toc-backref" href="#id45">9.1.2 Use of "ref" instead of "name" and "type" attributes</a></h3> <p>You can use the "ref" attribute to refer to another element definition, instead of using the "name" and "type" attributes. So, for example, you can use the following:</p> @@ -1606,7 +1664,7 @@ for example, you can use the following:</p> </pre> </div> <div class="section" id="extension-types"> -<h3><a class="toc-backref" href="#id44">9.1.3 Extension types</a></h3> +<h3><a class="toc-backref" href="#id46">9.1.3 Extension types</a></h3> <p><tt class="docutils literal">generateDS.py</tt> generates a subclass for each element that that is defined as the extension of a base element. So, for the following:</p> @@ -1628,7 +1686,7 @@ class BType(AType): </pre> </div> <div class="section" id="elements-containing-mixed-content"> -<h3><a class="toc-backref" href="#id45">9.1.4 Elements containing mixed content</a></h3> +<h3><a class="toc-backref" href="#id47">9.1.4 Elements containing mixed content</a></h3> <p><tt class="docutils literal">generateDS.py</tt> generates special code to handle elements defined as containing mixed content, that is elements defined with attribute <tt class="docutils literal"><span class="pre">mixed="true"</span></tt>. See section <a class="reference internal" href="#id3">Mixed content</a> for more @@ -1637,7 +1695,7 @@ details.</p> </div> </div> <div class="section" id="id2"> -<span id="xmlbehaviors"></span><h1><a class="toc-backref" href="#id46">10 XMLBehaviors</a></h1> +<span id="xmlbehaviors"></span><h1><a class="toc-backref" href="#id48">10 XMLBehaviors</a></h1> <p>With the use of the "-b" command line option, <tt class="docutils literal">generateDS.py</tt> will also accept as input an XML document instance that describes behaviors to be added to subclasses when the subclass file is @@ -1649,7 +1707,7 @@ for the most part, designed by gian paolo ciceri (<a class="reference external" href="mailto:gp.ciceri@suddenthinks.com">gp.ciceri@suddenthinks.com</a>). This work is part of our work on our application development project for Quixote.</p> <div class="section" id="the-xmlbehaviors-input-file"> -<h2><a class="toc-backref" href="#id47">10.1 The XMLBehaviors input file</a></h2> +<h2><a class="toc-backref" href="#id49">10.1 The XMLBehaviors input file</a></h2> <p>This section describes the XMLBehavior XML document that is used as input to <tt class="docutils literal">generateDS.py</tt>. The XMLBehavior XML document is an XML instance document (given as an argument to the "-b" command @@ -1722,7 +1780,7 @@ of the base-impl-url.</li> </ul> </div> <div class="section" id="implementing-other-sources-for-implementation-bodies"> -<h2><a class="toc-backref" href="#id48">10.2 Implementing other sources for implementation bodies</a></h2> +<h2><a class="toc-backref" href="#id50">10.2 Implementing other sources for implementation bodies</a></h2> <p><tt class="docutils literal">generateDS.py</tt> contains a function <tt class="docutils literal">get_impl_body()</tt> that implements the ability to retrieve implementation bodies. The current implementation retrieves implementation bodies from an @@ -1763,11 +1821,11 @@ def get_impl_body(classBehavior, baseImplUrl, implUrl): </div> </div> <div class="section" id="additional-features"> -<h1><a class="toc-backref" href="#id49">11 Additional features</a></h1> +<h1><a class="toc-backref" href="#id51">11 Additional features</a></h1> <p>Here are additional features, contributed by users such as Chris Allan. Many thanks.</p> <div class="section" id="xsd-list-element-support"> -<h2><a class="toc-backref" href="#id50">11.1 xsd:list element support</a></h2> +<h2><a class="toc-backref" href="#id52">11.1 xsd:list element support</a></h2> <p>xsd:list elements can be used with a child xsd:simpleType which confuses the XschemaHandler stack unrolling. xsd:list element support should allow the following XML Schema definition to be @@ -1785,18 +1843,18 @@ supported in <tt class="docutils literal">generateDS.py</tt>:</p> </pre> </div> <div class="section" id="xsd-enumeration-support"> -<h2><a class="toc-backref" href="#id51">11.2 xsd:enumeration support</a></h2> +<h2><a class="toc-backref" href="#id53">11.2 xsd:enumeration support</a></h2> <p>The enumerated values for the parent element are resolved and made available through the instance attribute <tt class="docutils literal">values</tt>.</p> </div> <div class="section" id="xsd-union-support"> -<h2><a class="toc-backref" href="#id52">11.3 xsd:union support</a></h2> +<h2><a class="toc-backref" href="#id54">11.3 xsd:union support</a></h2> <p>In order to properly resolve and query types which are unions in an XML Schema, an element's membership in an xsd:union is available through the instance attribute <tt class="docutils literal">unionOf</tt>.</p> </div> <div class="section" id="extended-xsd-choice-support"> -<h2><a class="toc-backref" href="#id53">11.4 Extended xsd:choice support</a></h2> +<h2><a class="toc-backref" href="#id55">11.4 Extended xsd:choice support</a></h2> <p>When a parent xsd:choice is exists, an element's "maxOccurs" and "minOccurs" values can be inherited from the xsd:choice rather than the element itself. xsd:choice elements have been added to @@ -1816,7 +1874,7 @@ supported in <tt class="docutils literal">generateDS.py</tt>:</p> </pre> </div> <div class="section" id="arity-minoccurs-maxoccurs-etc"> -<h2><a class="toc-backref" href="#id54">11.5 Arity, minOccurs, maxOccurs, etc</a></h2> +<h2><a class="toc-backref" href="#id56">11.5 Arity, minOccurs, maxOccurs, etc</a></h2> <p>Some applications require information about the "minOccurs" and "maxOccurs" attributes in the XML Schema. Some of that information can be obtained by using the --member-specs= (list|dict) command line @@ -1825,7 +1883,7 @@ that it generates in each data representation class. In particular, look at the <tt class="docutils literal">get_container</tt> method (from class <tt class="docutils literal">MemberSpec_</tt>).</p> </div> <div class="section" id="more-thorough-content-type-and-base-type-resolution"> -<h2><a class="toc-backref" href="#id55">11.6 More thorough content type and base type resolution</a></h2> +<h2><a class="toc-backref" href="#id57">11.6 More thorough content type and base type resolution</a></h2> <p>The previous content type and base type resolution is insufficient for some needs. Basically it was unable to handle more complex and shared element and simpleType definitions. This support has @@ -1838,7 +1896,7 @@ achieved is available as comments in the source code of class <tt class="docutils literal">XschemaElement</tt>.</p> </div> <div class="section" id="making-top-level-simpletypes-available-from-xschemahandler"> -<h2><a class="toc-backref" href="#id56">11.7 Making top level simpleTypes available from XschemaHandler</a></h2> +<h2><a class="toc-backref" href="#id58">11.7 Making top level simpleTypes available from XschemaHandler</a></h2> <p>Some developers working to extend the analysis and code generation in <tt class="docutils literal">generateDS.py</tt> may be helped by additional information collected during the parsing of the XML Schema file.</p> @@ -1849,7 +1907,7 @@ available as an instance attribute <tt class="docutils literal">topLevelSimpleTy <tt class="docutils literal">XschemaHandler</tt>.</p> </div> <div class="section" id="namespaces-inserting-namespace-definition-in-exported-documents"> -<h2><a class="toc-backref" href="#id57">11.8 Namespaces -- inserting namespace definition in exported documents</a></h2> +<h2><a class="toc-backref" href="#id59">11.8 Namespaces -- inserting namespace definition in exported documents</a></h2> <p>In some cases, the document produced by a call to an export method will contain elements that have namespace prefixes. For example, the following snippet contains namespace prefix "abc":</p> @@ -1895,7 +1953,7 @@ generateDS.py --namespacedef='xmlns:abc="http://www.abc.com/namespace.xsd&q <tt class="docutils literal">namespacedef_</tt> argument to the call to export.</p> </div> <div class="section" id="support-for-xs-any"> -<h2><a class="toc-backref" href="#id58">11.9 Support for xs:any</a></h2> +<h2><a class="toc-backref" href="#id60">11.9 Support for xs:any</a></h2> <p>There is minimal support for the <tt class="docutils literal">xs:any</tt> wild card declaration. Effectively, an element defined by an <tt class="docutils literal">xs:complexType</tt> containing <tt class="docutils literal">xs:any</tt> can contain any element type as a child element. Because @@ -1922,7 +1980,7 @@ with <tt class="docutils literal">xs:any</tt> should help you understand what is copy, paste, and edit code from there.</p> </div> <div class="section" id="generating-lxml-element-tree"> -<h2><a class="toc-backref" href="#id59">11.10 Generating Lxml Element tree</a></h2> +<h2><a class="toc-backref" href="#id61">11.10 Generating Lxml Element tree</a></h2> <p>Once you have build the tree of objects that are instances of the classes generated by <tt class="docutils literal">generateDS.py</tt>, you can use this to produce a tree of instances of the Lxml Element instances. See @@ -1952,7 +2010,7 @@ def parseEtree(inFileName): return rootObj, rootElement, mapping, reverse_mapping </pre> <div class="section" id="mapping-generateds-objects-to-lxml-elements-and-back"> -<h3><a class="toc-backref" href="#id60">11.10.1 Mapping generateDS objects to Lxml Elements and back</a></h3> +<h3><a class="toc-backref" href="#id62">11.10.1 Mapping generateDS objects to Lxml Elements and back</a></h3> <p>Now suppose that you have produced the tree of instances of the generated classes, and suppose that you have used that to produce a tree of instances of the Element class from Lxml. It may be useful @@ -1966,7 +2024,7 @@ convenience method <tt class="docutils literal">gds_reverse_node_mapping</tt> fr </div> </div> <div class="section" id="specifying-names-for-anonymous-nested-type-definitions"> -<h2><a class="toc-backref" href="#id61">11.11 Specifying names for anonymous nested type definitions</a></h2> +<h2><a class="toc-backref" href="#id63">11.11 Specifying names for anonymous nested type definitions</a></h2> <p><tt class="docutils literal">generateDS.py</tt> automatically assigns names for types (and the classes generated from them), when that type definition (for example, <tt class="docutils literal">xs:complexType</tt>) does not have a name and it is nested @@ -2027,9 +2085,9 @@ schema.</li> </div> </div> <div class="section" id="how-to-use-the-generated-source-code"> -<h1><a class="toc-backref" href="#id62">12 How to use the generated source code</a></h1> +<h1><a class="toc-backref" href="#id64">12 How to use the generated source code</a></h1> <div class="section" id="the-parsing-functions"> -<h2><a class="toc-backref" href="#id63">12.1 The parsing functions</a></h2> +<h2><a class="toc-backref" href="#id65">12.1 The parsing functions</a></h2> <p>The simplest use is to call one of the parsing functions in the generated source file. You may be able to use one of these functions without change, or can modify one to fit your needs. @@ -2055,7 +2113,7 @@ rootObject = people.parse('people.xml') </pre> </div> <div class="section" id="recognizing-the-top-level-element"> -<h2><a class="toc-backref" href="#id64">12.2 Recognizing the top level element</a></h2> +<h2><a class="toc-backref" href="#id66">12.2 Recognizing the top level element</a></h2> <p>It might be that the generated module, when parsing an XML instance document, does not, by default, recognize the top level (root) element in an instance document. This might happen because @@ -2176,14 +2234,14 @@ function can parse and export it.</p> </ol> </div> <div class="section" id="the-export-methods"> -<h2><a class="toc-backref" href="#id65">12.3 The export methods</a></h2> +<h2><a class="toc-backref" href="#id67">12.3 The export methods</a></h2> <p>The generated classes contain methods <tt class="docutils literal">export</tt> and <tt class="docutils literal">exportLiteral</tt> which can be called to export classes to several text formats, in particular to an XML instance document and a Python module containing Python literals. See the generated parse functions for examples showing how to call the export methods.</p> <div class="section" id="method-export"> -<h3><a class="toc-backref" href="#id66">12.3.1 Method export</a></h3> +<h3><a class="toc-backref" href="#id68">12.3.1 Method export</a></h3> <p>The export method in generated classes writes out an XML document that represents the instance that contains it and its child elements. So, for example, if your instance tree was created by @@ -2192,14 +2250,14 @@ one of the parsing functions described above, then calling document, differing only with respect to ignorable white space.</p> </div> <div class="section" id="method-exportliteral"> -<h3><a class="toc-backref" href="#id67">12.3.2 Method <tt class="docutils literal">exportLiteral</tt></a></h3> +<h3><a class="toc-backref" href="#id69">12.3.2 Method <tt class="docutils literal">exportLiteral</tt></a></h3> <p><tt class="docutils literal">generateDS.py</tt> generates Python classes that represent the elements in an XML document, given an Xschema definition of the XML document type. The <tt class="docutils literal">exportLiteral</tt> method will export a Python literal representation of the Python instances of the classes that represent an XML document.</p> <div class="section" id="what-it-does"> -<h4><a class="toc-backref" href="#id68">12.3.2.1 What It Does</a></h4> +<h4><a class="toc-backref" href="#id70">12.3.2.1 What It Does</a></h4> <p>When <tt class="docutils literal">generateDS.py</tt> generates the Python source code for your classes, this new feature also generates an <tt class="docutils literal">exportLiteral</tt> method in each class. If you call this method on the root @@ -2213,7 +2271,7 @@ that you can import to (re-)create instances of the classes that represent your XML document.</p> </div> <div class="section" id="why-you-might-care"> -<h4><a class="toc-backref" href="#id69">12.3.2.2 Why You Might Care</a></h4> +<h4><a class="toc-backref" href="#id71">12.3.2.2 Why You Might Care</a></h4> <p><tt class="docutils literal">generateDS.py</tt> was designed and built with the assumption that we are <em>not</em> interested in marking up text content at all. What we really want is a way to represent structured and nested date in @@ -2256,13 +2314,13 @@ import.</li> </ul> </div> <div class="section" id="how-to-use-it"> -<h4><a class="toc-backref" href="#id70">12.3.2.3 How to use it</a></h4> +<h4><a class="toc-backref" href="#id72">12.3.2.3 How to use it</a></h4> <p>See the generated function <tt class="docutils literal">parseLiteral</tt> for an example of how to use <tt class="docutils literal">exportLiteral</tt>.</p> </div> </div> <div class="section" id="exporting-compact-xml-documents"> -<h3><a class="toc-backref" href="#id71">12.3.3 Exporting compact XML documents</a></h3> +<h3><a class="toc-backref" href="#id73">12.3.3 Exporting compact XML documents</a></h3> <p>You can also export "compact" XML documents. A compact document is one that is exported <em>without</em> the ignorable whitespace that is used to produce pretty printed documents. In contrast, a pretty printed @@ -2276,7 +2334,7 @@ default.</p> </div> </div> <div class="section" id="building-instances"> -<h2><a class="toc-backref" href="#id72">12.4 Building instances</a></h2> +<h2><a class="toc-backref" href="#id74">12.4 Building instances</a></h2> <p>If you have an instance of a minidom node that represents an element in an XML document, you can also use the 'build' member function to populate an instance of the corresponding class. Here @@ -2296,7 +2354,7 @@ for child in rootNode.childNodes: </pre> </div> <div class="section" id="using-the-subclass-module"> -<h2><a class="toc-backref" href="#id73">12.5 Using the subclass module</a></h2> +<h2><a class="toc-backref" href="#id75">12.5 Using the subclass module</a></h2> <p>If you choose to use the generated subclass module, and I encourage you to do so, you may need to edit and modify that file. Here are some of the things that you must do (look for @@ -2323,14 +2381,14 @@ accessed through getter and setter methods in the class in which they are referenced.</p> </div> <div class="section" id="elements-with-attributes-but-no-nested-children"> -<h2><a class="toc-backref" href="#id74">12.6 Elements with attributes but no nested children</a></h2> +<h2><a class="toc-backref" href="#id76">12.6 Elements with attributes but no nested children</a></h2> <p>Element definitions that contain attributes but <em>no</em> nested child elements provide access to their data content through getter and setter methods <tt class="docutils literal">getValueOf_</tt> and <tt class="docutils literal">setValueOf_</tt> and member variable <tt class="docutils literal">valueOf_</tt>.</p> </div> <div class="section" id="id4"> -<span id="id3"></span><h2><a class="toc-backref" href="#id75">12.7 Mixed content</a></h2> +<span id="id3"></span><h2><a class="toc-backref" href="#id77">12.7 Mixed content</a></h2> <p>The goal of <tt class="docutils literal">generateDS.py</tt> is to support data structures represented in XML as opposed to text mark-up. However, it does provides some support for mixed content. But, for mixed content, @@ -2398,7 +2456,7 @@ elements, character data is captured in a member variable <tt class="docutils literal">getValueOf_</tt> and <tt class="docutils literal">setValueOf_</tt>.</p> </div> <div class="section" id="id6"> -<span id="id5"></span><h2><a class="toc-backref" href="#id76">12.8 anyAttribute</a></h2> +<span id="id5"></span><h2><a class="toc-backref" href="#id78">12.8 anyAttribute</a></h2> <p>For elements that specify <tt class="docutils literal">anyAttributes</tt>, <tt class="docutils literal">generateDS.py</tt> produces a class containing the following:</p> <ul class="simple"> @@ -2419,7 +2477,7 @@ are <em>not</em> stored in the dictionary <tt class="docutils literal">anyAttrib <tt class="docutils literal">anyAttribute</tt> element in the XML Schema</p> </div> <div class="section" id="user-methods"> -<h2><a class="toc-backref" href="#id77">12.9 User Methods</a></h2> +<h2><a class="toc-backref" href="#id79">12.9 User Methods</a></h2> <p><tt class="docutils literal">generateDS.py</tt> provides a mechanism that enables you to attach user defined methods to specific generated classes. In order to do so, create a Python module containing specifications of those @@ -2541,7 +2599,7 @@ source code and the class_name pattern in each specification.</li> </ol> </div> <div class="section" id="overridable-methods"> -<h2><a class="toc-backref" href="#id78">12.10 Overridable methods</a></h2> +<h2><a class="toc-backref" href="#id80">12.10 Overridable methods</a></h2> <p><tt class="docutils literal">generateDS.py</tt> generates calls to several methods that each have a default implementation in a superclass. The default superclass with default implementations is included in the generated code. @@ -2660,7 +2718,7 @@ option for <tt class="docutils literal">generateDS.py</tt>.</p> </ul> </div> <div class="section" id="the-element-name-to-class-name-dictionary"> -<h2><a class="toc-backref" href="#id79">12.11 The element name to class name dictionary</a></h2> +<h2><a class="toc-backref" href="#id81">12.11 The element name to class name dictionary</a></h2> <p><tt class="docutils literal">generateDS.py</tt> automatically generates a dictionary that maps element/complexType names to the names of the class generated for that complexType definition. This dictionary is named @@ -2669,7 +2727,7 @@ with the "-o" option.</p> </div> </div> <div class="section" id="one-per-generating-separate-files-from-imported-included-schemas"> -<h1><a class="toc-backref" href="#id80">13 "One Per" -- generating separate files from imported/included schemas</a></h1> +<h1><a class="toc-backref" href="#id82">13 "One Per" -- generating separate files from imported/included schemas</a></h1> <p>The <tt class="docutils literal"><span class="pre">--one-file-per-xsd</span></tt> command line option enables you to generate a separate Python module for each XML schema that is imported or included (using <tt class="docutils literal"><xs:import></tt> or <tt class="docutils literal"><xs:include></tt>) by @@ -2722,11 +2780,11 @@ directory into a Python package.</p> </ul> </div> <div class="section" id="how-to-modify-the-generated-code"> -<h1><a class="toc-backref" href="#id81">14 How to modify the generated code</a></h1> +<h1><a class="toc-backref" href="#id83">14 How to modify the generated code</a></h1> <p>This section attempts to explain how to modify and add features to the generated code.</p> <div class="section" id="adding-features-to-class-definitions"> -<h2><a class="toc-backref" href="#id82">14.1 Adding features to class definitions</a></h2> +<h2><a class="toc-backref" href="#id84">14.1 Adding features to class definitions</a></h2> <p>You can add new member definitions to a generated class. Look at the 'export' and 'exportLiteral' member functions for examples of how to access member variables and how to walk nested @@ -2771,7 +2829,7 @@ parser, for example, since generating the file.</li> </div> </div> <div class="section" id="examples-and-demonstrations"> -<h1><a class="toc-backref" href="#id83">15 Examples and demonstrations</a></h1> +<h1><a class="toc-backref" href="#id85">15 Examples and demonstrations</a></h1> <p>Under the directory Demos are several examples:</p> <ul class="simple"> <li>Demos/People provides a simple demonstration of generating @@ -2797,7 +2855,7 @@ containing explicit control logic, the order in which nodes of the parsed XML document are visited is under your control.</li> </ul> <div class="section" id="django-generating-models-and-forms"> -<h2><a class="toc-backref" href="#id84">15.1 Django -- Generating Models and Forms</a></h2> +<h2><a class="toc-backref" href="#id86">15.1 Django -- Generating Models and Forms</a></h2> <p><tt class="docutils literal">generateDS.py</tt> can be used to generate Django models and Django forms that represent the data structures defined in an XML Schema.</p> <p><strong>Note:</strong> In order to use this capability, you must obtain the @@ -2825,7 +2883,7 @@ or <tt class="docutils literal">easy_install</tt>).</p> </ul> <p>The script <tt class="docutils literal">gends_run_gen_django.py</tt> performs these three steps.</p> <div class="section" id="how-to-generate-django-models-and-forms"> -<h3><a class="toc-backref" href="#id85">15.1.1 How to generate Django models and forms</a></h3> +<h3><a class="toc-backref" href="#id87">15.1.1 How to generate Django models and forms</a></h3> <p><strong>Warning:</strong> Running this script attempts to over-write the following files in the current directory:</p> <ul class="simple"> @@ -2870,7 +2928,7 @@ Django application.</p> </ol> </div> <div class="section" id="how-it-works"> -<h3><a class="toc-backref" href="#id86">15.1.2 How it works</a></h3> +<h3><a class="toc-backref" href="#id88">15.1.2 How it works</a></h3> <p>Here are a few notes that might be helpful if and when you need to do some debugging or extend the current capabilities or write a new "meta-app" that uses the same approach but does something new and @@ -2897,9 +2955,9 @@ root super class of all generated data representation classes.</p> </div> </div> <div class="section" id="sample-code-and-extensions"> -<h1><a class="toc-backref" href="#id87">16 Sample code and extensions</a></h1> +<h1><a class="toc-backref" href="#id89">16 Sample code and extensions</a></h1> <div class="section" id="capturing-xs-date-elements-as-dates"> -<h2><a class="toc-backref" href="#id88">16.1 Capturing xs:date elements as dates</a></h2> +<h2><a class="toc-backref" href="#id90">16.1 Capturing xs:date elements as dates</a></h2> <p>The following extension employs a user method (see <a class="reference internal" href="#user-methods">User Methods</a>) in order to capture elements defined as xs:date as date objects.</p> @@ -2968,9 +3026,9 @@ import types </div> </div> <div class="section" id="limitations-of-generateds"> -<h1><a class="toc-backref" href="#id89">17 Limitations of generateDS</a></h1> +<h1><a class="toc-backref" href="#id91">17 Limitations of generateDS</a></h1> <div class="section" id="xml-schema-limitations"> -<h2><a class="toc-backref" href="#id90">17.1 XML Schema limitations</a></h2> +<h2><a class="toc-backref" href="#id92">17.1 XML Schema limitations</a></h2> <p>There are things in Xschema that are not supported. You will have to use a restricted sub-set of Xschema to define your data structures. See above for supported features. See people.xsd and @@ -2979,7 +3037,7 @@ people.xml for examples.</p> does not work.</p> </div> <div class="section" id="large-documents"> -<h2><a class="toc-backref" href="#id91">17.2 Large documents</a></h2> +<h2><a class="toc-backref" href="#id93">17.2 Large documents</a></h2> <p><strong>Warning</strong> -- This section describes an optional generated SAX parser which, I believe, is currently broken for all but the simplest schemas. Generation of a SAX parser has not been updated @@ -3006,7 +3064,7 @@ memory problem to some extent when the minidom parser is used.</p> </div> </div> <div class="section" id="includes-the-xml-schema-include-element"> -<h1><a class="toc-backref" href="#id92">18 Includes -- The XML schema include element</a></h1> +<h1><a class="toc-backref" href="#id94">18 Includes -- The XML schema include element</a></h1> <p>While <tt class="docutils literal">generateDS.py</tt> itself does not process XML Schema <tt class="docutils literal">include</tt> elements, the distribution provides a script <tt class="docutils literal">process_includes.py</tt> that can be used as a preprocessor. This @@ -3031,7 +3089,7 @@ $ python process_includes.py --help </pre> </div> <div class="section" id="acknowledgments"> -<h1><a class="toc-backref" href="#id93">19 Acknowledgments</a></h1> +<h1><a class="toc-backref" href="#id95">19 Acknowledgments</a></h1> <p>Many thanks to those who have used <tt class="docutils literal">generateDS.py</tt> and have contributed their comments and suggestions. These comments have been valuable both in teaching me about things I needed to know in @@ -3045,7 +3103,7 @@ following among others:</p> </ul> </div> <div class="section" id="see-also"> -<h1><a class="toc-backref" href="#id94">20 See also</a></h1> +<h1><a class="toc-backref" href="#id96">20 See also</a></h1> <p><a class="reference external" href="http://www.python.org">Python</a>: The Python home page.</p> <p><a class="reference external" href="http://www.davekuhlman.org">Dave's Page</a>: My home page, which contains more Python stuff.</p> <!-- vim:ft=rst: --> @@ -3054,7 +3112,7 @@ following among others:</p> <div class="footer"> <hr class="footer" /> <a class="reference external" href="generateDS.txt">View document source</a>. -Generated on: 2015-08-13 20:46 UTC. +Generated on: 2015-08-17 16:40 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 4e210ec70df9cbd56d61ea2c52cbc5b8b45bb99f..8279ce0b47a0da2062a411be0b9400c595d0029f 100755 --- a/generateDS.py +++ b/generateDS.py @@ -93,9 +93,9 @@ Options: Default: "write" --preserve-cdata-tags Preserve CDATA tags. Default: False --cleanup-name-list=<replacement-map> - Specifies list of 2-tuples used for cleaning names. - First element is a regular expression search - pattern and second is a replacement. + Specifies list of 2-tuples used for cleaning + names. First element is a regular expression + search pattern and second is a replacement. Example: "[('[-:.]', '_'), ('^__', 'Special')]" Default: "[('[-:.]', '_')]" -q, --no-questions Do not ask questions, for example, @@ -194,7 +194,7 @@ logging.disable(logging.INFO) # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.16a' +VERSION = '2.17a' ##VERSION## GenerateProperties = 0 @@ -6828,10 +6828,10 @@ def main(): 'Option --cleanup-name-list must be a list or a tuple.') CleanupNameList = [] for cleanup_pair in cleanup_list: - if type(cleanup_pair) not in (list, tuple) \ - or len(cleanup_pair) != 2 \ - or type(cleanup_pair[0]) not in (str, unicode) \ - or type(cleanup_pair[1]) not in (str, unicode): + if (type(cleanup_pair) not in (list, tuple) or + len(cleanup_pair) != 2 or + not isinstance(cleanup_pair[0], basestring) or + not isinstance(cleanup_pair[1], basestring)): raise RuntimeError( 'Option --cleanup-name-list contains invalid element.') try: @@ -6839,7 +6839,8 @@ def main(): (re.compile(cleanup_pair[0]), cleanup_pair[1])) except Exception: raise RuntimeError( - 'Option --cleanup-name-list contains invalid pattern "%s".' + 'Option --cleanup-name-list contains invalid ' + 'pattern "%s".' % cleanup_pair[0]) if showVersion: diff --git a/generateDS.txt b/generateDS.txt index ee16bb8cd2fd4cca2700577af0f6e2d4653c681f..44648c953af8deb98bc8a6d12002936fe9396b4d 100644 --- a/generateDS.txt +++ b/generateDS.txt @@ -12,7 +12,7 @@ generateDS -- Generate Data Structures from XML Schema .. version -:revision: 2.16a +:revision: 2.17a .. version @@ -310,11 +310,12 @@ Here is the usage message displayed by ``generateDS.py``:: Example: "write etree" Default: "write" --preserve-cdata-tags Preserve CDATA tags. Default: False - --cleanup-name-dict=<replacement-map> - Specifies replacement pairs when cleaning up - names. - Example: "{':': 'colon', '-': 'dash', '.': 'dot'}" - Default: "{':': '_', '-': '_', '.': '_'}" + --cleanup-name-list=<replacement-map> + Specifies list of 2-tuples used for cleaning + names. First element is a regular expression + search pattern and second is a replacement. + Example: "[('[-:.]', '_'), ('^__', 'Special')]" + Default: "[('[-:.]', '_')]" -q, --no-questions Do not ask questions, for example, force overwrite. --session=mysession.session @@ -339,6 +340,9 @@ Here is the usage message displayed by ``generateDS.py``:: also generates member specifications in each class (in a dictionary). +Command line options +---------------------- + The following command line options are recognized by ``generateDS.py``: o <filename> @@ -577,18 +581,26 @@ preserve-cdata-tags option is included, the generated code will preserve those tags and will write them out during export. The default is False. -cleanup-name-dict=<replacement-map> +cleanup-name-list=<replacement-map> Specifies replacement pairs to be used when cleaning up names. - Must be a string representation of a Python dictionary. The - keys and values in this dictionary must be strings. The - intension is to enable us to replace special characters in names - that would cause the generation of invalid Python names, for - example the names of generated classes. However, since a simple - string replacement is performed, you can replace any single - character or sequence of characters by any other single - character or sequence of characters. Example: ``{':': 'colon', - '-': 'dash', '.': 'dot'}``. Default when omitted: ``{':': '_', - '-': '_', '.': '_'}``. + Must be a string representation of a Python list of 2-tuples. + The values of each pair (2-tuple) must be strings. The first + item of each pair is a pattern and must be a valid Python + regular expression (see + https://docs.python.org/2/library/re.html#module-re) The second + item of each pair is a string that will replace anything matched + by the pattern. Also see `Cleaning up names with special characters etc.`_ + + The intension is to enable us to replace + special characters in names that would cause the generation of + invalid Python names, for example the names of generated + classes. However, since a string replacement is + performed, you can replace any single character or sequence of + characters by any other single character or sequence of + characters. Example: + ``[(':', 'colon'), ('-', 'dash'), ('.', 'dot')]``. + + The default when omitted is ``[('[-:.]', '_')]``. q, no-questions Do not ask questions. For example, if the "-f" command line @@ -625,8 +637,8 @@ version exit. -Name conflicts --------------- +Name conflicts etc. +--------------------- Conflicts with Python keywords .............................. @@ -683,14 +695,49 @@ Cleaning up names with special characters etc. ``generateDS.py`` attempts to clean up names that contain special characters. For example, a complexType whose name contains a dash would generate a Python class with an invalid name. But, you can -use this facility to make other changes to names as well. See the -notes on the command line option ``--cleanup-name-dict`` for more on -this. +use this facility to make other changes to names as well. + +The command line option ``--cleanup-name-list`` specifies +replacement pairs to be used when cleaning up (and modifying) names. +The value of this option must be a string representation of a Python +list of 2-tuples. The values of each pair (2-tuple) must be +strings. The first item of each pair is a pattern and must be a +valid Python regular expression (see +https://docs.python.org/2/library/re.html#module-re) The second item +of each pair is a string that will replace anything matched by the +pattern. The intension is to enable us to replace special +characters in names that would cause the generation of invalid +Python names, for example the names of generated classes. However, +since a string replacement is performed, you can replace any single +character or sequence of characters by any other single character or +sequence of characters. + +For example, the following option, in addition to performing the +default replacements of "-", ":", and "." by an underscore, would +also replace the string "Type" when it occurs at the end of a name, +by "Class":: + + --cleanup-name-list="[('[-:.]', '_'), ('Type$', 'Class')]" + +This would cause the name "big-data-Type" to become "big_data_Class". + +The default when this option is omitted is ``[('[-:.]', '_')]``. + +The order of replacements performed is the same as the order of the +tuples in the list. So, replacements performed by pattern +replacement pairs (2-tuples) later in the list (to the right) will +be performed after those earlier (to the left), and may overwrite +earlier replacements. + +See the notes on the command line option ``--cleanup-name-list`` for +more on this. Or, run ``$ generateDS.py --help``. The graphical user interface -- How to use it ============================================================== +**Note:** The graphical user interface is no longer supported. + Here are a few notes on how to use the GUI front-end. - ``generateds_gui.py`` is installed when you do the standard diff --git a/gui/generateds_gui.py b/gui/generateds_gui.py index 41ab05c313b96d5c61dcbed793fdb0a5d0364a4a..0a77cbce41e9d89aab0540b994a2372f638e9427 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.16a' +VERSION = '2.17a' ##VERSION## diff --git a/librarytemplate_howto.txt b/librarytemplate_howto.txt index 73dacac350df6c4150d051d8a7a1fe505cce77f2..ab38257c8b51a73be8ae6c8409c7154fb635c73a 100644 --- a/librarytemplate_howto.txt +++ b/librarytemplate_howto.txt @@ -8,7 +8,7 @@ How to package a generateDS.py generated library .. version -:revision: 2.16a +:revision: 2.17a .. version diff --git a/process_includes.py b/process_includes.py index b605ca94aa53f2d8da78a622dbed2d889a40e263..2abba61b41527386cc3e874da87784c5267a5a59 100755 --- a/process_includes.py +++ b/process_includes.py @@ -35,7 +35,7 @@ except ImportError: # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.16a' +VERSION = '2.17a' ##VERSION## CatalogDict = {} diff --git a/setup.py b/setup.py index b982052c5568649880fdc78c115a7c0e5faab70a..cb0f94be828a913a22b5e09dfcf6b87e2007cce6 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.16a", + version="2.17a", ##VERSION## author="Dave Kuhlman", author_email="dkuhlman@davekuhlman.org", diff --git a/tests/check_results.rb b/tests/check_results.rb index a4563266f682c0c0c70913f922131c008ea25af3..fd60745c4c4d4771c34a9162df4ee7fbe243ac37 100755 --- a/tests/check_results.rb +++ b/tests/check_results.rb @@ -61,6 +61,8 @@ $commands = [ "diff -u defaults_coverage1_sup.py defaults_coverage2_sup.py", "diff -u defaults_cases1_sub.py defaults_cases2_sub.py", "diff -u defaults_cases1_sup.py defaults_cases2_sup.py", + "diff -u cleanupname1_sub.py cleanupname2_sub.py", + "diff -u cleanupname1_sup.py cleanupname2_sup.py", ] def check diff --git a/tests/cleanupname.xsd b/tests/cleanupname.xsd new file mode 100644 index 0000000000000000000000000000000000000000..067422185df72a69394457f764068ab7ca7b3333 --- /dev/null +++ b/tests/cleanupname.xsd @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema + xmlns:xs="http://www.w3.org/2001/XMLSchema" + > + + <xs:element name="data" type="dataType"/> + + <xs:complexType name="dataType"> + <xs:sequence> + <xs:element name="data1" type="data1Type"/> + <xs:element name="data2" type="TypeData2"/> + <xs:element name="data3" type="RealTypeData3"/> + <xs:element name="data4" type="AABBCCdataType"/> + <xs:element name="data5" type="dataTypeXYZAXYZ"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="data1Type"> + <xs:sequence> + <xs:element name="content1" type="xs:string"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="TypeData2"> + <xs:sequence> + <xs:element name="content1" type="xs:string"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="RealTypeData3"> + <xs:sequence> + <xs:element name="content1" type="xs:string"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="AABBCCdataType"> + <xs:sequence> + <xs:element name="content1" type="xs:string"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="dataTypeXYZAXYZ"> + <xs:sequence> + <xs:element name="content1" type="xs:string"/> + </xs:sequence> + </xs:complexType> + +</xs:schema> diff --git a/tests/cleanupname1_sub.py b/tests/cleanupname1_sub.py new file mode 100644 index 0000000000000000000000000000000000000000..c00f3e0e4fbb1bccd3c66d705a03cf2c2983a682 --- /dev/null +++ b/tests/cleanupname1_sub.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--silence', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/cleanupname2_sup.py') +# ('-s', 'tests/cleanupname2_sub.py') +# ('--super', 'cleanupname2_sup') +# ('--cleanup-name-list', "[('[-:.]', '_'), ('^Type', 'Class'), ('Type$', 'Kind'), ('[ABC]', 'M'), ('[XYZ]', 'N'), ]") +# +# Command line arguments: +# tests/cleanupname.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --silence --member-specs="list" -f -o "tests/cleanupname2_sup.py" -s "tests/cleanupname2_sub.py" --super="cleanupname2_sup" --cleanup-name-list="[('[-:.]', '_'), ('^Type', 'Class'), ('Type$', 'Kind'), ('[ABC]', 'M'), ('[XYZ]', 'N'), ]" tests/cleanupname.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys +from lxml import etree as etree_ + +import cleanupname2_sup as supermod + +def parsexml_(infile, parser=None, **kwargs): + if parser is None: + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + parser = etree_.ETCompatXMLParser() + doc = etree_.parse(infile, parser=parser, **kwargs) + return doc + +# +# Globals +# + +ExternalEncoding = 'ascii' + +# +# Data representation classes +# + + +class dataKindSub(supermod.dataKind): + def __init__(self, data1=None, data2=None, data3=None, data4=None, data5=None): + super(dataKindSub, self).__init__(data1, data2, data3, data4, data5, ) +supermod.dataKind.subclass = dataKindSub +# end class dataKindSub + + +class data1KindSub(supermod.data1Kind): + def __init__(self, content1=None): + super(data1KindSub, self).__init__(content1, ) +supermod.data1Kind.subclass = data1KindSub +# end class data1KindSub + + +class MlassData2Sub(supermod.MlassData2): + def __init__(self, content1=None): + super(MlassData2Sub, self).__init__(content1, ) +supermod.MlassData2.subclass = MlassData2Sub +# end class MlassData2Sub + + +class RealTypeData3Sub(supermod.RealTypeData3): + def __init__(self, content1=None): + super(RealTypeData3Sub, self).__init__(content1, ) +supermod.RealTypeData3.subclass = RealTypeData3Sub +# end class RealTypeData3Sub + + +class MMMMMMdataKindSub(supermod.MMMMMMdataKind): + def __init__(self, content1=None): + super(MMMMMMdataKindSub, self).__init__(content1, ) +supermod.MMMMMMdataKind.subclass = MMMMMMdataKindSub +# end class MMMMMMdataKindSub + + +class dataTypeNNNMNNNSub(supermod.dataTypeNNNMNNN): + def __init__(self, content1=None): + super(dataTypeNNNMNNNSub, self).__init__(content1, ) +supermod.dataTypeNNNMNNN.subclass = dataTypeNNNMNNNSub +# end class dataTypeNNNMNNNSub + + +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): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = supermod.dataKind + 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): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = supermod.dataKind + 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 + parser = None + doc = parsexml_(StringIO(inString), parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = supermod.dataKind + 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): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = supermod.dataKind + 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 cleanupname2_sup import *\n\n') +## sys.stdout.write('import cleanupname2_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/cleanupname1_sup.py b/tests/cleanupname1_sup.py new file mode 100644 index 0000000000000000000000000000000000000000..bde041d8acc75c65cb53943fe8a267e85e834e1e --- /dev/null +++ b/tests/cleanupname1_sup.py @@ -0,0 +1,1223 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--silence', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/cleanupname2_sup.py') +# ('-s', 'tests/cleanupname2_sub.py') +# ('--super', 'cleanupname2_sup') +# ('--cleanup-name-list', "[('[-:.]', '_'), ('^Type', 'Class'), ('Type$', 'Kind'), ('[ABC]', 'M'), ('[XYZ]', 'N'), ]") +# +# Command line arguments: +# tests/cleanupname.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --silence --member-specs="list" -f -o "tests/cleanupname2_sup.py" -s "tests/cleanupname2_sub.py" --super="cleanupname2_sup" --cleanup-name-list="[('[-:.]', '_'), ('^Type', 'Class'), ('Type$', 'Kind'), ('[ABC]', 'M'), ('[XYZ]', 'N'), ]" tests/cleanupname.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys +import re as re_ +import base64 +import datetime as datetime_ +import warnings as warnings_ +from lxml import etree as etree_ + + +Validate_simpletypes_ = True + + +def parsexml_(infile, parser=None, **kwargs): + if parser is None: + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + parser = etree_.ETCompatXMLParser() + doc = etree_.parse(infile, parser=parser, **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 as 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=None, 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=None, 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=None, 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=None, input_name=''): + values = input_data.split() + for value in values: + try: + int(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=None, 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=None, 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=None, 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=None, 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=None, 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=None, 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=None, 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=None, 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=None, 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 + def gds_validate_simple_patterns(self, patterns, target): + # pat is a list of lists of strings/patterns. We should: + # - AND the outer elements + # - OR the inner elements + found1 = True + for patterns1 in patterns: + found2 = False + for patterns2 in patterns1: + if re_.search(patterns2, target) is not None: + found2 = True + break + if not found2: + found1 = False + break + return found1 + @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'{(.*)}(.*)') +CDATA_pattern_ = re_.compile(r"<!\[CDATA\[.*?\]\]>", re_.DOTALL) + +# +# Support/utility functions. +# + + +def showIndent(outfile, level, pretty_print=True): + if pretty_print: + for idx in range(level): + outfile.write(' ') + + +def quote_xml(inStr): + "Escape markup chars, but do not modify CDATA sections." + if not inStr: + return '' + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s2 = '' + pos = 0 + matchobjects = CDATA_pattern_.finditer(s1) + for mo in matchobjects: + s3 = s1[pos:mo.start()] + s2 += quote_xml_aux(s3) + s2 += s1[mo.start():mo.end()] + pos = mo.end() + s3 = s1[pos:] + s2 += quote_xml_aux(s3) + return s2 + + +def quote_xml_aux(inStr): + s1 = inStr.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): + msg = '%s (element %s/line %d)' % (msg, node.tag, node.sourceline, ) + 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 dataKind(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('data1', 'data1Type', 0), + MemberSpec_('data2', 'TypeData2', 0), + MemberSpec_('data3', 'RealTypeData3', 0), + MemberSpec_('data4', 'AABBCCdataType', 0), + MemberSpec_('data5', 'dataTypeXYZAXYZ', 0), + ] + subclass = None + superclass = None + def __init__(self, data1=None, data2=None, data3=None, data4=None, data5=None): + self.original_tagname_ = None + self.data1 = data1 + self.data2 = data2 + self.data3 = data3 + self.data4 = data4 + self.data5 = data5 + def factory(*args_, **kwargs_): + if dataKind.subclass: + return dataKind.subclass(*args_, **kwargs_) + else: + return dataKind(*args_, **kwargs_) + factory = staticmethod(factory) + def get_data1(self): return self.data1 + def set_data1(self, data1): self.data1 = data1 + def get_data2(self): return self.data2 + def set_data2(self, data2): self.data2 = data2 + def get_data3(self): return self.data3 + def set_data3(self, data3): self.data3 = data3 + def get_data4(self): return self.data4 + def set_data4(self, data4): self.data4 = data4 + def get_data5(self): return self.data5 + def set_data5(self, data5): self.data5 = data5 + def hasContent_(self): + if ( + self.data1 is not None or + self.data2 is not None or + self.data3 is not None or + self.data4 is not None or + self.data5 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='dataType', 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_='dataType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='dataType', 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_='dataType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='dataType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.data1 is not None: + self.data1.export(outfile, level, namespace_, name_='data1', pretty_print=pretty_print) + if self.data2 is not None: + self.data2.export(outfile, level, namespace_, name_='data2', pretty_print=pretty_print) + if self.data3 is not None: + self.data3.export(outfile, level, namespace_, name_='data3', pretty_print=pretty_print) + if self.data4 is not None: + self.data4.export(outfile, level, namespace_, name_='data4', pretty_print=pretty_print) + if self.data5 is not None: + self.data5.export(outfile, level, namespace_, name_='data5', pretty_print=pretty_print) + 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_ == 'data1': + obj_ = data1Kind.factory() + obj_.build(child_) + self.data1 = obj_ + obj_.original_tagname_ = 'data1' + elif nodeName_ == 'data2': + obj_ = MlassData2.factory() + obj_.build(child_) + self.data2 = obj_ + obj_.original_tagname_ = 'data2' + elif nodeName_ == 'data3': + obj_ = RealTypeData3.factory() + obj_.build(child_) + self.data3 = obj_ + obj_.original_tagname_ = 'data3' + elif nodeName_ == 'data4': + obj_ = MMMMMMdataKind.factory() + obj_.build(child_) + self.data4 = obj_ + obj_.original_tagname_ = 'data4' + elif nodeName_ == 'data5': + obj_ = dataTypeNNNMNNN.factory() + obj_.build(child_) + self.data5 = obj_ + obj_.original_tagname_ = 'data5' +# end class dataKind + + +class data1Kind(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if data1Kind.subclass: + return data1Kind.subclass(*args_, **kwargs_) + else: + return data1Kind(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='data1Type', 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_='data1Type') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='data1Type', 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_='data1Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='data1Type', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class data1Kind + + +class MlassData2(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if MlassData2.subclass: + return MlassData2.subclass(*args_, **kwargs_) + else: + return MlassData2(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='TypeData2', 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_='TypeData2') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='TypeData2', 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_='TypeData2'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='TypeData2', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class MlassData2 + + +class RealTypeData3(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if RealTypeData3.subclass: + return RealTypeData3.subclass(*args_, **kwargs_) + else: + return RealTypeData3(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='RealTypeData3', 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_='RealTypeData3') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='RealTypeData3', 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_='RealTypeData3'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='RealTypeData3', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class RealTypeData3 + + +class MMMMMMdataKind(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if MMMMMMdataKind.subclass: + return MMMMMMdataKind.subclass(*args_, **kwargs_) + else: + return MMMMMMdataKind(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='AABBCCdataType', 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_='AABBCCdataType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='AABBCCdataType', 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_='AABBCCdataType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='AABBCCdataType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class MMMMMMdataKind + + +class dataTypeNNNMNNN(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if dataTypeNNNMNNN.subclass: + return dataTypeNNNMNNN.subclass(*args_, **kwargs_) + else: + return dataTypeNNNMNNN(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='dataTypeXYZAXYZ', 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_='dataTypeXYZAXYZ') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='dataTypeXYZAXYZ', 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_='dataTypeXYZAXYZ'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='dataTypeXYZAXYZ', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class dataTypeNNNMNNN + + +GDSClassesMapping = { + 'data': dataKind, + 'data5': dataTypeNNNMNNN, + 'data4': MMMMMMdataKind, + 'data1': data1Kind, + 'data3': RealTypeData3, + 'data2': MlassData2, +} + + +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): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = dataKind + 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): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = dataKind + 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 + parser = None + doc = parsexml_(StringIO(inString), parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = dataKind + 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): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = dataKind + 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 cleanupname2_sup import *\n\n') +## sys.stdout.write('import cleanupname2_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__ = [ + "MMMMMMdataKind", + "MlassData2", + "RealTypeData3", + "data1Kind", + "dataKind", + "dataTypeNNNMNNN" +] diff --git a/tests/cleanupname2_sub.py b/tests/cleanupname2_sub.py new file mode 100644 index 0000000000000000000000000000000000000000..c00f3e0e4fbb1bccd3c66d705a03cf2c2983a682 --- /dev/null +++ b/tests/cleanupname2_sub.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--silence', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/cleanupname2_sup.py') +# ('-s', 'tests/cleanupname2_sub.py') +# ('--super', 'cleanupname2_sup') +# ('--cleanup-name-list', "[('[-:.]', '_'), ('^Type', 'Class'), ('Type$', 'Kind'), ('[ABC]', 'M'), ('[XYZ]', 'N'), ]") +# +# Command line arguments: +# tests/cleanupname.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --silence --member-specs="list" -f -o "tests/cleanupname2_sup.py" -s "tests/cleanupname2_sub.py" --super="cleanupname2_sup" --cleanup-name-list="[('[-:.]', '_'), ('^Type', 'Class'), ('Type$', 'Kind'), ('[ABC]', 'M'), ('[XYZ]', 'N'), ]" tests/cleanupname.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys +from lxml import etree as etree_ + +import cleanupname2_sup as supermod + +def parsexml_(infile, parser=None, **kwargs): + if parser is None: + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + parser = etree_.ETCompatXMLParser() + doc = etree_.parse(infile, parser=parser, **kwargs) + return doc + +# +# Globals +# + +ExternalEncoding = 'ascii' + +# +# Data representation classes +# + + +class dataKindSub(supermod.dataKind): + def __init__(self, data1=None, data2=None, data3=None, data4=None, data5=None): + super(dataKindSub, self).__init__(data1, data2, data3, data4, data5, ) +supermod.dataKind.subclass = dataKindSub +# end class dataKindSub + + +class data1KindSub(supermod.data1Kind): + def __init__(self, content1=None): + super(data1KindSub, self).__init__(content1, ) +supermod.data1Kind.subclass = data1KindSub +# end class data1KindSub + + +class MlassData2Sub(supermod.MlassData2): + def __init__(self, content1=None): + super(MlassData2Sub, self).__init__(content1, ) +supermod.MlassData2.subclass = MlassData2Sub +# end class MlassData2Sub + + +class RealTypeData3Sub(supermod.RealTypeData3): + def __init__(self, content1=None): + super(RealTypeData3Sub, self).__init__(content1, ) +supermod.RealTypeData3.subclass = RealTypeData3Sub +# end class RealTypeData3Sub + + +class MMMMMMdataKindSub(supermod.MMMMMMdataKind): + def __init__(self, content1=None): + super(MMMMMMdataKindSub, self).__init__(content1, ) +supermod.MMMMMMdataKind.subclass = MMMMMMdataKindSub +# end class MMMMMMdataKindSub + + +class dataTypeNNNMNNNSub(supermod.dataTypeNNNMNNN): + def __init__(self, content1=None): + super(dataTypeNNNMNNNSub, self).__init__(content1, ) +supermod.dataTypeNNNMNNN.subclass = dataTypeNNNMNNNSub +# end class dataTypeNNNMNNNSub + + +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): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = supermod.dataKind + 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): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = supermod.dataKind + 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 + parser = None + doc = parsexml_(StringIO(inString), parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = supermod.dataKind + 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): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = supermod.dataKind + 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 cleanupname2_sup import *\n\n') +## sys.stdout.write('import cleanupname2_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/cleanupname2_sup.py b/tests/cleanupname2_sup.py new file mode 100644 index 0000000000000000000000000000000000000000..bde041d8acc75c65cb53943fe8a267e85e834e1e --- /dev/null +++ b/tests/cleanupname2_sup.py @@ -0,0 +1,1223 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--silence', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/cleanupname2_sup.py') +# ('-s', 'tests/cleanupname2_sub.py') +# ('--super', 'cleanupname2_sup') +# ('--cleanup-name-list', "[('[-:.]', '_'), ('^Type', 'Class'), ('Type$', 'Kind'), ('[ABC]', 'M'), ('[XYZ]', 'N'), ]") +# +# Command line arguments: +# tests/cleanupname.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --silence --member-specs="list" -f -o "tests/cleanupname2_sup.py" -s "tests/cleanupname2_sub.py" --super="cleanupname2_sup" --cleanup-name-list="[('[-:.]', '_'), ('^Type', 'Class'), ('Type$', 'Kind'), ('[ABC]', 'M'), ('[XYZ]', 'N'), ]" tests/cleanupname.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys +import re as re_ +import base64 +import datetime as datetime_ +import warnings as warnings_ +from lxml import etree as etree_ + + +Validate_simpletypes_ = True + + +def parsexml_(infile, parser=None, **kwargs): + if parser is None: + # Use the lxml ElementTree compatible parser so that, e.g., + # we ignore comments. + parser = etree_.ETCompatXMLParser() + doc = etree_.parse(infile, parser=parser, **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 as 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=None, 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=None, 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=None, 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=None, input_name=''): + values = input_data.split() + for value in values: + try: + int(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=None, 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=None, 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=None, 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=None, 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=None, 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=None, 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=None, 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=None, 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=None, 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 + def gds_validate_simple_patterns(self, patterns, target): + # pat is a list of lists of strings/patterns. We should: + # - AND the outer elements + # - OR the inner elements + found1 = True + for patterns1 in patterns: + found2 = False + for patterns2 in patterns1: + if re_.search(patterns2, target) is not None: + found2 = True + break + if not found2: + found1 = False + break + return found1 + @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'{(.*)}(.*)') +CDATA_pattern_ = re_.compile(r"<!\[CDATA\[.*?\]\]>", re_.DOTALL) + +# +# Support/utility functions. +# + + +def showIndent(outfile, level, pretty_print=True): + if pretty_print: + for idx in range(level): + outfile.write(' ') + + +def quote_xml(inStr): + "Escape markup chars, but do not modify CDATA sections." + if not inStr: + return '' + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s2 = '' + pos = 0 + matchobjects = CDATA_pattern_.finditer(s1) + for mo in matchobjects: + s3 = s1[pos:mo.start()] + s2 += quote_xml_aux(s3) + s2 += s1[mo.start():mo.end()] + pos = mo.end() + s3 = s1[pos:] + s2 += quote_xml_aux(s3) + return s2 + + +def quote_xml_aux(inStr): + s1 = inStr.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): + msg = '%s (element %s/line %d)' % (msg, node.tag, node.sourceline, ) + 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 dataKind(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('data1', 'data1Type', 0), + MemberSpec_('data2', 'TypeData2', 0), + MemberSpec_('data3', 'RealTypeData3', 0), + MemberSpec_('data4', 'AABBCCdataType', 0), + MemberSpec_('data5', 'dataTypeXYZAXYZ', 0), + ] + subclass = None + superclass = None + def __init__(self, data1=None, data2=None, data3=None, data4=None, data5=None): + self.original_tagname_ = None + self.data1 = data1 + self.data2 = data2 + self.data3 = data3 + self.data4 = data4 + self.data5 = data5 + def factory(*args_, **kwargs_): + if dataKind.subclass: + return dataKind.subclass(*args_, **kwargs_) + else: + return dataKind(*args_, **kwargs_) + factory = staticmethod(factory) + def get_data1(self): return self.data1 + def set_data1(self, data1): self.data1 = data1 + def get_data2(self): return self.data2 + def set_data2(self, data2): self.data2 = data2 + def get_data3(self): return self.data3 + def set_data3(self, data3): self.data3 = data3 + def get_data4(self): return self.data4 + def set_data4(self, data4): self.data4 = data4 + def get_data5(self): return self.data5 + def set_data5(self, data5): self.data5 = data5 + def hasContent_(self): + if ( + self.data1 is not None or + self.data2 is not None or + self.data3 is not None or + self.data4 is not None or + self.data5 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='dataType', 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_='dataType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='dataType', 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_='dataType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='dataType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.data1 is not None: + self.data1.export(outfile, level, namespace_, name_='data1', pretty_print=pretty_print) + if self.data2 is not None: + self.data2.export(outfile, level, namespace_, name_='data2', pretty_print=pretty_print) + if self.data3 is not None: + self.data3.export(outfile, level, namespace_, name_='data3', pretty_print=pretty_print) + if self.data4 is not None: + self.data4.export(outfile, level, namespace_, name_='data4', pretty_print=pretty_print) + if self.data5 is not None: + self.data5.export(outfile, level, namespace_, name_='data5', pretty_print=pretty_print) + 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_ == 'data1': + obj_ = data1Kind.factory() + obj_.build(child_) + self.data1 = obj_ + obj_.original_tagname_ = 'data1' + elif nodeName_ == 'data2': + obj_ = MlassData2.factory() + obj_.build(child_) + self.data2 = obj_ + obj_.original_tagname_ = 'data2' + elif nodeName_ == 'data3': + obj_ = RealTypeData3.factory() + obj_.build(child_) + self.data3 = obj_ + obj_.original_tagname_ = 'data3' + elif nodeName_ == 'data4': + obj_ = MMMMMMdataKind.factory() + obj_.build(child_) + self.data4 = obj_ + obj_.original_tagname_ = 'data4' + elif nodeName_ == 'data5': + obj_ = dataTypeNNNMNNN.factory() + obj_.build(child_) + self.data5 = obj_ + obj_.original_tagname_ = 'data5' +# end class dataKind + + +class data1Kind(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if data1Kind.subclass: + return data1Kind.subclass(*args_, **kwargs_) + else: + return data1Kind(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='data1Type', 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_='data1Type') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='data1Type', 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_='data1Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='data1Type', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class data1Kind + + +class MlassData2(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if MlassData2.subclass: + return MlassData2.subclass(*args_, **kwargs_) + else: + return MlassData2(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='TypeData2', 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_='TypeData2') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='TypeData2', 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_='TypeData2'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='TypeData2', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class MlassData2 + + +class RealTypeData3(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if RealTypeData3.subclass: + return RealTypeData3.subclass(*args_, **kwargs_) + else: + return RealTypeData3(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='RealTypeData3', 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_='RealTypeData3') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='RealTypeData3', 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_='RealTypeData3'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='RealTypeData3', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class RealTypeData3 + + +class MMMMMMdataKind(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if MMMMMMdataKind.subclass: + return MMMMMMdataKind.subclass(*args_, **kwargs_) + else: + return MMMMMMdataKind(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='AABBCCdataType', 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_='AABBCCdataType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='AABBCCdataType', 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_='AABBCCdataType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='AABBCCdataType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class MMMMMMdataKind + + +class dataTypeNNNMNNN(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('content1', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, content1=None): + self.original_tagname_ = None + self.content1 = content1 + def factory(*args_, **kwargs_): + if dataTypeNNNMNNN.subclass: + return dataTypeNNNMNNN.subclass(*args_, **kwargs_) + else: + return dataTypeNNNMNNN(*args_, **kwargs_) + factory = staticmethod(factory) + def get_content1(self): return self.content1 + def set_content1(self, content1): self.content1 = content1 + def hasContent_(self): + if ( + self.content1 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='dataTypeXYZAXYZ', 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_='dataTypeXYZAXYZ') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='dataTypeXYZAXYZ', 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_='dataTypeXYZAXYZ'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='dataTypeXYZAXYZ', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.content1 is not None: + showIndent(outfile, level, pretty_print) + outfile.write('<%scontent1>%s</%scontent1>%s' % (namespace_, self.gds_format_string(quote_xml(self.content1).encode(ExternalEncoding), input_name='content1'), namespace_, eol_)) + 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_ == 'content1': + content1_ = child_.text + content1_ = self.gds_validate_string(content1_, node, 'content1') + self.content1 = content1_ +# end class dataTypeNNNMNNN + + +GDSClassesMapping = { + 'data': dataKind, + 'data5': dataTypeNNNMNNN, + 'data4': MMMMMMdataKind, + 'data1': data1Kind, + 'data3': RealTypeData3, + 'data2': MlassData2, +} + + +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): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = dataKind + 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): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = dataKind + 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 + parser = None + doc = parsexml_(StringIO(inString), parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = dataKind + 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): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'dataKind' + rootClass = dataKind + 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 cleanupname2_sup import *\n\n') +## sys.stdout.write('import cleanupname2_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__ = [ + "MMMMMMdataKind", + "MlassData2", + "RealTypeData3", + "data1Kind", + "dataKind", + "dataTypeNNNMNNN" +] diff --git a/tests/copy_all b/tests/copy_all index 3f4f6e5fff4f90c0fc099628152274d2de1ab628..f62e238a39eac2c03e97e527c9ea7a00defe4f05 100755 --- a/tests/copy_all +++ b/tests/copy_all @@ -51,3 +51,5 @@ cp defaults_cases2_sup.py defaults_cases1_sup.py cp defaults_cases2_sub.py defaults_cases1_sub.py cp nested_def2_sup.py nested_def1_sup.py cp nested_def2_sub.py nested_def1_sub.py +cp cleanupname2_sup.py cleanupname1_sup.py +cp cleanupname2_sub.py cleanupname1_sub.py diff --git a/tests/test.py b/tests/test.py index b97da999a13b726971547dc979daf644b76589c6..2a91d7510eeb998a76064e1bab6eb1e67cddf1b1 100755 --- a/tests/test.py +++ b/tests/test.py @@ -709,6 +709,32 @@ class GenTest(unittest.TestCase): result, err = self.execute(cmd) self.check_result(result, err, ()) + # + # Test enhancements to cleanupName function. + def test_031_cleanupname(self): + cmdTempl = ( + 'python generateDS.py --no-dates --no-versions ' + '--silence --member-specs=list -f ' + '-o tests/%s2_sup.py -s tests/%s2_sub.py ' + '--super=%s2_sup ' + "--cleanup-name-list=\"[('[-:.]', '_'), " + "('^Type', 'Class'), " + "('Type$', 'Kind'), " + "('[ABC]', 'M'), " + "('[XYZ]', 'N'), " + "]\" " + 'tests/%s.xsd' + ) + t_ = 'cleanupname' + 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, ()) + def check_result(self, result, err, ignore_strings): self.failUnlessEqual(len(result), 0) self.failUnlessEqual(len(err), 0) diff --git a/tutorial/generateds_tutorial.txt b/tutorial/generateds_tutorial.txt index 03b01e78d55cc102150b1645005269a159e948f1..89a303f05b3771c5af02d6c7116cfc34e3ad27d6 100644 --- a/tutorial/generateds_tutorial.txt +++ b/tutorial/generateds_tutorial.txt @@ -11,7 +11,7 @@ generateDS -- Introduction and Tutorial .. version -:revision: 2.16a +:revision: 2.17a .. version