aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ee/__main__.py9
-rw-r--r--src/ee/bom/part_type_uris.py5
-rw-r--r--src/ee/kicad/make_bom.py151
-rw-r--r--src/ee/tools/kicad_make_bom.py24
-rw-r--r--src/ee/xml/__init__.py0
-rw-r--r--src/ee/xml/bomFile.py1326
-rw-r--r--src/ee/xml/catalogFile.py1103
7 files changed, 2600 insertions, 18 deletions
diff --git a/src/ee/__main__.py b/src/ee/__main__.py
index 6a7517f..a387b1d 100644
--- a/src/ee/__main__.py
+++ b/src/ee/__main__.py
@@ -1,9 +1,11 @@
-from functools import total_ordering
-import ee.tools
import importlib
import logging
import pkgutil
import sys
+import os
+from functools import total_ordering
+
+import ee.tools
def eprint(*args, **kwargs):
@@ -50,6 +52,9 @@ def main():
name = sys.argv[1]
del sys.argv[1]
+ if os.path.isdir("py"):
+ sys.path.append("py")
+
for t in tools:
if t.name != name:
continue
diff --git a/src/ee/bom/part_type_uris.py b/src/ee/bom/part_type_uris.py
new file mode 100644
index 0000000..b7f5e88
--- /dev/null
+++ b/src/ee/bom/part_type_uris.py
@@ -0,0 +1,5 @@
+CAPACITOR = "http://purl.org/ee/part-type#capacitor"
+RESISTOR = "http://purl.org/ee/part-type#resistor"
+DIODE = "http://purl.org/ee/part-type#diode"
+INDUCTOR = "http://purl.org/ee/part-type#inductor"
+CRYSTAL = "http://purl.org/ee/part-type#inductor"
diff --git a/src/ee/kicad/make_bom.py b/src/ee/kicad/make_bom.py
new file mode 100644
index 0000000..3fa102f
--- /dev/null
+++ b/src/ee/kicad/make_bom.py
@@ -0,0 +1,151 @@
+import sys
+from typing import Optional, List, Callable, Mapping
+from xml.dom import minidom
+from xml.etree import ElementTree
+
+from ee import EeException
+from ee.kicad.model import Component
+from ee.kicad.read_schematic import read_schematics
+from ee.kicad.to_bom import to_bom, to_bom_xml
+from ee.tools import mk_parents
+from ee.xml import bomFile
+from ee.bom import part_type_uris
+
+__all__ = [
+ "StrategyCallable",
+ "MakeBomStrategy",
+ "apply_strategies",
+ "mpn_strategy",
+ "part_type_strategy",
+ "dpn_strategy_factory",
+ "make_bom",
+]
+
+StrategyCallable = Callable[[Component, bomFile.Part], Optional[bomFile.Part]]
+
+
+def apply_strategies(c: Component, part: bomFile.Part, strategies: List[StrategyCallable]):
+ for strategy in strategies:
+ part = strategy(c, part)
+
+ if part is None:
+ return
+
+ if not isinstance(part, bomFile.Part):
+ raise EeException("Values returned from strategy must be a bomFile.Part, got {}".format(type(part)))
+
+ return part
+
+
+def part_type_strategy(component: Component, part: bomFile.Part) -> bomFile.Part:
+ fp = component.footprint
+ if fp is None:
+ return part
+
+ lib, part_name = fp.split(":")
+
+ if lib == "Capacitor_SMD":
+ part.part_typeProp = part_type_uris.CAPACITOR
+ elif lib == "Resistor_SMD":
+ part.part_typeProp = part_type_uris.RESISTOR
+ elif lib == "Diode_SMD":
+ part.part_typeProp = part_type_uris.DIODE
+ elif lib == "Inductor_SMD":
+ part.part_typeProp = part_type_uris.INDUCTOR
+ elif lib == "Crystal":
+ part.part_typeProp = part_type_uris.CRYSTAL
+
+ return part
+
+
+def mpn_strategy(component: Component, part: bomFile.Part) -> bomFile.Part:
+ mpn = component.get_field("mpn")
+ if mpn is not None:
+ pn = bomFile.PartNumber(value=mpn.value)
+ part.part_numbersProp.add_part_number(pn)
+
+ return part
+
+
+def dpn_strategy_factory(dpn_mappings: Mapping[str, str]) -> StrategyCallable:
+ def dpn_strategy(component: Component, part: bomFile.Part) -> bomFile.Part:
+ for field_name, distributor in dpn_mappings:
+ s = component.get_field(field_name)
+ if s is not None:
+ pn = bomFile.PartNumber(value=s, distributor=distributor)
+ part.part_numbersProp.add_part_number(pn)
+
+ return part
+
+ return dpn_strategy
+
+
+class MakeBomStrategy():
+ def __init__(self, dpn_mappings: Mapping[str, str] = None):
+ self.dpn_mappings = dpn_mappings or {}
+ self.default_strategies = [
+ mpn_strategy,
+ part_type_strategy,
+ dpn_strategy_factory(self.dpn_mappings),
+ ]
+
+ def process_part(self, component: Component, part: bomFile.Part):
+ return self.default_process_part(component, part)
+
+ def default_process_part(self, component: Component, part: bomFile.Part):
+ return apply_strategies(component, part, self.default_strategies)
+
+
+def work(sch, out_file, strategy: MakeBomStrategy, new_mode, pretty):
+ if not new_mode:
+ bom = to_bom_xml(sch)
+ xml = ElementTree.tostring(bom, encoding="unicode")
+
+ if pretty:
+ xml = minidom.parseString(xml).toprettyxml(indent=" ")
+
+ print(xml, file=out_file)
+ else:
+ file = bomFile.BomFile()
+
+ parts = bomFile.PartList()
+ file.partsProp = parts
+
+ components = to_bom(sch)
+ for c in components:
+ part = bomFile.Part(id=c.ref)
+ part.schema_reference = c.ref
+ part.part_numbersProp = bomFile.PartNumberList()
+
+ part = strategy.process_part(c, part)
+
+ if len(part.part_numbersProp.get_part_number()) == 0:
+ part.part_numbersProp = None
+
+ if part is not None:
+ parts.add_part(part)
+
+ file.export(out_file, 0, name_="bom-file", namespacedef_="xmlns='http://purl.org/ee/bom-file'",
+ pretty_print=pretty)
+
+
+def make_bom(sch_file: str, out_file: Optional[str], strategy_name: str, new_mode: bool, pretty: bool):
+ sch = read_schematics(sch_file)
+
+ import pydoc
+ make_bom_strategy_factory = pydoc.locate(strategy_name)
+
+ if not callable(make_bom_strategy_factory):
+ raise EeException("Not a callable: {}, is a {}".format(strategy_name, type(make_bom_strategy_factory)))
+
+ make_bom_strategy = make_bom_strategy_factory() # type: MakeBomStrategy
+
+ if not isinstance(make_bom_strategy, MakeBomStrategy):
+ raise EeException("Not a MakeBomStrategy: {}, is a {}".format(strategy_name, type(make_bom_strategy)))
+
+ if out_file:
+ mk_parents(out_file)
+ with open(out_file, "w") as f:
+ work(sch, f, make_bom_strategy, new_mode, pretty)
+ else:
+ work(sch, sys.stdout, make_bom_strategy, new_mode, pretty)
diff --git a/src/ee/tools/kicad_make_bom.py b/src/ee/tools/kicad_make_bom.py
index 2600968..769ea0d 100644
--- a/src/ee/tools/kicad_make_bom.py
+++ b/src/ee/tools/kicad_make_bom.py
@@ -1,8 +1,6 @@
import argparse
-import ee.kicad as kicad
-from ee.tools import mk_parents
-from xml.etree import ElementTree
-from xml.dom import minidom
+
+from ee.kicad.make_bom import make_bom
pretty = True # we always pretty print the XML
@@ -17,19 +15,13 @@ parser.add_argument("--out",
metavar="FILE",
help="The output file")
-args = parser.parse_args()
+parser.add_argument("--strategy",
+ metavar="FUNC")
-sch = kicad.read_schematics(args.sch)
+args = parser.parse_args()
-bom = kicad.to_bom_xml(sch)
-xml = ElementTree.tostring(bom, encoding='unicode')
+new_mode = True
-if pretty:
- xml = minidom.parseString(xml).toprettyxml(indent=" ")
+strategy = args.strategy if args.strategy else "ee.kicad.make_bom.MakeBomStrategy"
-if args.out:
- mk_parents(args.out)
- with open(args.out, "w") as f:
- f.write(xml)
-else:
- print(xml)
+make_bom(args.sch, args.out, strategy, new_mode, pretty)
diff --git a/src/ee/xml/__init__.py b/src/ee/xml/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ee/xml/__init__.py
diff --git a/src/ee/xml/bomFile.py b/src/ee/xml/bomFile.py
new file mode 100644
index 0000000..d1967a6
--- /dev/null
+++ b/src/ee/xml/bomFile.py
@@ -0,0 +1,1326 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#
+# Generated Thu Feb 21 08:05:29 2019 by generateDS.py version 2.30.11.
+# Python 3.7.2+ (default, Feb 2 2019, 14:31:48) [GCC 8.2.0]
+#
+# Command line options:
+# ('-f', '')
+# ('--one-file-per-xsd', '')
+# ('--output-directory', 'src/ee/xml')
+# ('-m', '')
+#
+# Command line arguments:
+# xsd/ee-bom.xsd
+#
+# Command line:
+# env/bin/generateDS.py -f --one-file-per-xsd --output-directory="src/ee/xml" -m xsd/ee-bom.xsd
+#
+# Current working directory (os.getcwd()):
+# ee-python
+#
+
+import sys
+import re as re_
+import base64
+import datetime as datetime_
+import warnings as warnings_
+try:
+ from lxml import etree as etree_
+except ImportError:
+ from xml.etree import ElementTree as etree_
+
+
+Validate_simpletypes_ = True
+if sys.version_info.major == 2:
+ BaseStrType_ = basestring
+else:
+ BaseStrType_ = str
+
+
+def parsexml_(infile, parser=None, **kwargs):
+ if parser is None:
+ # Use the lxml ElementTree compatible parser so that, e.g.,
+ # we ignore comments.
+ try:
+ parser = etree_.ETCompatXMLParser()
+ except AttributeError:
+ # fallback to xml.etree
+ parser = etree_.XMLParser()
+ doc = etree_.parse(infile, parser=parser, **kwargs)
+ return doc
+
+def parsexmlstring_(instring, parser=None, **kwargs):
+ if parser is None:
+ # Use the lxml ElementTree compatible parser so that, e.g.,
+ # we ignore comments.
+ try:
+ parser = etree_.ETCompatXMLParser()
+ except AttributeError:
+ # fallback to xml.etree
+ parser = etree_.XMLParser()
+ element = etree_.fromstring(instring, parser=parser, **kwargs)
+ return element
+
+#
+# Namespace prefix definition table (and other attributes, too)
+#
+# The module generatedsnamespaces, if it is importable, must contain
+# a dictionary named GeneratedsNamespaceDefs. This Python dictionary
+# should map element type names (strings) to XML schema namespace prefix
+# definitions. The export method for any class for which there is
+# a namespace prefix definition, will export that definition in the
+# XML representation of that element. See the export method of
+# any generated element type class for a example of the use of this
+# table.
+# A sample table is:
+#
+# # File: generatedsnamespaces.py
+#
+# GenerateDSNamespaceDefs = {
+# "ElementtypeA": "http://www.xxx.com/namespaceA",
+# "ElementtypeB": "http://www.xxx.com/namespaceB",
+# }
+#
+
+try:
+ from generatedsnamespaces import GenerateDSNamespaceDefs as GenerateDSNamespaceDefs_
+except ImportError:
+ GenerateDSNamespaceDefs_ = {}
+
+#
+# The root super-class for element type classes
+#
+# 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], "{}".format(micro_seconds).rjust(6, "0"), )
+ 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.
+ # The target value must match at least one of the patterns
+ # in order for the test to succeed.
+ found1 = True
+ for patterns1 in patterns:
+ found2 = False
+ for patterns2 in patterns1:
+ mo = re_.search(patterns2, target)
+ if mo is not None and len(mo.group(0)) == len(target):
+ 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.items()))
+ @staticmethod
+ def gds_encode(instring):
+ if sys.version_info.major == 2:
+ if ExternalEncoding:
+ encoding = ExternalEncoding
+ else:
+ encoding = 'utf-8'
+ return instring.encode(encoding)
+ else:
+ return instring
+ @staticmethod
+ def convert_unicode(instring):
+ if isinstance(instring, str):
+ result = quote_xml(instring)
+ elif sys.version_info.major == 2 and isinstance(instring, unicode):
+ result = quote_xml(instring).encode('utf8')
+ else:
+ result = GeneratedsSuper.gds_encode(str(instring))
+ return result
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return False
+ return self.__dict__ == other.__dict__
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def getSubclassFromModule_(module, class_):
+ '''Get the subclass of a class from a specific module.'''
+ name = class_.__name__ + 'Sub'
+ if hasattr(module, name):
+ return getattr(module, name)
+ else:
+ return None
+
+
+#
+# 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 = ''
+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)
+
+# Change this to redirect the generated superclass module to use a
+# specific subclass module.
+CurrentSubclassModule_ = None
+
+#
+# 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, BaseStrType_) 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('&', '&amp;')
+ s1 = s1.replace('<', '&lt;')
+ s1 = s1.replace('>', '&gt;')
+ return s1
+
+
+def quote_attrib(inStr):
+ s1 = (isinstance(inStr, BaseStrType_) and inStr or '%s' % inStr)
+ s1 = s1.replace('&', '&amp;')
+ s1 = s1.replace('<', '&lt;')
+ s1 = s1.replace('>', '&gt;')
+ if '"' in s1:
+ if "'" in s1:
+ s1 = '"%s"' % s1.replace('"', "&quot;")
+ else:
+ s1 = "'%s'" % s1
+ else:
+ s1 = '"%s"' % s1
+ return s1
+
+
+def quote_python(inStr):
+ s1 = inStr
+ if s1.find("'") == -1:
+ if s1.find('\n') == -1:
+ return "'%s'" % s1
+ else:
+ return "'''%s'''" % s1
+ else:
+ if s1.find('"') != -1:
+ s1 = s1.replace('"', '\\"')
+ if s1.find('\n') == -1:
+ return '"%s"' % s1
+ else:
+ return '"""%s"""' % s1
+
+
+def get_all_text_(node):
+ if node.text is not None:
+ text = node.text
+ else:
+ text = ''
+ for child in node:
+ if child.tail is not None:
+ text += child.tail
+ return text
+
+
+def find_attr_value_(attr_name, node):
+ attrs = node.attrib
+ attr_parts = attr_name.split(':')
+ value = None
+ if len(attr_parts) == 1:
+ value = attrs.get(attr_name)
+ elif len(attr_parts) == 2:
+ prefix, name = attr_parts
+ namespace = node.nsmap.get(prefix)
+ if namespace is not None:
+ value = attrs.get('{%s}%s' % (namespace, name, ))
+ return value
+
+
+class GDSParseError(Exception):
+ pass
+
+
+def raise_parse_error(node, msg):
+ msg = '%s (element %s/line %d)' % (msg, node.tag, node.sourceline, )
+ raise GDSParseError(msg)
+
+
+class MixedContainer:
+ # Constants for category:
+ CategoryNone = 0
+ CategoryText = 1
+ CategorySimple = 2
+ CategoryComplex = 3
+ # Constants for content_type:
+ TypeNone = 0
+ TypeText = 1
+ TypeString = 2
+ TypeInteger = 3
+ TypeFloat = 4
+ TypeDecimal = 5
+ TypeDouble = 6
+ TypeBoolean = 7
+ TypeBase64 = 8
+ def __init__(self, category, content_type, name, value):
+ self.category = category
+ self.content_type = content_type
+ self.name = name
+ self.value = value
+ def getCategory(self):
+ return self.category
+ def getContenttype(self, content_type):
+ return self.content_type
+ def getValue(self):
+ return self.value
+ def getName(self):
+ return self.name
+ def export(self, outfile, level, name, namespace,
+ pretty_print=True):
+ if self.category == MixedContainer.CategoryText:
+ # Prevent exporting empty content as empty lines.
+ if self.value.strip():
+ outfile.write(self.value)
+ elif self.category == MixedContainer.CategorySimple:
+ self.exportSimple(outfile, level, name)
+ else: # category == MixedContainer.CategoryComplex
+ self.value.export(
+ outfile, level, namespace, name_=name,
+ pretty_print=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,
+ optional=0, child_attrs=None, choice=None):
+ self.name = name
+ self.data_type = data_type
+ self.container = container
+ self.child_attrs = child_attrs
+ self.choice = choice
+ self.optional = optional
+ 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 set_child_attrs(self, child_attrs): self.child_attrs = child_attrs
+ def get_child_attrs(self): return self.child_attrs
+ def set_choice(self, choice): self.choice = choice
+ def get_choice(self): return self.choice
+ def set_optional(self, optional): self.optional = optional
+ def get_optional(self): return self.optional
+
+
+def _cast(typ, value):
+ if typ is None or value is None:
+ return value
+ return typ(value)
+
+#
+# Data representation classes.
+#
+
+
+class BomFile(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, parts=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ self.parts = parts
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, BomFile)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if BomFile.subclass:
+ return BomFile.subclass(*args_, **kwargs_)
+ else:
+ return BomFile(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_parts(self):
+ return self.parts
+ def set_parts(self, parts):
+ self.parts = parts
+ partsProp = property(get_parts, set_parts)
+ def hasContent_(self):
+ if (
+ self.parts is not None
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='BomFile', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('BomFile')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ 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' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='BomFile')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='BomFile', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='BomFile'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='BomFile', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.parts is not None:
+ self.parts.export(outfile, level, namespaceprefix_, namespacedef_='', name_='parts', pretty_print=pretty_print)
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'parts':
+ obj_ = PartList.factory(parent_object_=self)
+ obj_.build(child_)
+ self.parts = obj_
+ obj_.original_tagname_ = 'parts'
+# end class BomFile
+
+
+class Part(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, id=None, schema_reference=None, part_type=None, part_numbers=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ self.id = _cast(None, id)
+ self.schema_reference = schema_reference
+ self.part_type = part_type
+ self.part_numbers = part_numbers
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, Part)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if Part.subclass:
+ return Part.subclass(*args_, **kwargs_)
+ else:
+ return Part(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_schema_reference(self):
+ return self.schema_reference
+ def set_schema_reference(self, schema_reference):
+ self.schema_reference = schema_reference
+ schema_referenceProp = property(get_schema_reference, set_schema_reference)
+ def get_part_type(self):
+ return self.part_type
+ def set_part_type(self, part_type):
+ self.part_type = part_type
+ part_typeProp = property(get_part_type, set_part_type)
+ def get_part_numbers(self):
+ return self.part_numbers
+ def set_part_numbers(self, part_numbers):
+ self.part_numbers = part_numbers
+ part_numbersProp = property(get_part_numbers, set_part_numbers)
+ def get_id(self):
+ return self.id
+ def set_id(self, id):
+ self.id = id
+ idProp = property(get_id, set_id)
+ def hasContent_(self):
+ if (
+ self.schema_reference is not None or
+ self.part_type is not None or
+ self.part_numbers is not None
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='Part', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('Part')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ 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' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='Part')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='Part', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='Part'):
+ if self.id is not None and 'id' not in already_processed:
+ already_processed.add('id')
+ outfile.write(' id=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.id), input_name='id')), ))
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='Part', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.schema_reference is not None:
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%sschema-reference>%s</%sschema-reference>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(self.schema_reference), input_name='schema-reference')), namespaceprefix_ , eol_))
+ if self.part_type is not None:
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%spart-type>%s</%spart-type>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(self.part_type), input_name='part-type')), namespaceprefix_ , eol_))
+ if self.part_numbers is not None:
+ self.part_numbers.export(outfile, level, namespaceprefix_, namespacedef_='', name_='part-numbers', pretty_print=pretty_print)
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ value = find_attr_value_('id', node)
+ if value is not None and 'id' not in already_processed:
+ already_processed.add('id')
+ self.id = value
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'schema-reference':
+ schema_reference_ = child_.text
+ schema_reference_ = self.gds_validate_string(schema_reference_, node, 'schema_reference')
+ self.schema_reference = schema_reference_
+ elif nodeName_ == 'part-type':
+ part_type_ = child_.text
+ part_type_ = self.gds_validate_string(part_type_, node, 'part_type')
+ self.part_type = part_type_
+ elif nodeName_ == 'part-numbers':
+ obj_ = PartNumberList.factory(parent_object_=self)
+ obj_.build(child_)
+ self.part_numbers = obj_
+ obj_.original_tagname_ = 'part-numbers'
+# end class Part
+
+
+class PartList(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, part=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ if part is None:
+ self.part = []
+ else:
+ self.part = part
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, PartList)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if PartList.subclass:
+ return PartList.subclass(*args_, **kwargs_)
+ else:
+ return PartList(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_part(self):
+ return self.part
+ def set_part(self, part):
+ self.part = part
+ def add_part(self, value):
+ self.part.append(value)
+ def add_part(self, value):
+ self.part.append(value)
+ def insert_part_at(self, index, value):
+ self.part.insert(index, value)
+ def replace_part_at(self, index, value):
+ self.part[index] = value
+ partProp = property(get_part, set_part)
+ def hasContent_(self):
+ if (
+ self.part
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='PartList', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('PartList')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ 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' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='PartList')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='PartList', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='PartList'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='PartList', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ for part_ in self.part:
+ part_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='part', pretty_print=pretty_print)
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'part':
+ obj_ = Part.factory(parent_object_=self)
+ obj_.build(child_)
+ self.part.append(obj_)
+ obj_.original_tagname_ = 'part'
+# end class PartList
+
+
+class PartNumber(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, value=None, distributor=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ self.value = value
+ self.distributor = distributor
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, PartNumber)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if PartNumber.subclass:
+ return PartNumber.subclass(*args_, **kwargs_)
+ else:
+ return PartNumber(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_value(self):
+ return self.value
+ def set_value(self, value):
+ self.value = value
+ valueProp = property(get_value, set_value)
+ def get_distributor(self):
+ return self.distributor
+ def set_distributor(self, distributor):
+ self.distributor = distributor
+ distributorProp = property(get_distributor, set_distributor)
+ def hasContent_(self):
+ if (
+ self.value is not None or
+ self.distributor is not None
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='PartNumber', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('PartNumber')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ 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' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='PartNumber')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='PartNumber', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='PartNumber'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='PartNumber', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.value is not None:
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%svalue>%s</%svalue>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(self.value), input_name='value')), namespaceprefix_ , eol_))
+ if self.distributor is not None:
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%sdistributor>%s</%sdistributor>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(self.distributor), input_name='distributor')), namespaceprefix_ , eol_))
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'value':
+ value_ = child_.text
+ value_ = self.gds_validate_string(value_, node, 'value')
+ self.value = value_
+ elif nodeName_ == 'distributor':
+ distributor_ = child_.text
+ distributor_ = self.gds_validate_string(distributor_, node, 'distributor')
+ self.distributor = distributor_
+# end class PartNumber
+
+
+class PartNumberList(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, part_number=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ if part_number is None:
+ self.part_number = []
+ else:
+ self.part_number = part_number
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, PartNumberList)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if PartNumberList.subclass:
+ return PartNumberList.subclass(*args_, **kwargs_)
+ else:
+ return PartNumberList(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_part_number(self):
+ return self.part_number
+ def set_part_number(self, part_number):
+ self.part_number = part_number
+ def add_part_number(self, value):
+ self.part_number.append(value)
+ def add_part_number(self, value):
+ self.part_number.append(value)
+ def insert_part_number_at(self, index, value):
+ self.part_number.insert(index, value)
+ def replace_part_number_at(self, index, value):
+ self.part_number[index] = value
+ part_numberProp = property(get_part_number, set_part_number)
+ def hasContent_(self):
+ if (
+ self.part_number
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='PartNumberList', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('PartNumberList')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ 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' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='PartNumberList')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='PartNumberList', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='PartNumberList'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='PartNumberList', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ for part_number_ in self.part_number:
+ part_number_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='part-number', pretty_print=pretty_print)
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'part-number':
+ obj_ = PartNumber.factory(parent_object_=self)
+ obj_.build(child_)
+ self.part_number.append(obj_)
+ obj_.original_tagname_ = 'part-number'
+# end class PartNumberList
+
+
+GDSClassesMapping = {
+ 'bom-file': BomFile,
+}
+
+
+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 = 'BomFile'
+ rootClass = BomFile
+ 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 = 'BomFile'
+ rootClass = BomFile
+ 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):
+ '''Parse a string, create the object tree, and export it.
+
+ Arguments:
+ - inString -- A string. This XML fragment should not start
+ with an XML declaration containing an encoding.
+ - silence -- A boolean. If False, export the object.
+ Returns -- The root object in the tree.
+ '''
+ parser = None
+ rootNode= parsexmlstring_(inString, parser)
+ rootTag, rootClass = get_root_tag(rootNode)
+ if rootClass is None:
+ rootTag = 'BomFile'
+ rootClass = BomFile
+ rootObj = rootClass.factory()
+ rootObj.build(rootNode)
+ # Enable Python to collect the space used by the DOM.
+ 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 = 'BomFile'
+ rootClass = BomFile
+ 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 bomFile import *\n\n')
+ sys.stdout.write('import bomFile 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__ = [
+ "BomFile",
+ "Part",
+ "PartList",
+ "PartNumber",
+ "PartNumberList"
+]
diff --git a/src/ee/xml/catalogFile.py b/src/ee/xml/catalogFile.py
new file mode 100644
index 0000000..61085e7
--- /dev/null
+++ b/src/ee/xml/catalogFile.py
@@ -0,0 +1,1103 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#
+# Generated Tue Feb 19 12:27:27 2019 by generateDS.py version 2.30.11.
+# Python 3.7.2+ (default, Feb 2 2019, 14:31:48) [GCC 8.2.0]
+#
+# Command line options:
+# ('-f', '')
+# ('--one-file-per-xsd', '')
+# ('--output-directory', 'src/ee/xml')
+# ('-m', '')
+#
+# Command line arguments:
+# xsd/ee-catalog.xsd
+#
+# Command line:
+# env/bin/generateDS.py -f --one-file-per-xsd --output-directory="src/ee/xml" -m xsd/ee-catalog.xsd
+#
+# Current working directory (os.getcwd()):
+# ee-python
+#
+
+import sys
+import re as re_
+import base64
+import datetime as datetime_
+import warnings as warnings_
+try:
+ from lxml import etree as etree_
+except ImportError:
+ from xml.etree import ElementTree as etree_
+
+
+Validate_simpletypes_ = True
+if sys.version_info.major == 2:
+ BaseStrType_ = basestring
+else:
+ BaseStrType_ = str
+
+
+def parsexml_(infile, parser=None, **kwargs):
+ if parser is None:
+ # Use the lxml ElementTree compatible parser so that, e.g.,
+ # we ignore comments.
+ try:
+ parser = etree_.ETCompatXMLParser()
+ except AttributeError:
+ # fallback to xml.etree
+ parser = etree_.XMLParser()
+ doc = etree_.parse(infile, parser=parser, **kwargs)
+ return doc
+
+def parsexmlstring_(instring, parser=None, **kwargs):
+ if parser is None:
+ # Use the lxml ElementTree compatible parser so that, e.g.,
+ # we ignore comments.
+ try:
+ parser = etree_.ETCompatXMLParser()
+ except AttributeError:
+ # fallback to xml.etree
+ parser = etree_.XMLParser()
+ element = etree_.fromstring(instring, parser=parser, **kwargs)
+ return element
+
+#
+# Namespace prefix definition table (and other attributes, too)
+#
+# The module generatedsnamespaces, if it is importable, must contain
+# a dictionary named GeneratedsNamespaceDefs. This Python dictionary
+# should map element type names (strings) to XML schema namespace prefix
+# definitions. The export method for any class for which there is
+# a namespace prefix definition, will export that definition in the
+# XML representation of that element. See the export method of
+# any generated element type class for a example of the use of this
+# table.
+# A sample table is:
+#
+# # File: generatedsnamespaces.py
+#
+# GenerateDSNamespaceDefs = {
+# "ElementtypeA": "http://www.xxx.com/namespaceA",
+# "ElementtypeB": "http://www.xxx.com/namespaceB",
+# }
+#
+
+try:
+ from generatedsnamespaces import GenerateDSNamespaceDefs as GenerateDSNamespaceDefs_
+except ImportError:
+ GenerateDSNamespaceDefs_ = {}
+
+#
+# The root super-class for element type classes
+#
+# 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], "{}".format(micro_seconds).rjust(6, "0"), )
+ 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.
+ # The target value must match at least one of the patterns
+ # in order for the test to succeed.
+ found1 = True
+ for patterns1 in patterns:
+ found2 = False
+ for patterns2 in patterns1:
+ mo = re_.search(patterns2, target)
+ if mo is not None and len(mo.group(0)) == len(target):
+ 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.items()))
+ @staticmethod
+ def gds_encode(instring):
+ if sys.version_info.major == 2:
+ if ExternalEncoding:
+ encoding = ExternalEncoding
+ else:
+ encoding = 'utf-8'
+ return instring.encode(encoding)
+ else:
+ return instring
+ @staticmethod
+ def convert_unicode(instring):
+ if isinstance(instring, str):
+ result = quote_xml(instring)
+ elif sys.version_info.major == 2 and isinstance(instring, unicode):
+ result = quote_xml(instring).encode('utf8')
+ else:
+ result = GeneratedsSuper.gds_encode(str(instring))
+ return result
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return False
+ return self.__dict__ == other.__dict__
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def getSubclassFromModule_(module, class_):
+ '''Get the subclass of a class from a specific module.'''
+ name = class_.__name__ + 'Sub'
+ if hasattr(module, name):
+ return getattr(module, name)
+ else:
+ return None
+
+
+#
+# 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 = ''
+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)
+
+# Change this to redirect the generated superclass module to use a
+# specific subclass module.
+CurrentSubclassModule_ = None
+
+#
+# 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, BaseStrType_) 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('&', '&amp;')
+ s1 = s1.replace('<', '&lt;')
+ s1 = s1.replace('>', '&gt;')
+ return s1
+
+
+def quote_attrib(inStr):
+ s1 = (isinstance(inStr, BaseStrType_) and inStr or '%s' % inStr)
+ s1 = s1.replace('&', '&amp;')
+ s1 = s1.replace('<', '&lt;')
+ s1 = s1.replace('>', '&gt;')
+ if '"' in s1:
+ if "'" in s1:
+ s1 = '"%s"' % s1.replace('"', "&quot;")
+ else:
+ s1 = "'%s'" % s1
+ else:
+ s1 = '"%s"' % s1
+ return s1
+
+
+def quote_python(inStr):
+ s1 = inStr
+ if s1.find("'") == -1:
+ if s1.find('\n') == -1:
+ return "'%s'" % s1
+ else:
+ return "'''%s'''" % s1
+ else:
+ if s1.find('"') != -1:
+ s1 = s1.replace('"', '\\"')
+ if s1.find('\n') == -1:
+ return '"%s"' % s1
+ else:
+ return '"""%s"""' % s1
+
+
+def get_all_text_(node):
+ if node.text is not None:
+ text = node.text
+ else:
+ text = ''
+ for child in node:
+ if child.tail is not None:
+ text += child.tail
+ return text
+
+
+def find_attr_value_(attr_name, node):
+ attrs = node.attrib
+ attr_parts = attr_name.split(':')
+ value = None
+ if len(attr_parts) == 1:
+ value = attrs.get(attr_name)
+ elif len(attr_parts) == 2:
+ prefix, name = attr_parts
+ namespace = node.nsmap.get(prefix)
+ if namespace is not None:
+ value = attrs.get('{%s}%s' % (namespace, name, ))
+ return value
+
+
+class GDSParseError(Exception):
+ pass
+
+
+def raise_parse_error(node, msg):
+ msg = '%s (element %s/line %d)' % (msg, node.tag, node.sourceline, )
+ raise GDSParseError(msg)
+
+
+class MixedContainer:
+ # Constants for category:
+ CategoryNone = 0
+ CategoryText = 1
+ CategorySimple = 2
+ CategoryComplex = 3
+ # Constants for content_type:
+ TypeNone = 0
+ TypeText = 1
+ TypeString = 2
+ TypeInteger = 3
+ TypeFloat = 4
+ TypeDecimal = 5
+ TypeDouble = 6
+ TypeBoolean = 7
+ TypeBase64 = 8
+ def __init__(self, category, content_type, name, value):
+ self.category = category
+ self.content_type = content_type
+ self.name = name
+ self.value = value
+ def getCategory(self):
+ return self.category
+ def getContenttype(self, content_type):
+ return self.content_type
+ def getValue(self):
+ return self.value
+ def getName(self):
+ return self.name
+ def export(self, outfile, level, name, namespace,
+ pretty_print=True):
+ if self.category == MixedContainer.CategoryText:
+ # Prevent exporting empty content as empty lines.
+ if self.value.strip():
+ outfile.write(self.value)
+ elif self.category == MixedContainer.CategorySimple:
+ self.exportSimple(outfile, level, name)
+ else: # category == MixedContainer.CategoryComplex
+ self.value.export(
+ outfile, level, namespace, name_=name,
+ pretty_print=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,
+ optional=0, child_attrs=None, choice=None):
+ self.name = name
+ self.data_type = data_type
+ self.container = container
+ self.child_attrs = child_attrs
+ self.choice = choice
+ self.optional = optional
+ 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 set_child_attrs(self, child_attrs): self.child_attrs = child_attrs
+ def get_child_attrs(self): return self.child_attrs
+ def set_choice(self, choice): self.choice = choice
+ def get_choice(self): return self.choice
+ def set_optional(self, optional): self.optional = optional
+ def get_optional(self): return self.optional
+
+
+def _cast(typ, value):
+ if typ is None or value is None:
+ return value
+ return typ(value)
+
+#
+# Data representation classes.
+#
+
+
+class CatalogFile(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, products=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ self.products = products
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, CatalogFile)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if CatalogFile.subclass:
+ return CatalogFile.subclass(*args_, **kwargs_)
+ else:
+ return CatalogFile(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_products(self):
+ return self.products
+ def set_products(self, products):
+ self.products = products
+ productsProp = property(get_products, set_products)
+ def hasContent_(self):
+ if (
+ self.products is not None
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='CatalogFile', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('CatalogFile')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ 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' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='CatalogFile')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='CatalogFile', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='CatalogFile'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='CatalogFile', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.products is not None:
+ self.products.export(outfile, level, namespaceprefix_, namespacedef_='', name_='products', pretty_print=pretty_print)
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'products':
+ obj_ = ProductList.factory(parent_object_=self)
+ obj_.build(child_)
+ self.products = obj_
+ obj_.original_tagname_ = 'products'
+# end class CatalogFile
+
+
+class Product(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, ref=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ self.ref = ref
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, Product)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if Product.subclass:
+ return Product.subclass(*args_, **kwargs_)
+ else:
+ return Product(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_ref(self):
+ return self.ref
+ def set_ref(self, ref):
+ self.ref = ref
+ refProp = property(get_ref, set_ref)
+ def hasContent_(self):
+ if (
+ self.ref is not None
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='Product', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('Product')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ 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' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='Product')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='Product', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='Product'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='Product', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.ref is not None:
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%sref>%s</%sref>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(self.ref), input_name='ref')), namespaceprefix_ , eol_))
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'ref':
+ ref_ = child_.text
+ ref_ = self.gds_validate_string(ref_, node, 'ref')
+ self.ref = ref_
+# end class Product
+
+
+class ProductList(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, product=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ if product is None:
+ self.product = []
+ else:
+ self.product = product
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, ProductList)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if ProductList.subclass:
+ return ProductList.subclass(*args_, **kwargs_)
+ else:
+ return ProductList(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_product(self):
+ return self.product
+ def set_product(self, product):
+ self.product = product
+ def add_product(self, value):
+ self.product.append(value)
+ def add_product(self, value):
+ self.product.append(value)
+ def insert_product_at(self, index, value):
+ self.product.insert(index, value)
+ def replace_product_at(self, index, value):
+ self.product[index] = value
+ productProp = property(get_product, set_product)
+ def hasContent_(self):
+ if (
+ self.product
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='ProductList', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('ProductList')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ 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' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='ProductList')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='ProductList', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='ProductList'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='ProductList', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ for product_ in self.product:
+ product_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='product', pretty_print=pretty_print)
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'product':
+ obj_ = Product.factory(parent_object_=self)
+ obj_.build(child_)
+ self.product.append(obj_)
+ obj_.original_tagname_ = 'product'
+# end class ProductList
+
+
+GDSClassesMapping = {
+}
+
+
+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 = 'CatalogFile'
+ rootClass = CatalogFile
+ 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 = 'CatalogFile'
+ rootClass = CatalogFile
+ 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):
+ '''Parse a string, create the object tree, and export it.
+
+ Arguments:
+ - inString -- A string. This XML fragment should not start
+ with an XML declaration containing an encoding.
+ - silence -- A boolean. If False, export the object.
+ Returns -- The root object in the tree.
+ '''
+ parser = None
+ rootNode= parsexmlstring_(inString, parser)
+ rootTag, rootClass = get_root_tag(rootNode)
+ if rootClass is None:
+ rootTag = 'CatalogFile'
+ rootClass = CatalogFile
+ rootObj = rootClass.factory()
+ rootObj.build(rootNode)
+ # Enable Python to collect the space used by the DOM.
+ 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 = 'CatalogFile'
+ rootClass = CatalogFile
+ 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 catalogFile import *\n\n')
+ sys.stdout.write('import catalogFile 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__ = [
+ "CatalogFile",
+ "Product",
+ "ProductList"
+]