From 3cc34680f7f4acc8b935e80c5f5b280812cd870f Mon Sep 17 00:00:00 2001 From: Dave Kuhlman <dkuhlman@davekuhlman.org> Date: Wed, 20 May 2015 19:20:19 -0700 Subject: [PATCH] nested names with unit test first version --- README | 10 +- generateDS.py | 2 +- generateDS.txt | 2 +- gui/generateds_gui.py | 2 +- librarytemplate_howto.txt | 2 +- process_includes.py | 66 +- setup.py | 2 +- tests/gds_inner_name_map.py | 7 + tests/nested_def.xml | 9 + tests/nested_def.xsd | 38 + tests/nested_def1_out.xml | 9 + tests/nested_def1_sub.py | 200 +++++ tests/nested_def1_sup.py | 1216 ++++++++++++++++++++++++++++++ tests/nested_def2_out.xml | 9 + tests/nested_def2_sub.py | 200 +++++ tests/nested_def2_sup.py | 1216 ++++++++++++++++++++++++++++++ tests/test.py | 37 +- tutorial/generateds_tutorial.txt | 2 +- 18 files changed, 3006 insertions(+), 23 deletions(-) create mode 100644 tests/gds_inner_name_map.py create mode 100644 tests/nested_def.xml create mode 100644 tests/nested_def.xsd create mode 100644 tests/nested_def1_out.xml create mode 100644 tests/nested_def1_sub.py create mode 100644 tests/nested_def1_sup.py create mode 100644 tests/nested_def2_out.xml create mode 100644 tests/nested_def2_sub.py create mode 100644 tests/nested_def2_sup.py diff --git a/README b/README index 4d0ff83..4d548c1 100644 --- a/README +++ b/README @@ -141,10 +141,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Change history -------------- -Version 2.16a (05/04/2015) +Version 2.16a (05/18/2015) - Added new command line option ("--preserve-cdata-tags") that causes generation of code that contains a special parser to retain - CDATA tags. Thanks to Adrian Cook for reporting this. + CDATA tags. Thanks to Adrian Cook for reporting this, for + providing test data and test cases, and for help with testing and + feed-back. +- Added ability for user to specify the names of classes generated + from nested xs:complexType definitions, rather than accept the + names created in process_includes.py. +- Added a unit test for the nested definition capability. Version 2.15b (04/07/2015) - Fix to generation of simpleType validation code for list (unbounded) diff --git a/generateDS.py b/generateDS.py index 4e27c5b..960e428 100755 --- a/generateDS.py +++ b/generateDS.py @@ -187,7 +187,7 @@ logging.disable(logging.INFO) # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.15b' +VERSION = '2.16a' ##VERSION## GenerateProperties = 0 diff --git a/generateDS.txt b/generateDS.txt index 4d90a12..7e0efbf 100644 --- a/generateDS.txt +++ b/generateDS.txt @@ -12,7 +12,7 @@ generateDS -- Generate Data Structures from XML Schema .. version -:revision: 2.15b +:revision: 2.16a .. version diff --git a/gui/generateds_gui.py b/gui/generateds_gui.py index dd14694..41ab05c 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.15b' +VERSION = '2.16a' ##VERSION## diff --git a/librarytemplate_howto.txt b/librarytemplate_howto.txt index 3a3f9c2..73dacac 100644 --- a/librarytemplate_howto.txt +++ b/librarytemplate_howto.txt @@ -8,7 +8,7 @@ How to package a generateDS.py generated library .. version -:revision: 2.15b +:revision: 2.16a .. version diff --git a/process_includes.py b/process_includes.py index 62f4fe6..b605ca9 100755 --- a/process_includes.py +++ b/process_includes.py @@ -22,6 +22,11 @@ import itertools from copy import deepcopy from lxml import etree +try: + from gds_inner_name_map import Inner_name_map +except ImportError: + Inner_name_map = None + # # Globals and constants @@ -30,7 +35,7 @@ from lxml import etree # Do not modify the following VERSION comments. # Used by updateversion.py. ##VERSION## -VERSION = '2.15b' +VERSION = '2.16a' ##VERSION## CatalogDict = {} @@ -38,6 +43,17 @@ CatalogDict = {} CatalogBaseUrl = None +# +# Exceptions + +class SchemaIOError(IOError): + pass + + +class InnerNameMapError(Exception): + pass + + def load_catalog(catalogpath): global CatalogBaseUrl if catalogpath: @@ -91,17 +107,10 @@ class Params(object): def __setattr__(self, name, value): if name not in self.members: raise AttributeError('Class %s has no set-able attribute "%s"' % ( - self.__class__.__name__, name, )) + self.__class__.__name__, name, )) self.__dict__[name] = value -class SchemaIOError(IOError): - pass - - -class RaiseComplexTypesError(Exception): - pass - # # Functions for internal use and testing @@ -475,7 +484,10 @@ def raise_anon_complextypes(root): if not name: continue type_name = '%sType' % (name, ) - type_name, def_count = unique_name(type_name, def_names, def_count) + if Inner_name_map is None: + type_name, def_count = unique_name(type_name, def_names, def_count) + else: + type_name = map_inner_name(node, Inner_name_map) def_names.add(type_name) parent.set('type', type_name) node.set('name', type_name) @@ -483,6 +495,35 @@ def raise_anon_complextypes(root): root.append(node) +def map_inner_name(node, inner_name_map): + """Use a user-supplied mapping table to look up a name for this class/type. + """ + # find the name for the enclosing type definition and + # the name of the type definition that encloses that. + node1 = node + name2 = node1.get('name') + while name2 is None: + node1 = node1.getparent() + if node1 is None: + raise InnerNameMapError('cannot find parent with "name" attribute') + name2 = node1.get('name') + node1 = node1.getparent() + name1 = node1.get('name') + while name1 is None: + node1 = node1.getparent() + if node1 is None: + raise InnerNameMapError('cannot find parent with "name" attribute') + name1 = node1.get('name') + new_name = inner_name_map.get((name1, name2)) + if new_name is None: + msg1 = '("{}", "{}")'.format( + name1, name2) + sys.stderr.write('\n*** error. Must add entry to inner_name_map:\n') + sys.stderr.write('\n {}: "xxxx",\n\n'.format(msg1)) + raise InnerNameMapError('mapping missing for {}'.format(msg1)) + return new_name + + # # Collect the names of all currently defined types (complexType, # simpleType, element). @@ -498,11 +539,10 @@ def collect_type_names(node): else: pattern = './/complexType|.//simpleType|.//element' elements = node.xpath(pattern) - names = [ + names = { el.attrib['name'] for el in elements if 'name' in el.attrib and el.getchildren() - ] - names = set(names) + } return names diff --git a/setup.py b/setup.py index f0bb6dd..8b17964 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.15b", + version="2.16a", ##VERSION## author="Dave Kuhlman", author_email="dkuhlman@davekuhlman.org", diff --git a/tests/gds_inner_name_map.py b/tests/gds_inner_name_map.py new file mode 100644 index 0000000..a883760 --- /dev/null +++ b/tests/gds_inner_name_map.py @@ -0,0 +1,7 @@ + +Inner_name_map = { + ("classAType", "inner"): "inner_001", + ("classBType", "inner"): "inner_002", + #("classAType", "inner"): "class_a_inner", + #("classBType", "inner"): "class_b_inner", +} diff --git a/tests/nested_def.xml b/tests/nested_def.xml new file mode 100644 index 0000000..3582540 --- /dev/null +++ b/tests/nested_def.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<container> + <item1> + <inner attrA1="attrA1value" attrA2="attrA2value"/> + </item1> + <item2> + <inner attrB1="attrB1value" attrB2="attrB2value"/> + </item2> +</container> diff --git a/tests/nested_def.xsd b/tests/nested_def.xsd new file mode 100644 index 0000000..9ad3b50 --- /dev/null +++ b/tests/nested_def.xsd @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema + xmlns:xs="http://www.w3.org/2001/XMLSchema" + > + + <xs:element name="container" type="containerType" /> + + <xs:complexType name="containerType"> + <xs:sequence> + <xs:element name="item1" type="classAType" /> + <xs:element name="item2" type="classBType" /> + </xs:sequence> + </xs:complexType> + + <xs:element name="classA" type="classAType" /> + <xs:complexType name="classAType"> + <xs:sequence> + <xs:element name="inner"> + <xs:complexType> + <xs:attribute name="attrA1" type="xs:string"/> + <xs:attribute name="attrA2" type="xs:string"/> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + + <xs:element name="classB" type="classBType" /> + <xs:complexType name="classBType"> + <xs:sequence> + <xs:element name="inner"> + <xs:complexType> + <xs:attribute name="attrB1" type="xs:string"/> + <xs:attribute name="attrB2" type="xs:string"/> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> +</xs:schema> diff --git a/tests/nested_def1_out.xml b/tests/nested_def1_out.xml new file mode 100644 index 0000000..692c598 --- /dev/null +++ b/tests/nested_def1_out.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" ?> +<container> + <item1> + <inner attrA1="attrA1value" attrA2="attrA2value"/> + </item1> + <item2> + <inner attrB1="attrB1value" attrB2="attrB2value"/> + </item2> +</container> diff --git a/tests/nested_def1_sub.py b/tests/nested_def1_sub.py new file mode 100644 index 0000000..0bb693d --- /dev/null +++ b/tests/nested_def1_sub.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/nested_def2_sup.py') +# ('-s', 'tests/nested_def2_sub.py') +# ('--super', 'nested_def2_sup') +# +# Command line arguments: +# tests/nested_def.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --member-specs="list" -f -o "tests/nested_def2_sup.py" -s "tests/nested_def2_sub.py" --super="nested_def2_sup" tests/nested_def.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys +from lxml import etree as etree_ + +import nested_def2_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 containerTypeSub(supermod.containerType): + def __init__(self, item1=None, item2=None): + super(containerTypeSub, self).__init__(item1, item2, ) +supermod.containerType.subclass = containerTypeSub +# end class containerTypeSub + + +class classATypeSub(supermod.classAType): + def __init__(self, inner=None): + super(classATypeSub, self).__init__(inner, ) +supermod.classAType.subclass = classATypeSub +# end class classATypeSub + + +class classBTypeSub(supermod.classBType): + def __init__(self, inner=None): + super(classBTypeSub, self).__init__(inner, ) +supermod.classBType.subclass = classBTypeSub +# end class classBTypeSub + + +class inner_001Sub(supermod.inner_001): + def __init__(self, attrA1=None, attrA2=None): + super(inner_001Sub, self).__init__(attrA1, attrA2, ) +supermod.inner_001.subclass = inner_001Sub +# end class inner_001Sub + + +class inner_002Sub(supermod.inner_002): + def __init__(self, attrB1=None, attrB2=None): + super(inner_002Sub, self).__init__(attrB1, attrB2, ) +supermod.inner_002.subclass = inner_002Sub +# end class inner_002Sub + + +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 = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='', + pretty_print=True) + return rootObj + + +def parseEtree(inFilename, silence=False): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) + if not silence: + content = etree_.tostring( + rootElement, pretty_print=True, + xml_declaration=True, encoding="utf-8") + sys.stdout.write(content) + sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + parser = None + doc = parsexml_(StringIO(inString), parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='') + return rootObj + + +def parseLiteral(inFilename, silence=False): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('#from nested_def2_sup import *\n\n') + sys.stdout.write('import nested_def2_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/nested_def1_sup.py b/tests/nested_def1_sup.py new file mode 100644 index 0000000..d49c00e --- /dev/null +++ b/tests/nested_def1_sup.py @@ -0,0 +1,1216 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/nested_def2_sup.py') +# ('-s', 'tests/nested_def2_sub.py') +# ('--super', 'nested_def2_sup') +# +# Command line arguments: +# tests/nested_def.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --member-specs="list" -f -o "tests/nested_def2_sup.py" -s "tests/nested_def2_sub.py" --super="nested_def2_sup" tests/nested_def.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): + if XMLParser_import_library == XMLParser_import_lxml: + msg = '%s (element %s/line %d)' % ( + msg, node.tag, node.sourceline, ) + else: + msg = '%s (element %s)' % (msg, node.tag, ) + raise GDSParseError(msg) + + +class MixedContainer: + # Constants for category: + CategoryNone = 0 + CategoryText = 1 + CategorySimple = 2 + CategoryComplex = 3 + # Constants for content_type: + TypeNone = 0 + TypeText = 1 + TypeString = 2 + TypeInteger = 3 + TypeFloat = 4 + TypeDecimal = 5 + TypeDouble = 6 + TypeBoolean = 7 + TypeBase64 = 8 + def __init__(self, category, content_type, name, value): + self.category = category + self.content_type = content_type + self.name = name + self.value = value + def getCategory(self): + return self.category + def getContenttype(self, content_type): + return self.content_type + def getValue(self): + return self.value + def getName(self): + return self.name + def export(self, outfile, level, name, namespace, pretty_print=True): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + outfile.write(self.value) + elif self.category == MixedContainer.CategorySimple: + self.exportSimple(outfile, level, name) + else: # category == MixedContainer.CategoryComplex + self.value.export(outfile, level, namespace, name, pretty_print) + def exportSimple(self, outfile, level, name): + if self.content_type == MixedContainer.TypeString: + outfile.write('<%s>%s</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeInteger or \ + self.content_type == MixedContainer.TypeBoolean: + outfile.write('<%s>%d</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeFloat or \ + self.content_type == MixedContainer.TypeDecimal: + outfile.write('<%s>%f</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeDouble: + outfile.write('<%s>%g</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeBase64: + outfile.write('<%s>%s</%s>' % ( + self.name, base64.b64encode(self.value), self.name)) + def to_etree(self, element): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + if len(element) > 0: + if element[-1].tail is None: + element[-1].tail = self.value + else: + element[-1].tail += self.value + else: + if element.text is None: + element.text = self.value + else: + element.text += self.value + elif self.category == MixedContainer.CategorySimple: + subelement = etree_.SubElement(element, '%s' % self.name) + subelement.text = self.to_etree_simple() + else: # category == MixedContainer.CategoryComplex + self.value.to_etree(element) + def to_etree_simple(self): + if self.content_type == MixedContainer.TypeString: + text = self.value + elif (self.content_type == MixedContainer.TypeInteger or + self.content_type == MixedContainer.TypeBoolean): + text = '%d' % self.value + elif (self.content_type == MixedContainer.TypeFloat or + self.content_type == MixedContainer.TypeDecimal): + text = '%f' % self.value + elif self.content_type == MixedContainer.TypeDouble: + text = '%g' % self.value + elif self.content_type == MixedContainer.TypeBase64: + text = '%s' % base64.b64encode(self.value) + return text + def exportLiteral(self, outfile, level, name): + if self.category == MixedContainer.CategoryText: + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % ( + self.category, self.content_type, self.name, self.value)) + elif self.category == MixedContainer.CategorySimple: + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % ( + self.category, self.content_type, self.name, self.value)) + else: # category == MixedContainer.CategoryComplex + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s",\n' % ( + self.category, self.content_type, self.name,)) + self.value.exportLiteral(outfile, level + 1) + showIndent(outfile, level) + outfile.write(')\n') + + +class MemberSpec_(object): + def __init__(self, name='', data_type='', container=0): + self.name = name + self.data_type = data_type + self.container = container + def set_name(self, name): self.name = name + def get_name(self): return self.name + def set_data_type(self, data_type): self.data_type = data_type + def get_data_type_chain(self): return self.data_type + def get_data_type(self): + if isinstance(self.data_type, list): + if len(self.data_type) > 0: + return self.data_type[-1] + else: + return 'xs:string' + else: + return self.data_type + def set_container(self, container): self.container = container + def get_container(self): return self.container + + +def _cast(typ, value): + if typ is None or value is None: + return value + return typ(value) + +# +# Data representation classes. +# + + +class containerType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('item1', 'classAType', 0), + MemberSpec_('item2', 'classBType', 0), + ] + subclass = None + superclass = None + def __init__(self, item1=None, item2=None): + self.original_tagname_ = None + self.item1 = item1 + self.item2 = item2 + def factory(*args_, **kwargs_): + if containerType.subclass: + return containerType.subclass(*args_, **kwargs_) + else: + return containerType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_item1(self): return self.item1 + def set_item1(self, item1): self.item1 = item1 + def get_item2(self): return self.item2 + def set_item2(self, item2): self.item2 = item2 + def hasContent_(self): + if ( + self.item1 is not None or + self.item2 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='containerType', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='containerType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='containerType', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='containerType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='containerType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.item1 is not None: + self.item1.export(outfile, level, namespace_, name_='item1', pretty_print=pretty_print) + if self.item2 is not None: + self.item2.export(outfile, level, namespace_, name_='item2', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='containerType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.item1 is not None: + showIndent(outfile, level) + outfile.write('item1=model_.classAType(\n') + self.item1.exportLiteral(outfile, level, name_='item1') + showIndent(outfile, level) + outfile.write('),\n') + if self.item2 is not None: + showIndent(outfile, level) + outfile.write('item2=model_.classBType(\n') + self.item2.exportLiteral(outfile, level, name_='item2') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'item1': + obj_ = classAType.factory() + obj_.build(child_) + self.item1 = obj_ + obj_.original_tagname_ = 'item1' + elif nodeName_ == 'item2': + obj_ = classBType.factory() + obj_.build(child_) + self.item2 = obj_ + obj_.original_tagname_ = 'item2' +# end class containerType + + +class classAType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('inner', 'inner_001', 0), + ] + subclass = None + superclass = None + def __init__(self, inner=None): + self.original_tagname_ = None + self.inner = inner + def factory(*args_, **kwargs_): + if classAType.subclass: + return classAType.subclass(*args_, **kwargs_) + else: + return classAType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_inner(self): return self.inner + def set_inner(self, inner): self.inner = inner + def hasContent_(self): + if ( + self.inner is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='classAType', 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_='classAType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='classAType', 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_='classAType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='classAType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.inner is not None: + self.inner.export(outfile, level, namespace_, name_='inner', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='classAType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.inner is not None: + showIndent(outfile, level) + outfile.write('inner=model_.inner_001(\n') + self.inner.exportLiteral(outfile, level, name_='inner') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'inner': + obj_ = inner_001.factory() + obj_.build(child_) + self.inner = obj_ + obj_.original_tagname_ = 'inner' +# end class classAType + + +class classBType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('inner', 'inner_002', 0), + ] + subclass = None + superclass = None + def __init__(self, inner=None): + self.original_tagname_ = None + self.inner = inner + def factory(*args_, **kwargs_): + if classBType.subclass: + return classBType.subclass(*args_, **kwargs_) + else: + return classBType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_inner(self): return self.inner + def set_inner(self, inner): self.inner = inner + def hasContent_(self): + if ( + self.inner is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='classBType', 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_='classBType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='classBType', 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_='classBType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='classBType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.inner is not None: + self.inner.export(outfile, level, namespace_, name_='inner', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='classBType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.inner is not None: + showIndent(outfile, level) + outfile.write('inner=model_.inner_002(\n') + self.inner.exportLiteral(outfile, level, name_='inner') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'inner': + obj_ = inner_002.factory() + obj_.build(child_) + self.inner = obj_ + obj_.original_tagname_ = 'inner' +# end class classBType + + +class inner_001(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('attrA1', 'xs:string', 0), + MemberSpec_('attrA2', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, attrA1=None, attrA2=None): + self.original_tagname_ = None + self.attrA1 = _cast(None, attrA1) + self.attrA2 = _cast(None, attrA2) + def factory(*args_, **kwargs_): + if inner_001.subclass: + return inner_001.subclass(*args_, **kwargs_) + else: + return inner_001(*args_, **kwargs_) + factory = staticmethod(factory) + def get_attrA1(self): return self.attrA1 + def set_attrA1(self, attrA1): self.attrA1 = attrA1 + def get_attrA2(self): return self.attrA2 + def set_attrA2(self, attrA2): self.attrA2 = attrA2 + def hasContent_(self): + if ( + + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='inner_001', 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_='inner_001') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='inner_001', pretty_print=pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='inner_001'): + if self.attrA1 is not None and 'attrA1' not in already_processed: + already_processed.add('attrA1') + outfile.write(' attrA1=%s' % (self.gds_format_string(quote_attrib(self.attrA1).encode(ExternalEncoding), input_name='attrA1'), )) + if self.attrA2 is not None and 'attrA2' not in already_processed: + already_processed.add('attrA2') + outfile.write(' attrA2=%s' % (self.gds_format_string(quote_attrib(self.attrA2).encode(ExternalEncoding), input_name='attrA2'), )) + def exportChildren(self, outfile, level, namespace_='', name_='inner_001', fromsubclass_=False, pretty_print=True): + pass + def exportLiteral(self, outfile, level, name_='inner_001'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + if self.attrA1 is not None and 'attrA1' not in already_processed: + already_processed.add('attrA1') + showIndent(outfile, level) + outfile.write('attrA1="%s",\n' % (self.attrA1,)) + if self.attrA2 is not None and 'attrA2' not in already_processed: + already_processed.add('attrA2') + showIndent(outfile, level) + outfile.write('attrA2="%s",\n' % (self.attrA2,)) + def exportLiteralChildren(self, outfile, level, name_): + pass + 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): + value = find_attr_value_('attrA1', node) + if value is not None and 'attrA1' not in already_processed: + already_processed.add('attrA1') + self.attrA1 = value + value = find_attr_value_('attrA2', node) + if value is not None and 'attrA2' not in already_processed: + already_processed.add('attrA2') + self.attrA2 = value + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + pass +# end class inner_001 + + +class inner_002(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('attrB1', 'xs:string', 0), + MemberSpec_('attrB2', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, attrB1=None, attrB2=None): + self.original_tagname_ = None + self.attrB1 = _cast(None, attrB1) + self.attrB2 = _cast(None, attrB2) + def factory(*args_, **kwargs_): + if inner_002.subclass: + return inner_002.subclass(*args_, **kwargs_) + else: + return inner_002(*args_, **kwargs_) + factory = staticmethod(factory) + def get_attrB1(self): return self.attrB1 + def set_attrB1(self, attrB1): self.attrB1 = attrB1 + def get_attrB2(self): return self.attrB2 + def set_attrB2(self, attrB2): self.attrB2 = attrB2 + def hasContent_(self): + if ( + + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='inner_002', 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_='inner_002') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='inner_002', pretty_print=pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='inner_002'): + if self.attrB1 is not None and 'attrB1' not in already_processed: + already_processed.add('attrB1') + outfile.write(' attrB1=%s' % (self.gds_format_string(quote_attrib(self.attrB1).encode(ExternalEncoding), input_name='attrB1'), )) + if self.attrB2 is not None and 'attrB2' not in already_processed: + already_processed.add('attrB2') + outfile.write(' attrB2=%s' % (self.gds_format_string(quote_attrib(self.attrB2).encode(ExternalEncoding), input_name='attrB2'), )) + def exportChildren(self, outfile, level, namespace_='', name_='inner_002', fromsubclass_=False, pretty_print=True): + pass + def exportLiteral(self, outfile, level, name_='inner_002'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + if self.attrB1 is not None and 'attrB1' not in already_processed: + already_processed.add('attrB1') + showIndent(outfile, level) + outfile.write('attrB1="%s",\n' % (self.attrB1,)) + if self.attrB2 is not None and 'attrB2' not in already_processed: + already_processed.add('attrB2') + showIndent(outfile, level) + outfile.write('attrB2="%s",\n' % (self.attrB2,)) + def exportLiteralChildren(self, outfile, level, name_): + pass + 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): + value = find_attr_value_('attrB1', node) + if value is not None and 'attrB1' not in already_processed: + already_processed.add('attrB1') + self.attrB1 = value + value = find_attr_value_('attrB2', node) + if value is not None and 'attrB2' not in already_processed: + already_processed.add('attrB2') + self.attrB2 = value + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + pass +# end class inner_002 + + +GDSClassesMapping = { + 'container': containerType, + 'item2': classBType, + 'item1': classAType, + 'classB': classBType, + 'classA': classAType, + 'inner': inner_002, +} + + +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 = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='', + pretty_print=True) + return rootObj + + +def parseEtree(inFileName, silence=False): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) + if not silence: + content = etree_.tostring( + rootElement, pretty_print=True, + xml_declaration=True, encoding="utf-8") + sys.stdout.write(content) + sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + parser = None + doc = parsexml_(StringIO(inString), parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='') + return rootObj + + +def parseLiteral(inFileName, silence=False): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('#from nested_def2_sup import *\n\n') + sys.stdout.write('import nested_def2_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__ = [ + "classAType", + "classBType", + "containerType", + "inner_001", + "inner_002" +] diff --git a/tests/nested_def2_out.xml b/tests/nested_def2_out.xml new file mode 100644 index 0000000..692c598 --- /dev/null +++ b/tests/nested_def2_out.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" ?> +<container> + <item1> + <inner attrA1="attrA1value" attrA2="attrA2value"/> + </item1> + <item2> + <inner attrB1="attrB1value" attrB2="attrB2value"/> + </item2> +</container> diff --git a/tests/nested_def2_sub.py b/tests/nested_def2_sub.py new file mode 100644 index 0000000..0bb693d --- /dev/null +++ b/tests/nested_def2_sub.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/nested_def2_sup.py') +# ('-s', 'tests/nested_def2_sub.py') +# ('--super', 'nested_def2_sup') +# +# Command line arguments: +# tests/nested_def.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --member-specs="list" -f -o "tests/nested_def2_sup.py" -s "tests/nested_def2_sub.py" --super="nested_def2_sup" tests/nested_def.xsd +# +# Current working directory (os.getcwd()): +# generateds +# + +import sys +from lxml import etree as etree_ + +import nested_def2_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 containerTypeSub(supermod.containerType): + def __init__(self, item1=None, item2=None): + super(containerTypeSub, self).__init__(item1, item2, ) +supermod.containerType.subclass = containerTypeSub +# end class containerTypeSub + + +class classATypeSub(supermod.classAType): + def __init__(self, inner=None): + super(classATypeSub, self).__init__(inner, ) +supermod.classAType.subclass = classATypeSub +# end class classATypeSub + + +class classBTypeSub(supermod.classBType): + def __init__(self, inner=None): + super(classBTypeSub, self).__init__(inner, ) +supermod.classBType.subclass = classBTypeSub +# end class classBTypeSub + + +class inner_001Sub(supermod.inner_001): + def __init__(self, attrA1=None, attrA2=None): + super(inner_001Sub, self).__init__(attrA1, attrA2, ) +supermod.inner_001.subclass = inner_001Sub +# end class inner_001Sub + + +class inner_002Sub(supermod.inner_002): + def __init__(self, attrB1=None, attrB2=None): + super(inner_002Sub, self).__init__(attrB1, attrB2, ) +supermod.inner_002.subclass = inner_002Sub +# end class inner_002Sub + + +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 = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='', + pretty_print=True) + return rootObj + + +def parseEtree(inFilename, silence=False): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) + if not silence: + content = etree_.tostring( + rootElement, pretty_print=True, + xml_declaration=True, encoding="utf-8") + sys.stdout.write(content) + sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + parser = None + doc = parsexml_(StringIO(inString), parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='') + return rootObj + + +def parseLiteral(inFilename, silence=False): + parser = None + doc = parsexml_(inFilename, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = supermod.containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('#from nested_def2_sup import *\n\n') + sys.stdout.write('import nested_def2_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/nested_def2_sup.py b/tests/nested_def2_sup.py new file mode 100644 index 0000000..d49c00e --- /dev/null +++ b/tests/nested_def2_sup.py @@ -0,0 +1,1216 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# Generated by generateDS.py. +# +# Command line options: +# ('--no-dates', '') +# ('--no-versions', '') +# ('--member-specs', 'list') +# ('-f', '') +# ('-o', 'tests/nested_def2_sup.py') +# ('-s', 'tests/nested_def2_sub.py') +# ('--super', 'nested_def2_sup') +# +# Command line arguments: +# tests/nested_def.xsd +# +# Command line: +# generateDS.py --no-dates --no-versions --member-specs="list" -f -o "tests/nested_def2_sup.py" -s "tests/nested_def2_sub.py" --super="nested_def2_sup" tests/nested_def.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): + if XMLParser_import_library == XMLParser_import_lxml: + msg = '%s (element %s/line %d)' % ( + msg, node.tag, node.sourceline, ) + else: + msg = '%s (element %s)' % (msg, node.tag, ) + raise GDSParseError(msg) + + +class MixedContainer: + # Constants for category: + CategoryNone = 0 + CategoryText = 1 + CategorySimple = 2 + CategoryComplex = 3 + # Constants for content_type: + TypeNone = 0 + TypeText = 1 + TypeString = 2 + TypeInteger = 3 + TypeFloat = 4 + TypeDecimal = 5 + TypeDouble = 6 + TypeBoolean = 7 + TypeBase64 = 8 + def __init__(self, category, content_type, name, value): + self.category = category + self.content_type = content_type + self.name = name + self.value = value + def getCategory(self): + return self.category + def getContenttype(self, content_type): + return self.content_type + def getValue(self): + return self.value + def getName(self): + return self.name + def export(self, outfile, level, name, namespace, pretty_print=True): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + outfile.write(self.value) + elif self.category == MixedContainer.CategorySimple: + self.exportSimple(outfile, level, name) + else: # category == MixedContainer.CategoryComplex + self.value.export(outfile, level, namespace, name, pretty_print) + def exportSimple(self, outfile, level, name): + if self.content_type == MixedContainer.TypeString: + outfile.write('<%s>%s</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeInteger or \ + self.content_type == MixedContainer.TypeBoolean: + outfile.write('<%s>%d</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeFloat or \ + self.content_type == MixedContainer.TypeDecimal: + outfile.write('<%s>%f</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeDouble: + outfile.write('<%s>%g</%s>' % ( + self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeBase64: + outfile.write('<%s>%s</%s>' % ( + self.name, base64.b64encode(self.value), self.name)) + def to_etree(self, element): + if self.category == MixedContainer.CategoryText: + # Prevent exporting empty content as empty lines. + if self.value.strip(): + if len(element) > 0: + if element[-1].tail is None: + element[-1].tail = self.value + else: + element[-1].tail += self.value + else: + if element.text is None: + element.text = self.value + else: + element.text += self.value + elif self.category == MixedContainer.CategorySimple: + subelement = etree_.SubElement(element, '%s' % self.name) + subelement.text = self.to_etree_simple() + else: # category == MixedContainer.CategoryComplex + self.value.to_etree(element) + def to_etree_simple(self): + if self.content_type == MixedContainer.TypeString: + text = self.value + elif (self.content_type == MixedContainer.TypeInteger or + self.content_type == MixedContainer.TypeBoolean): + text = '%d' % self.value + elif (self.content_type == MixedContainer.TypeFloat or + self.content_type == MixedContainer.TypeDecimal): + text = '%f' % self.value + elif self.content_type == MixedContainer.TypeDouble: + text = '%g' % self.value + elif self.content_type == MixedContainer.TypeBase64: + text = '%s' % base64.b64encode(self.value) + return text + def exportLiteral(self, outfile, level, name): + if self.category == MixedContainer.CategoryText: + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % ( + self.category, self.content_type, self.name, self.value)) + elif self.category == MixedContainer.CategorySimple: + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % ( + self.category, self.content_type, self.name, self.value)) + else: # category == MixedContainer.CategoryComplex + showIndent(outfile, level) + outfile.write( + 'model_.MixedContainer(%d, %d, "%s",\n' % ( + self.category, self.content_type, self.name,)) + self.value.exportLiteral(outfile, level + 1) + showIndent(outfile, level) + outfile.write(')\n') + + +class MemberSpec_(object): + def __init__(self, name='', data_type='', container=0): + self.name = name + self.data_type = data_type + self.container = container + def set_name(self, name): self.name = name + def get_name(self): return self.name + def set_data_type(self, data_type): self.data_type = data_type + def get_data_type_chain(self): return self.data_type + def get_data_type(self): + if isinstance(self.data_type, list): + if len(self.data_type) > 0: + return self.data_type[-1] + else: + return 'xs:string' + else: + return self.data_type + def set_container(self, container): self.container = container + def get_container(self): return self.container + + +def _cast(typ, value): + if typ is None or value is None: + return value + return typ(value) + +# +# Data representation classes. +# + + +class containerType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('item1', 'classAType', 0), + MemberSpec_('item2', 'classBType', 0), + ] + subclass = None + superclass = None + def __init__(self, item1=None, item2=None): + self.original_tagname_ = None + self.item1 = item1 + self.item2 = item2 + def factory(*args_, **kwargs_): + if containerType.subclass: + return containerType.subclass(*args_, **kwargs_) + else: + return containerType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_item1(self): return self.item1 + def set_item1(self, item1): self.item1 = item1 + def get_item2(self): return self.item2 + def set_item2(self, item2): self.item2 = item2 + def hasContent_(self): + if ( + self.item1 is not None or + self.item2 is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='containerType', namespacedef_='', pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.original_tagname_ is not None: + name_ = self.original_tagname_ + showIndent(outfile, level, pretty_print) + outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', )) + already_processed = set() + self.exportAttributes(outfile, level, already_processed, namespace_, name_='containerType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='containerType', pretty_print=pretty_print) + showIndent(outfile, level, pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='containerType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='containerType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.item1 is not None: + self.item1.export(outfile, level, namespace_, name_='item1', pretty_print=pretty_print) + if self.item2 is not None: + self.item2.export(outfile, level, namespace_, name_='item2', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='containerType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.item1 is not None: + showIndent(outfile, level) + outfile.write('item1=model_.classAType(\n') + self.item1.exportLiteral(outfile, level, name_='item1') + showIndent(outfile, level) + outfile.write('),\n') + if self.item2 is not None: + showIndent(outfile, level) + outfile.write('item2=model_.classBType(\n') + self.item2.exportLiteral(outfile, level, name_='item2') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'item1': + obj_ = classAType.factory() + obj_.build(child_) + self.item1 = obj_ + obj_.original_tagname_ = 'item1' + elif nodeName_ == 'item2': + obj_ = classBType.factory() + obj_.build(child_) + self.item2 = obj_ + obj_.original_tagname_ = 'item2' +# end class containerType + + +class classAType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('inner', 'inner_001', 0), + ] + subclass = None + superclass = None + def __init__(self, inner=None): + self.original_tagname_ = None + self.inner = inner + def factory(*args_, **kwargs_): + if classAType.subclass: + return classAType.subclass(*args_, **kwargs_) + else: + return classAType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_inner(self): return self.inner + def set_inner(self, inner): self.inner = inner + def hasContent_(self): + if ( + self.inner is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='classAType', 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_='classAType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='classAType', 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_='classAType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='classAType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.inner is not None: + self.inner.export(outfile, level, namespace_, name_='inner', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='classAType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.inner is not None: + showIndent(outfile, level) + outfile.write('inner=model_.inner_001(\n') + self.inner.exportLiteral(outfile, level, name_='inner') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'inner': + obj_ = inner_001.factory() + obj_.build(child_) + self.inner = obj_ + obj_.original_tagname_ = 'inner' +# end class classAType + + +class classBType(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('inner', 'inner_002', 0), + ] + subclass = None + superclass = None + def __init__(self, inner=None): + self.original_tagname_ = None + self.inner = inner + def factory(*args_, **kwargs_): + if classBType.subclass: + return classBType.subclass(*args_, **kwargs_) + else: + return classBType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_inner(self): return self.inner + def set_inner(self, inner): self.inner = inner + def hasContent_(self): + if ( + self.inner is not None + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='classBType', 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_='classBType') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='classBType', 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_='classBType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='classBType', fromsubclass_=False, pretty_print=True): + if pretty_print: + eol_ = '\n' + else: + eol_ = '' + if self.inner is not None: + self.inner.export(outfile, level, namespace_, name_='inner', pretty_print=pretty_print) + def exportLiteral(self, outfile, level, name_='classBType'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.inner is not None: + showIndent(outfile, level) + outfile.write('inner=model_.inner_002(\n') + self.inner.exportLiteral(outfile, level, name_='inner') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node): + already_processed = set() + self.buildAttributes(node, node.attrib, already_processed) + for child in node: + nodeName_ = Tag_pattern_.match(child.tag).groups()[-1] + self.buildChildren(child, node, nodeName_) + return self + def buildAttributes(self, node, attrs, already_processed): + pass + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + if nodeName_ == 'inner': + obj_ = inner_002.factory() + obj_.build(child_) + self.inner = obj_ + obj_.original_tagname_ = 'inner' +# end class classBType + + +class inner_001(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('attrA1', 'xs:string', 0), + MemberSpec_('attrA2', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, attrA1=None, attrA2=None): + self.original_tagname_ = None + self.attrA1 = _cast(None, attrA1) + self.attrA2 = _cast(None, attrA2) + def factory(*args_, **kwargs_): + if inner_001.subclass: + return inner_001.subclass(*args_, **kwargs_) + else: + return inner_001(*args_, **kwargs_) + factory = staticmethod(factory) + def get_attrA1(self): return self.attrA1 + def set_attrA1(self, attrA1): self.attrA1 = attrA1 + def get_attrA2(self): return self.attrA2 + def set_attrA2(self, attrA2): self.attrA2 = attrA2 + def hasContent_(self): + if ( + + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='inner_001', 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_='inner_001') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='inner_001', pretty_print=pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='inner_001'): + if self.attrA1 is not None and 'attrA1' not in already_processed: + already_processed.add('attrA1') + outfile.write(' attrA1=%s' % (self.gds_format_string(quote_attrib(self.attrA1).encode(ExternalEncoding), input_name='attrA1'), )) + if self.attrA2 is not None and 'attrA2' not in already_processed: + already_processed.add('attrA2') + outfile.write(' attrA2=%s' % (self.gds_format_string(quote_attrib(self.attrA2).encode(ExternalEncoding), input_name='attrA2'), )) + def exportChildren(self, outfile, level, namespace_='', name_='inner_001', fromsubclass_=False, pretty_print=True): + pass + def exportLiteral(self, outfile, level, name_='inner_001'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + if self.attrA1 is not None and 'attrA1' not in already_processed: + already_processed.add('attrA1') + showIndent(outfile, level) + outfile.write('attrA1="%s",\n' % (self.attrA1,)) + if self.attrA2 is not None and 'attrA2' not in already_processed: + already_processed.add('attrA2') + showIndent(outfile, level) + outfile.write('attrA2="%s",\n' % (self.attrA2,)) + def exportLiteralChildren(self, outfile, level, name_): + pass + 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): + value = find_attr_value_('attrA1', node) + if value is not None and 'attrA1' not in already_processed: + already_processed.add('attrA1') + self.attrA1 = value + value = find_attr_value_('attrA2', node) + if value is not None and 'attrA2' not in already_processed: + already_processed.add('attrA2') + self.attrA2 = value + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + pass +# end class inner_001 + + +class inner_002(GeneratedsSuper): + member_data_items_ = [ + MemberSpec_('attrB1', 'xs:string', 0), + MemberSpec_('attrB2', 'xs:string', 0), + ] + subclass = None + superclass = None + def __init__(self, attrB1=None, attrB2=None): + self.original_tagname_ = None + self.attrB1 = _cast(None, attrB1) + self.attrB2 = _cast(None, attrB2) + def factory(*args_, **kwargs_): + if inner_002.subclass: + return inner_002.subclass(*args_, **kwargs_) + else: + return inner_002(*args_, **kwargs_) + factory = staticmethod(factory) + def get_attrB1(self): return self.attrB1 + def set_attrB1(self, attrB1): self.attrB1 = attrB1 + def get_attrB2(self): return self.attrB2 + def set_attrB2(self, attrB2): self.attrB2 = attrB2 + def hasContent_(self): + if ( + + ): + return True + else: + return False + def export(self, outfile, level, namespace_='', name_='inner_002', 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_='inner_002') + if self.hasContent_(): + outfile.write('>%s' % (eol_, )) + self.exportChildren(outfile, level + 1, namespace_='', name_='inner_002', pretty_print=pretty_print) + outfile.write('</%s%s>%s' % (namespace_, name_, eol_)) + else: + outfile.write('/>%s' % (eol_, )) + def exportAttributes(self, outfile, level, already_processed, namespace_='', name_='inner_002'): + if self.attrB1 is not None and 'attrB1' not in already_processed: + already_processed.add('attrB1') + outfile.write(' attrB1=%s' % (self.gds_format_string(quote_attrib(self.attrB1).encode(ExternalEncoding), input_name='attrB1'), )) + if self.attrB2 is not None and 'attrB2' not in already_processed: + already_processed.add('attrB2') + outfile.write(' attrB2=%s' % (self.gds_format_string(quote_attrib(self.attrB2).encode(ExternalEncoding), input_name='attrB2'), )) + def exportChildren(self, outfile, level, namespace_='', name_='inner_002', fromsubclass_=False, pretty_print=True): + pass + def exportLiteral(self, outfile, level, name_='inner_002'): + level += 1 + already_processed = set() + self.exportLiteralAttributes(outfile, level, already_processed, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, already_processed, name_): + if self.attrB1 is not None and 'attrB1' not in already_processed: + already_processed.add('attrB1') + showIndent(outfile, level) + outfile.write('attrB1="%s",\n' % (self.attrB1,)) + if self.attrB2 is not None and 'attrB2' not in already_processed: + already_processed.add('attrB2') + showIndent(outfile, level) + outfile.write('attrB2="%s",\n' % (self.attrB2,)) + def exportLiteralChildren(self, outfile, level, name_): + pass + 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): + value = find_attr_value_('attrB1', node) + if value is not None and 'attrB1' not in already_processed: + already_processed.add('attrB1') + self.attrB1 = value + value = find_attr_value_('attrB2', node) + if value is not None and 'attrB2' not in already_processed: + already_processed.add('attrB2') + self.attrB2 = value + def buildChildren(self, child_, node, nodeName_, fromsubclass_=False): + pass +# end class inner_002 + + +GDSClassesMapping = { + 'container': containerType, + 'item2': classBType, + 'item1': classAType, + 'classB': classBType, + 'classA': classAType, + 'inner': inner_002, +} + + +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 = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='', + pretty_print=True) + return rootObj + + +def parseEtree(inFileName, silence=False): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + mapping = {} + rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping) + reverse_mapping = rootObj.gds_reverse_node_mapping(mapping) + if not silence: + content = etree_.tostring( + rootElement, pretty_print=True, + xml_declaration=True, encoding="utf-8") + sys.stdout.write(content) + sys.stdout.write('\n') + return rootObj, rootElement, mapping, reverse_mapping + + +def parseString(inString, silence=False): + from StringIO import StringIO + parser = None + doc = parsexml_(StringIO(inString), parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('<?xml version="1.0" ?>\n') + rootObj.export( + sys.stdout, 0, name_=rootTag, + namespacedef_='') + return rootObj + + +def parseLiteral(inFileName, silence=False): + parser = None + doc = parsexml_(inFileName, parser) + rootNode = doc.getroot() + rootTag, rootClass = get_root_tag(rootNode) + if rootClass is None: + rootTag = 'containerType' + rootClass = containerType + rootObj = rootClass.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + if not silence: + sys.stdout.write('#from nested_def2_sup import *\n\n') + sys.stdout.write('import nested_def2_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__ = [ + "classAType", + "classBType", + "containerType", + "inner_001", + "inner_002" +] diff --git a/tests/test.py b/tests/test.py index f242360..d94418f 100755 --- a/tests/test.py +++ b/tests/test.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import sys +import os import subprocess import getopt import unittest @@ -8,11 +9,12 @@ from lxml import etree class GenTest(unittest.TestCase): - def execute(self, cmd, cwd=None): + def execute(self, cmd, cwd=None, env=None): p = subprocess.Popen( cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - shell=True) + shell=True, + env=env) stdout, stderr = p.communicate() return stdout, stderr @@ -675,6 +677,37 @@ class GenTest(unittest.TestCase): result, err = self.execute(cmd) self.check_result(result, err, ()) + def test_030_nested_def(self): + cmdTempl = ( + 'python generateDS.py --no-dates --no-versions ' + '--member-specs=list -f ' + '-o tests/%s2_sup.py -s tests/%s2_sub.py ' + '--super=%s2_sup ' + 'tests/%s.xsd' + ) + t_ = 'nested_def' + cmd = cmdTempl % (t_, t_, t_, t_, ) + env = os.environ + directory = os.getcwd() + env['PYTHONPATH'] = directory + result, stderr = self.execute(cmd, cwd='..', env=env) + if stderr: + sys.stderr.write(stderr) + sys.stderr.write('\n') + raise RuntimeError('error while generating nested_def modules') + cmd = 'diff %s1_sup.py %s2_sup.py' % (t_, t_, ) + result, err = self.execute(cmd) + self.check_result(result, err, ('sys.stdout.write',)) + cmd = 'diff %s1_sub.py %s2_sub.py' % (t_, t_, ) + result, err = self.execute(cmd) + self.check_result(result, err, ()) + cmdTempl = 'python tests/%s2_sup.py tests/%s.xml > tests/%s2_out.xml' + cmd = cmdTempl % (t_, t_, t_, ) + result, _ = self.execute(cmd, cwd='..') + cmd = 'diff %s1_out.xml %s2_out.xml' % (t_, t_, ) + result, err = self.execute(cmd) + 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 adf2b8b..03b01e7 100644 --- a/tutorial/generateds_tutorial.txt +++ b/tutorial/generateds_tutorial.txt @@ -11,7 +11,7 @@ generateDS -- Introduction and Tutorial .. version -:revision: 2.15b +:revision: 2.16a .. version -- GitLab