From 6689c7cc0f0a9757a356fa5185f9ef9d736d2c8a Mon Sep 17 00:00:00 2001
From: lsowen <logan.owen@**********.com>
Date: Fri, 4 May 2012 12:49:09 -0400
Subject: [PATCH] Base64Type and DateTimeType automatic serialize/deserialize on generateDS-2.7c base

---
 generateDS.py |  145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 138 insertions(+), 7 deletions(-)

diff --git a/generateDS.py b/generateDS.py
index 2d4f797..f130423 100755
--- a/generateDS.py
+++ b/generateDS.py
@@ -205,7 +205,7 @@ def set_type_constants(nameSpace):
         NameType, NCNameType, QNameType, NameTypes, \
         AnyAttributeType, SimpleTypeType, RestrictionType, \
         WhiteSpaceType, ListType, EnumerationType, UnionType, \
-        AnyType, \
+        Base64Type, AnyType, \
         AnnotationType, DocumentationType, \
         OtherSimpleTypes
     CurrentNamespacePrefix = nameSpace
@@ -252,7 +252,6 @@ def set_type_constants(nameSpace):
     StringType = (nameSpace + 'string',
         nameSpace + 'duration',
         nameSpace + 'anyURI',
-        nameSpace + 'base64Binary',
         nameSpace + 'hexBinary',
         nameSpace + 'normalizedString',
         nameSpace + 'NMTOKEN',
@@ -260,6 +259,7 @@ def set_type_constants(nameSpace):
         nameSpace + 'Name',
         nameSpace + 'language',
         )
+    Base64Type = nameSpace + 'base64Binary'
     TokenType = nameSpace + 'token'
     NameType = nameSpace + 'Name'
     NCNameType = nameSpace + 'NCName'
@@ -1005,6 +1005,7 @@ class XschemaAttribute:
                 typeObjType == DateTimeType or \
                 typeObjType == TimeType or \
                 typeObjType == DateType or \
+                typeObjType == Base64Type or \
                 typeObjType in IntegerType or \
                 typeObjType == DecimalType or \
                 typeObjType == PositiveIntegerType or \
@@ -1197,6 +1198,7 @@ class XschemaHandler(handler.ContentHandler):
                     extensionBase == DateTimeType or \
                     extensionBase == TimeType or \
                     extensionBase == DateType or \
+                    extensionBase == Base64Type or \
                     extensionBase in IntegerType or \
                     extensionBase == DecimalType or \
                     extensionBase == PositiveIntegerType or \
@@ -1431,7 +1433,6 @@ def generateExportFn_1(wrt, child, name, namespace, fill):
     child_type = child.getType()
     if child_type in StringType or \
         child_type == TokenType or \
-        child_type == DateTimeType or \
         child_type == TimeType or \
         child_type == DateType:
         wrt('%s        if self.%s is not None:\n' % (fill, mappedName, ))
@@ -1490,6 +1491,18 @@ def generateExportFn_1(wrt, child, name, namespace, fill):
             s1 = "%s            outfile.write('<%%s%s>%%s</%%s%s>%%s' %% (namespace_, self.gds_format_double(self.%s, input_name='%s'), namespace_, eol_))\n" % \
                 (fill, name, name, mappedName, name, )
         wrt(s1)
+    elif child_type == Base64Type:
+        wrt('%s        if self.%s is not None:\n' % (fill, mappedName, ))
+        wrt('%s            showIndent(outfile, level, pretty_print)\n' % fill)
+        s1 = "%s            outfile.write('<%%s%s>%%s</%%s%s>%%s' %% (namespace_, self.gds_format_base64(self.%s, input_name='%s'), namespace_, eol_))\n" % \
+            (fill, name, name, mappedName, name, )
+        wrt(s1)
+    elif child_type == DateTimeType:
+        wrt('%s        if self.%s is not None:\n' % (fill, mappedName, ))
+        wrt('%s            showIndent(outfile, level, pretty_print)\n' % fill)
+        s1 = "%s            outfile.write('<%%s%s>%%s</%%s%s>%%s' %% (namespace_, self.gds_format_datetime(self.%s, input_name='%s'), namespace_, eol_))\n" % \
+            (fill, name, name, mappedName, name, )
+        wrt(s1)
     else:
         wrt("%s        if self.%s is not None:\n" % (fill, mappedName))
         # name_type_problem
@@ -1511,7 +1524,6 @@ def generateExportFn_2(wrt, child, name, namespace, fill):
     wrt("%s    for %s_ in self.%s:\n" % (fill, cleanName, mappedName, ))
     if child_type in StringType or \
         child_type == TokenType or \
-        child_type == DateTimeType or \
         child_type == TimeType or \
         child_type == DateType:
         wrt('%s        showIndent(outfile, level, pretty_print)\n' % fill)
@@ -1558,6 +1570,16 @@ def generateExportFn_2(wrt, child, name, namespace, fill):
             s1 = "%s        outfile.write('<%%s%s>%%s</%%s%s>%%s' %% (namespace_, self.gds_format_double(%s_, input_name='%s'), namespace_, eol_))\n" % \
                 (fill, name, name, cleanName, name, )
         wrt(s1)
+    elif child_type == Base64Type:
+        wrt('%s        showIndent(outfile, level, pretty_print)\n' % fill)
+        s1 = "%s        outfile.write('<%%s%s>%%s</%%s%s>%%s' %% (namespace_, self.gds_format_base64(%s_, input_name='%s'), namespace_, eol_))\n" % \
+            (fill, name, name, cleanName, name, )
+        wrt(s1)
+    elif child_type == DateTimeType:
+        wrt('%s        showIndent(outfile, level, pretty_print)\n' % fill)
+        s1 = "%s        outfile.write('<%%s%s>%%s</%%s%s>%%s' %% (namespace_, self.gds_format_datetime(%s_, input_name='%s'), namespace_, eol_))\n" % \
+            (fill, name, name, cleanName, name, )
+        wrt(s1)
     else:
         # name_type_problem
         if False:        # name == child.getType():
@@ -1576,7 +1598,6 @@ def generateExportFn_3(wrt, child, name, namespace, fill):
     # fix_simpletype
     if child_type in StringType or \
         child_type == TokenType or \
-        child_type == DateTimeType or \
         child_type == TimeType or \
         child_type == DateType:
         wrt('%s        if self.%s is not None:\n' % (fill, mappedName, ))
@@ -1635,6 +1656,18 @@ def generateExportFn_3(wrt, child, name, namespace, fill):
             s1 = "%s            outfile.write('<%%s%s>%%s</%%s%s>%%s' %% (namespace_, self.gds_format_double(self.%s, input_name='%s'), namespace_, eol_))\n" % \
                 (fill, name, name, mappedName, name, )
         wrt(s1)
+    elif child_type == Base64Type:
+        wrt('%s        if self.%s is not None:\n' % (fill, mappedName, ))
+        wrt('%s            showIndent(outfile, level, pretty_print)\n' % fill)
+        s1 = "%s            outfile.write('<%%s%s>%%s</%%s%s>%%s' %% (namespace_, self.gds_format_base64(self.%s, input_name='%s'), namespace_, eol_))\n" % \
+            (fill, name, name, mappedName, name, )
+        wrt(s1)
+    elif child_type == DateTimeType:
+        wrt('%s        if self.%s is not None:\n' % (fill, mappedName, ))
+        wrt('%s            showIndent(outfile, level, pretty_print)\n' % fill)
+        s1 = "%s            outfile.write('<%%s%s>%%s</%%s%s>%%s' %% (namespace_, self.gds_format_datetime(self.%s, input_name='%s'), namespace_, eol_))\n" % \
+            (fill, name, name, mappedName, name, )
+        wrt(s1)
     else:
         wrt("%s        if self.%s is not None:\n" % (fill, mappedName))
         # name_type_problem
@@ -1668,7 +1701,6 @@ def generateExportAttributes(wrt, element, hasAttributes):
             if (attrDef.getType() in StringType or
                 attrDef.getType() in IDTypes or
                 attrDef.getType() == TokenType or
-                attrDef.getType() == DateTimeType or
                 attrDef.getType() == TimeType or
                 attrDef.getType() == DateType):
                 s1 = '''%s        outfile.write(' %s=%%s' %% (self.gds_format_string(quote_attrib(self.%s).encode(ExternalEncoding), input_name='%s'), ))\n''' % \
@@ -1690,6 +1722,9 @@ def generateExportAttributes(wrt, element, hasAttributes):
             elif attrDef.getType() == DoubleType:
                 s1 = '''%s        outfile.write(' %s="%%s"' %% self.gds_format_double(self.%s, input_name='%s'))\n''' % (
                     indent, name, cleanName, name)
+            elif attrDef.getType() == DateTimeType:
+                s1 = '''%s        outfile.write(' %s="%%s"' %% self.gds_format_datetime(self.%s, input_name='%s'))\n''' % (
+                    indent, name, cleanName, name)
             else:
                 s1 = '''%s        outfile.write(' %s=%%s' %% (quote_attrib(self.%s), ))\n''' % (
                     indent, name, cleanName, )
@@ -2314,6 +2349,18 @@ def generateBuildMixed_1(wrt, prefix, child, headChild, keyword, delayed):
         wrt("                MixedContainer.TypeFloat, '%s', fval_)\n" % \
             origName)
         wrt("            self.content_.append(obj_)\n")
+    elif childType == Base64Type:
+        wrt("        %s nodeName_ == '%s' and child_.text is not None:\n" % (
+            keyword, origName, ))
+        wrt("            sval_ = child_.text\n")
+        wrt("            try:\n")
+        wrt("                bval_ = base64.b64decode(sval_)\n")
+        wrt("            except (TypeError, ValueError), exp:\n")
+        wrt("                raise_parse_error(child_, 'requires base64 encoded string: %s' % exp)\n")
+        wrt("            obj_ = self.mixedclass_(MixedContainer.CategorySimple,\n")
+        wrt("                MixedContainer.TypeBase64, '%s', bval_)\n" % \
+            origName)
+        wrt("            self.content_.append(obj_)\n")
     else:
         # Perhaps it's a complexType that is defined right here.
         # Generate (later) a class for the nested types.
@@ -2392,7 +2439,6 @@ def generateBuildStandard_1(wrt, prefix, child, headChild,
     if (attrCount == 0 and
         ((childType in StringType or
             childType == TokenType or
-            childType == DateTimeType or
             childType == TimeType or
             childType == DateType or
             child.isListType()
@@ -2486,6 +2532,31 @@ def generateBuildStandard_1(wrt, prefix, child, headChild,
             wrt("            self.%s.append(fval_)\n" % (mappedName, ))
         else:
             wrt("            self.%s = fval_\n" % (mappedName, ))
+    elif childType == DateTimeType:
+        wrt("        %s nodeName_ == '%s':\n" % (keyword, origName, ))
+        wrt("            sval_ = child_.text\n")
+        wrt("            dval_ = self.gds_parse_datetime(sval_, node, '%s')\n" % (
+            name, ))
+        if child.getMaxOccurs() > 1:
+            wrt("            self.%s.append(dval_)\n" % (mappedName, ))
+        else:
+            wrt("            self.%s = dval_\n" % (mappedName, ))
+    elif childType == Base64Type:
+        wrt("        %s nodeName_ == '%s':\n" % (keyword, origName, ))
+        wrt("            sval_ = child_.text\n")
+        wrt("            if sval_ is not None:\n")
+        wrt("                try:\n")
+        wrt("                    bval_ = base64.b64decode(sval_)\n")
+        wrt("                except (TypeError, ValueError), exp:\n")
+        wrt("                    raise_parse_error(child_, 'requires base64 encoded string: %s' % exp)\n")
+        wrt("                bval_ = self.gds_validate_base64(bval_, node, '%s')\n" % (
+            name, ))
+        wrt("            else:\n")
+        wrt("                bval_ = None\n")
+        if child.getMaxOccurs() > 1:
+            wrt("            self.%s.append(bval_)\n" % (mappedName, ))
+        else:
+            wrt("            self.%s = bval_\n" % (mappedName, ))
     else:
         # Perhaps it's a complexType that is defined right here.
         # Generate (later) a class for the nested types.
@@ -2787,6 +2858,7 @@ def buildCtorArgs_aux(addedArgs, add, element):
             childType = child.getType()
             if childType in StringType or \
                 childType == TokenType or \
+                childType == Base64Type or \
                 childType == DateTimeType or \
                 childType == TimeType or \
                 childType == DateType:
@@ -3278,6 +3350,9 @@ TEMPLATE_HEADER = """\
 import sys
 import getopt
 import re as re_
+import base64
+from datetime import datetime, tzinfo, timedelta
+
 
 etree_ = None
 Verbose_import_ = False
@@ -3347,6 +3422,10 @@ except ImportError, exp:
             return input_data
         def gds_validate_string(self, input_data, node, input_name=''):
             return input_data
+        def gds_format_base64(self, input_data, input_name=''):
+            return base64.b64encode(input_data)
+        def gds_validate_base64(self, input_data, node, input_name=''):
+            return input_data
         def gds_format_integer(self, input_data, input_name=''):
             return '%%d' %% input_data
         def gds_validate_integer(self, input_data, node, input_name=''):
@@ -3401,6 +3480,55 @@ except ImportError, exp:
                 if value not in ('true', '1', 'false', '0', ):
                     raise_parse_error(node, 'Requires sequence of booleans ("true", "1", "false", "0")')
             return input_data
+        def gds_validate_datetime(self, input_data, node, input_name=''):
+            return input_data
+        def gds_format_datetime(self, input_data, input_name=''):
+            _svalue = input_data.strftime('%%Y-%%m-%%dT%%H:%%M:%%S')
+            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_parse_datetime(self, input_data, node, input_name=''):
+            class _FixedOffsetTZ(tzinfo):
+                def __init__(self, offset, name):
+                    self.__offset = 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
+            tz = None
+            if input_data[-1] == 'Z':
+                tz = _FixedOffsetTZ(0, 'GMT')
+                input_data = input_data[:-1]
+            else:
+                tzoff_pattern = re_.compile(r'(\+|-)((0\d|1[0-3]):[0-5]\d|14:00)$')
+                results = 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 = _FixedOffsetTZ( tzoff, results.group(0))
+                    input_data = input_data[:-6]
+            return datetime.strptime(input_data, '%%Y-%%m-%%dT%%H:%%M:%%S').replace(tzinfo = tz)
         def gds_str_lower(self, instring):
             return instring.lower()
         def get_path_(self, node):
@@ -3556,6 +3684,7 @@ class MixedContainer:
     TypeDecimal = 5
     TypeDouble = 6
     TypeBoolean = 7
+    TypeBase64 = 8
     def __init__(self, category, content_type, name, value):
         self.category = category
         self.content_type = content_type
@@ -3589,6 +3718,8 @@ class MixedContainer:
             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 exportLiteral(self, outfile, level, name):
         if self.category == MixedContainer.CategoryText:
             showIndent(outfile, level)
-- 
1.7.1

