1 from __future__ import nested_scopes
4 ################################################################################
5 # Copyright (c) 2003, Pfizer
6 # Copyright (c) 2001, Cayce Ullman.
7 # Copyright (c) 2001, Brian Matthews.
11 # Redistribution and use in source and binary forms, with or without
12 # modification, are permitted provided that the following conditions are met:
13 # Redistributions of source code must retain the above copyright notice, this
14 # list of conditions and the following disclaimer.
16 # Redistributions in binary form must reproduce the above copyright notice,
17 # this list of conditions and the following disclaimer in the documentation
18 # and/or other materials provided with the distribution.
20 # Neither the name of actzero, inc. nor the names of its contributors may
21 # be used to endorse or promote products derived from this software without
22 # specific prior written permission.
24 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
28 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 ################################################################################
38 ident = '$Id: Types.py 1496 2010-03-04 23:46:17Z pooryorick $'
39 from version import __version__
53 from Utilities import encodeHexString, cleanDate
54 from Config import Config
56 ###############################################################################
58 ###############################################################################
60 def isPrivate(name): return name[0]=='_'
61 def isPublic(name): return name[0]!='_'
63 ###############################################################################
65 ###############################################################################
68 _validURIs = (NS.XSD, NS.XSD2, NS.XSD3, NS.ENC)
70 def __init__(self, data = None, name = None, typed = 1, attrs = None):
71 if self.__class__ == anyType:
72 raise Error, "anyType can't be instantiated directly"
74 if type(name) in (ListType, TupleType):
75 self._ns, self._name = name
77 self._ns = self._validURIs[0]
84 self._type = self._typeName()
86 self._data = self._checkValueSpace(data)
92 if hasattr(self,'_name') and self._name:
93 return "<%s %s at %d>" % (self.__class__, self._name, id(self))
94 return "<%s at %d>" % (self.__class__, id(self))
98 def _checkValueSpace(self, data):
101 def _marshalData(self):
102 return str(self._data)
104 def _marshalAttrs(self, ns_map, builder):
107 for attr, value in self._attrs.items():
108 ns, n = builder.genns(ns_map, attr[0])
109 a += n + ' %s%s="%s"' % \
110 (ns, attr[1], cgi.escape(str(value), 1))
114 def _fixAttr(self, attr):
115 if type(attr) in (StringType, UnicodeType):
117 elif type(attr) == ListType:
119 elif type(attr) != TupleType:
120 raise AttributeError, "invalid attribute type"
123 raise AttributeError, "invalid attribute length"
125 if type(attr[0]) not in (NoneType, StringType, UnicodeType):
126 raise AttributeError, "invalid attribute namespace URI type"
130 def _getAttr(self, attr):
131 attr = self._fixAttr(attr)
134 return self._attrs[attr]
138 def _setAttr(self, attr, value):
139 attr = self._fixAttr(attr)
141 if type(value) is StringType:
142 value = unicode(value)
144 self._attrs[attr] = value
147 def _setAttrs(self, attrs):
148 if type(attrs) in (ListType, TupleType):
149 for i in range(0, len(attrs), 2):
150 self._setAttr(attrs[i], attrs[i + 1])
154 if type(attrs) == DictType:
156 elif isinstance(attrs, anyType):
159 raise AttributeError, "invalid attribute type"
161 for attr, value in d.items():
162 self._setAttr(attr, value)
164 def _setMustUnderstand(self, val):
165 self._setAttr((NS.ENV, "mustUnderstand"), val)
167 def _getMustUnderstand(self):
168 return self._getAttr((NS.ENV, "mustUnderstand"))
170 def _setActor(self, val):
171 self._setAttr((NS.ENV, "actor"), val)
174 return self._getAttr((NS.ENV, "actor"))
177 return self.__class__.__name__[:-4]
179 def _validNamespaceURI(self, URI, strict):
180 if not hasattr(self, '_typed') or not self._typed:
182 if URI in self._validURIs:
186 raise AttributeError, \
187 "not a valid namespace for type %s" % self._type
189 class voidType(anyType):
192 class stringType(anyType):
193 def _checkValueSpace(self, data):
195 raise ValueError, "must supply initial %s value" % self._type
197 if type(data) not in (StringType, UnicodeType):
198 raise AttributeError, "invalid %s type:" % self._type
202 def _marshalData(self):
206 class untypedType(stringType):
207 def __init__(self, data = None, name = None, attrs = None):
208 stringType.__init__(self, data, name, 0, attrs)
210 class IDType(stringType): pass
211 class NCNameType(stringType): pass
212 class NameType(stringType): pass
213 class ENTITYType(stringType): pass
214 class IDREFType(stringType): pass
215 class languageType(stringType): pass
216 class NMTOKENType(stringType): pass
217 class QNameType(stringType): pass
219 class tokenType(anyType):
220 _validURIs = (NS.XSD2, NS.XSD3)
221 __invalidre = '[\n\t]|^ | $| '
223 def _checkValueSpace(self, data):
225 raise ValueError, "must supply initial %s value" % self._type
227 if type(data) not in (StringType, UnicodeType):
228 raise AttributeError, "invalid %s type" % self._type
230 if type(self.__invalidre) == StringType:
231 self.__invalidre = re.compile(self.__invalidre)
233 if self.__invalidre.search(data):
234 raise ValueError, "invalid %s value" % self._type
238 class normalizedStringType(anyType):
239 _validURIs = (NS.XSD3,)
240 __invalidre = '[\n\r\t]'
242 def _checkValueSpace(self, data):
244 raise ValueError, "must supply initial %s value" % self._type
246 if type(data) not in (StringType, UnicodeType):
247 raise AttributeError, "invalid %s type" % self._type
249 if type(self.__invalidre) == StringType:
250 self.__invalidre = re.compile(self.__invalidre)
252 if self.__invalidre.search(data):
253 raise ValueError, "invalid %s value" % self._type
257 class CDATAType(normalizedStringType):
258 _validURIs = (NS.XSD2,)
260 class booleanType(anyType):
264 __nonzero__ = __int__
266 def _marshalData(self):
267 return ['false', 'true'][self._data]
269 def _checkValueSpace(self, data):
271 raise ValueError, "must supply initial %s value" % self._type
273 if data in (0, '0', 'false', ''):
275 if data in (1, '1', 'true'):
277 raise ValueError, "invalid %s value" % self._type
279 class decimalType(anyType):
280 def _checkValueSpace(self, data):
282 raise ValueError, "must supply initial %s value" % self._type
284 if type(data) not in (IntType, LongType, FloatType):
285 raise Error, "invalid %s value" % self._type
289 class floatType(anyType):
290 def _checkValueSpace(self, data):
292 raise ValueError, "must supply initial %s value" % self._type
294 if type(data) not in (IntType, LongType, FloatType) or \
295 data < -3.4028234663852886E+38 or \
296 data > 3.4028234663852886E+38:
297 raise ValueError, "invalid %s value: %s" % (self._type, repr(data))
301 def _marshalData(self):
302 return "%.18g" % self._data # More precision
304 class doubleType(anyType):
305 def _checkValueSpace(self, data):
307 raise ValueError, "must supply initial %s value" % self._type
309 if type(data) not in (IntType, LongType, FloatType) or \
310 data < -1.7976931348623158E+308 or \
311 data > 1.7976931348623157E+308:
312 raise ValueError, "invalid %s value: %s" % (self._type, repr(data))
316 def _marshalData(self):
317 return "%.18g" % self._data # More precision
319 class durationType(anyType):
320 _validURIs = (NS.XSD3,)
322 def _checkValueSpace(self, data):
324 raise ValueError, "must supply initial %s value" % self._type
327 # A tuple or a scalar is OK, but make them into a list
329 if type(data) == TupleType:
331 elif type(data) != ListType:
335 raise Exception, "too many values"
337 # Now check the types of all the components, and find
338 # the first nonzero element along the way.
342 for i in range(len(data)):
347 if type(data[i]) not in \
348 (IntType, LongType, FloatType):
349 raise Exception, "element %d a bad type" % i
351 if data[i] and f == -1:
354 # If they're all 0, just use zero seconds.
361 # Make sure only the last nonzero element has a decimal fraction
362 # and only the first element is negative.
366 for i in range(f, len(data)):
370 "all except the last nonzero element must be " \
372 if data[i] < 0 and i > f:
374 "only the first nonzero element can be negative"
375 elif data[i] != long(data[i]):
378 # Pad the list on the left if necessary.
384 data = [0] * n + data
386 # Save index of the first nonzero element and the decimal
387 # element for _marshalData.
389 self.__firstnonzero = f
393 raise ValueError, "invalid %s value - %s" % (self._type, e)
397 def _marshalData(self):
398 if self._cache == None:
402 if d[self.__firstnonzero] < 0:
409 for i in range(self.__firstnonzero, len(d)):
414 if self.__decimal == i:
415 s += "%g" % abs(d[i])
417 s += "%d" % long(abs(d[i]))
418 s += ['Y', 'M', 'D', 'H', 'M', 'S'][i]
424 class timeDurationType(durationType):
425 _validURIs = (NS.XSD, NS.XSD2, NS.ENC)
427 class dateTimeType(anyType):
428 _validURIs = (NS.XSD3,)
430 def _checkValueSpace(self, data):
435 if (type(data) in (IntType, LongType)):
436 data = list(time.gmtime(data)[:6])
437 elif (type(data) == FloatType):
439 data = list(time.gmtime(int(data))[:6])
441 elif type(data) in (ListType, TupleType):
443 raise Exception, "not enough values"
445 raise Exception, "too many values"
447 data = list(data[:6])
451 raise Exception, "invalid type"
453 raise ValueError, "invalid %s value - %s" % (self._type, e)
457 def _marshalData(self):
458 if self._cache == None:
460 s = "%04d-%02d-%02dT%02d:%02d:%02d" % ((abs(d[0]),) + d[1:])
472 class recurringInstantType(anyType):
473 _validURIs = (NS.XSD,)
475 def _checkValueSpace(self, data):
478 data = list(time.gmtime(time.time())[:6])
479 if (type(data) in (IntType, LongType)):
480 data = list(time.gmtime(data)[:6])
481 elif (type(data) == FloatType):
483 data = list(time.gmtime(int(data))[:6])
485 elif type(data) in (ListType, TupleType):
487 raise Exception, "not enough values"
489 raise Exception, "too many values"
491 data = list(data[:6])
494 data += [0] * (6 - len(data))
502 "only leftmost elements can be none"
509 raise Exception, "invalid type"
511 raise ValueError, "invalid %s value - %s" % (self._type, e)
515 def _marshalData(self):
516 if self._cache == None:
528 e[0] = '-' + "%02d" % e[0]
532 for i in range(1, len(e)):
533 if e[i] == None or (i < 3 and e[i] == 0):
543 f = abs(d[5] - int(d[5]))
546 e[5] += ("%g" % f)[1:]
548 s = "%s%s-%s-%sT%s:%s:%sZ" % ((neg,) + tuple(e))
554 class timeInstantType(dateTimeType):
555 _validURIs = (NS.XSD, NS.XSD2, NS.ENC)
557 class timePeriodType(dateTimeType):
558 _validURIs = (NS.XSD2, NS.ENC)
560 class timeType(anyType):
561 def _checkValueSpace(self, data):
564 data = time.gmtime(time.time())[3:6]
565 elif (type(data) == FloatType):
567 data = list(time.gmtime(int(data))[3:6])
569 elif type(data) in (IntType, LongType):
570 data = time.gmtime(data)[3:6]
571 elif type(data) in (ListType, TupleType):
575 raise Exception, "too many values"
577 data = [None, None, None] + list(data)
580 data += [0] * (6 - len(data))
586 raise Exception, "invalid type"
588 raise ValueError, "invalid %s value - %s" % (self._type, e)
592 def _marshalData(self):
593 if self._cache == None:
597 #s = time.strftime("%H:%M:%S", (0, 0, 0) + d + (0, 0, -1))
598 s = "%02d:%02d:%02d" % d
608 class dateType(anyType):
609 def _checkValueSpace(self, data):
612 data = time.gmtime(time.time())[0:3]
613 elif type(data) in (IntType, LongType, FloatType):
614 data = time.gmtime(data)[0:3]
615 elif type(data) in (ListType, TupleType):
619 raise Exception, "too many values"
624 data += [1, 1, 1][len(data):]
632 raise Exception, "invalid type"
634 raise ValueError, "invalid %s value - %s" % (self._type, e)
638 def _marshalData(self):
639 if self._cache == None:
641 s = "%04d-%02d-%02dZ" % ((abs(d[0]),) + d[1:])
649 class gYearMonthType(anyType):
650 _validURIs = (NS.XSD3,)
652 def _checkValueSpace(self, data):
655 data = time.gmtime(time.time())[0:2]
656 elif type(data) in (IntType, LongType, FloatType):
657 data = time.gmtime(data)[0:2]
658 elif type(data) in (ListType, TupleType):
662 raise Exception, "too many values"
667 data += [1, 1][len(data):]
675 raise Exception, "invalid type"
677 raise ValueError, "invalid %s value - %s" % (self._type, e)
681 def _marshalData(self):
682 if self._cache == None:
684 s = "%04d-%02dZ" % ((abs(d[0]),) + d[1:])
692 class gYearType(anyType):
693 _validURIs = (NS.XSD3,)
695 def _checkValueSpace(self, data):
698 data = time.gmtime(time.time())[0:1]
699 elif type(data) in (IntType, LongType, FloatType):
702 if type(data) in (ListType, TupleType):
706 raise Exception, "too few values"
708 raise Exception, "too many values"
710 if type(data[0]) == FloatType:
711 try: s = int(data[0])
712 except: s = long(data[0])
715 raise Exception, "not integral"
718 elif type(data[0]) not in (IntType, LongType):
719 raise Exception, "bad type"
721 raise Exception, "invalid type"
723 raise ValueError, "invalid %s value - %s" % (self._type, e)
727 def _marshalData(self):
728 if self._cache == None:
738 class centuryType(anyType):
739 _validURIs = (NS.XSD2, NS.ENC)
741 def _checkValueSpace(self, data):
744 data = time.gmtime(time.time())[0:1] / 100
745 elif type(data) in (IntType, LongType, FloatType):
748 if type(data) in (ListType, TupleType):
750 data = data[0:1] / 100
752 raise Exception, "too few values"
754 raise Exception, "too many values"
756 if type(data[0]) == FloatType:
757 try: s = int(data[0])
758 except: s = long(data[0])
761 raise Exception, "not integral"
764 elif type(data[0]) not in (IntType, LongType):
765 raise Exception, "bad type"
767 raise Exception, "invalid type"
769 raise ValueError, "invalid %s value - %s" % (self._type, e)
773 def _marshalData(self):
774 if self._cache == None:
784 class yearType(gYearType):
785 _validURIs = (NS.XSD2, NS.ENC)
787 class gMonthDayType(anyType):
788 _validURIs = (NS.XSD3,)
790 def _checkValueSpace(self, data):
793 data = time.gmtime(time.time())[1:3]
794 elif type(data) in (IntType, LongType, FloatType):
795 data = time.gmtime(data)[1:3]
796 elif type(data) in (ListType, TupleType):
800 raise Exception, "too many values"
805 data += [1, 1][len(data):]
807 data = [0] + data + [0, 0, 0]
813 raise Exception, "invalid type"
815 raise ValueError, "invalid %s value - %s" % (self._type, e)
819 def _marshalData(self):
820 if self._cache == None:
821 self._cache = "--%02d-%02dZ" % self._data
825 class recurringDateType(gMonthDayType):
826 _validURIs = (NS.XSD2, NS.ENC)
828 class gMonthType(anyType):
829 _validURIs = (NS.XSD3,)
831 def _checkValueSpace(self, data):
834 data = time.gmtime(time.time())[1:2]
835 elif type(data) in (IntType, LongType, FloatType):
838 if type(data) in (ListType, TupleType):
842 raise Exception, "too few values"
844 raise Exception, "too many values"
846 if type(data[0]) == FloatType:
847 try: s = int(data[0])
848 except: s = long(data[0])
851 raise Exception, "not integral"
854 elif type(data[0]) not in (IntType, LongType):
855 raise Exception, "bad type"
857 if data[0] < 1 or data[0] > 12:
858 raise Exception, "bad value"
860 raise Exception, "invalid type"
862 raise ValueError, "invalid %s value - %s" % (self._type, e)
866 def _marshalData(self):
867 if self._cache == None:
868 self._cache = "--%02d--Z" % self._data
872 class monthType(gMonthType):
873 _validURIs = (NS.XSD2, NS.ENC)
875 class gDayType(anyType):
876 _validURIs = (NS.XSD3,)
878 def _checkValueSpace(self, data):
881 data = time.gmtime(time.time())[2:3]
882 elif type(data) in (IntType, LongType, FloatType):
885 if type(data) in (ListType, TupleType):
889 raise Exception, "too few values"
891 raise Exception, "too many values"
893 if type(data[0]) == FloatType:
894 try: s = int(data[0])
895 except: s = long(data[0])
898 raise Exception, "not integral"
901 elif type(data[0]) not in (IntType, LongType):
902 raise Exception, "bad type"
904 if data[0] < 1 or data[0] > 31:
905 raise Exception, "bad value"
907 raise Exception, "invalid type"
909 raise ValueError, "invalid %s value - %s" % (self._type, e)
913 def _marshalData(self):
914 if self._cache == None:
915 self._cache = "---%02dZ" % self._data
919 class recurringDayType(gDayType):
920 _validURIs = (NS.XSD2, NS.ENC)
922 class hexBinaryType(anyType):
923 _validURIs = (NS.XSD3,)
925 def _checkValueSpace(self, data):
927 raise ValueError, "must supply initial %s value" % self._type
929 if type(data) not in (StringType, UnicodeType):
930 raise AttributeError, "invalid %s type" % self._type
934 def _marshalData(self):
935 if self._cache == None:
936 self._cache = encodeHexString(self._data)
940 class base64BinaryType(anyType):
941 _validURIs = (NS.XSD3,)
943 def _checkValueSpace(self, data):
945 raise ValueError, "must supply initial %s value" % self._type
947 if type(data) not in (StringType, UnicodeType):
948 raise AttributeError, "invalid %s type" % self._type
952 def _marshalData(self):
953 if self._cache == None:
954 self._cache = base64.encodestring(self._data)
958 class base64Type(base64BinaryType):
959 _validURIs = (NS.ENC,)
961 class binaryType(anyType):
962 _validURIs = (NS.XSD, NS.ENC)
964 def __init__(self, data, name = None, typed = 1, encoding = 'base64',
967 anyType.__init__(self, data, name, typed, attrs)
969 self._setAttr('encoding', encoding)
971 def _marshalData(self):
972 if self._cache == None:
973 if self._getAttr((None, 'encoding')) == 'base64':
974 self._cache = base64.encodestring(self._data)
976 self._cache = encodeHexString(self._data)
980 def _checkValueSpace(self, data):
982 raise ValueError, "must supply initial %s value" % self._type
984 if type(data) not in (StringType, UnicodeType):
985 raise AttributeError, "invalid %s type" % self._type
989 def _setAttr(self, attr, value):
990 attr = self._fixAttr(attr)
992 if attr[1] == 'encoding':
993 if attr[0] != None or value not in ('base64', 'hex'):
994 raise AttributeError, "invalid encoding"
998 anyType._setAttr(self, attr, value)
1001 class anyURIType(anyType):
1002 _validURIs = (NS.XSD3,)
1004 def _checkValueSpace(self, data):
1006 raise ValueError, "must supply initial %s value" % self._type
1008 if type(data) not in (StringType, UnicodeType):
1009 raise AttributeError, "invalid %s type" % self._type
1013 def _marshalData(self):
1014 if self._cache == None:
1015 self._cache = urllib.quote(self._data)
1019 class uriType(anyURIType):
1020 _validURIs = (NS.XSD,)
1022 class uriReferenceType(anyURIType):
1023 _validURIs = (NS.XSD2,)
1025 class NOTATIONType(anyType):
1026 def __init__(self, data, name = None, typed = 1, attrs = None):
1028 if self.__class__ == NOTATIONType:
1029 raise Error, "a NOTATION can't be instantiated directly"
1031 anyType.__init__(self, data, name, typed, attrs)
1033 class ENTITIESType(anyType):
1034 def _checkValueSpace(self, data):
1036 raise ValueError, "must supply initial %s value" % self._type
1038 if type(data) in (StringType, UnicodeType):
1041 if type(data) not in (ListType, TupleType) or \
1042 filter (lambda x: type(x) not in (StringType, UnicodeType), data):
1043 raise AttributeError, "invalid %s type" % self._type
1047 def _marshalData(self):
1048 return ' '.join(self._data)
1050 class IDREFSType(ENTITIESType): pass
1051 class NMTOKENSType(ENTITIESType): pass
1053 class integerType(anyType):
1054 def _checkValueSpace(self, data):
1056 raise ValueError, "must supply initial %s value" % self._type
1058 if type(data) not in (IntType, LongType):
1059 raise ValueError, "invalid %s value" % self._type
1063 class nonPositiveIntegerType(anyType):
1064 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1066 def _checkValueSpace(self, data):
1068 raise ValueError, "must supply initial %s value" % self._type
1070 if type(data) not in (IntType, LongType) or data > 0:
1071 raise ValueError, "invalid %s value" % self._type
1075 class non_Positive_IntegerType(nonPositiveIntegerType):
1076 _validURIs = (NS.XSD,)
1078 def _typeName(self):
1079 return 'non-positive-integer'
1081 class negativeIntegerType(anyType):
1082 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1084 def _checkValueSpace(self, data):
1086 raise ValueError, "must supply initial %s value" % self._type
1088 if type(data) not in (IntType, LongType) or data >= 0:
1089 raise ValueError, "invalid %s value" % self._type
1093 class negative_IntegerType(negativeIntegerType):
1094 _validURIs = (NS.XSD,)
1096 def _typeName(self):
1097 return 'negative-integer'
1099 class longType(anyType):
1100 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1102 def _checkValueSpace(self, data):
1104 raise ValueError, "must supply initial %s value" % self._type
1106 if type(data) not in (IntType, LongType) or \
1107 data < -9223372036854775808L or \
1108 data > 9223372036854775807L:
1109 raise ValueError, "invalid %s value" % self._type
1113 class intType(anyType):
1114 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1116 def _checkValueSpace(self, data):
1118 raise ValueError, "must supply initial %s value" % self._type
1120 if type(data) not in (IntType, LongType) or \
1121 data < -2147483648L or \
1123 raise ValueError, "invalid %s value" % self._type
1127 class shortType(anyType):
1128 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1130 def _checkValueSpace(self, data):
1132 raise ValueError, "must supply initial %s value" % self._type
1134 if type(data) not in (IntType, LongType) or \
1137 raise ValueError, "invalid %s value" % self._type
1141 class byteType(anyType):
1142 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1144 def _checkValueSpace(self, data):
1146 raise ValueError, "must supply initial %s value" % self._type
1148 if type(data) not in (IntType, LongType) or \
1151 raise ValueError, "invalid %s value" % self._type
1155 class nonNegativeIntegerType(anyType):
1156 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1158 def _checkValueSpace(self, data):
1160 raise ValueError, "must supply initial %s value" % self._type
1162 if type(data) not in (IntType, LongType) or data < 0:
1163 raise ValueError, "invalid %s value" % self._type
1167 class non_Negative_IntegerType(nonNegativeIntegerType):
1168 _validURIs = (NS.XSD,)
1170 def _typeName(self):
1171 return 'non-negative-integer'
1173 class unsignedLongType(anyType):
1174 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1176 def _checkValueSpace(self, data):
1178 raise ValueError, "must supply initial %s value" % self._type
1180 if type(data) not in (IntType, LongType) or \
1182 data > 18446744073709551615L:
1183 raise ValueError, "invalid %s value" % self._type
1187 class unsignedIntType(anyType):
1188 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1190 def _checkValueSpace(self, data):
1192 raise ValueError, "must supply initial %s value" % self._type
1194 if type(data) not in (IntType, LongType) or \
1197 raise ValueError, "invalid %s value" % self._type
1201 class unsignedShortType(anyType):
1202 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1204 def _checkValueSpace(self, data):
1206 raise ValueError, "must supply initial %s value" % self._type
1208 if type(data) not in (IntType, LongType) or \
1211 raise ValueError, "invalid %s value" % self._type
1215 class unsignedByteType(anyType):
1216 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1218 def _checkValueSpace(self, data):
1220 raise ValueError, "must supply initial %s value" % self._type
1222 if type(data) not in (IntType, LongType) or \
1225 raise ValueError, "invalid %s value" % self._type
1229 class positiveIntegerType(anyType):
1230 _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
1232 def _checkValueSpace(self, data):
1234 raise ValueError, "must supply initial %s value" % self._type
1236 if type(data) not in (IntType, LongType) or data <= 0:
1237 raise ValueError, "invalid %s value" % self._type
1241 class positive_IntegerType(positiveIntegerType):
1242 _validURIs = (NS.XSD,)
1244 def _typeName(self):
1245 return 'positive-integer'
1247 # Now compound types
1249 class compoundType(anyType):
1250 def __init__(self, data = None, name = None, typed = 1, attrs = None):
1251 if self.__class__ == compoundType:
1252 raise Error, "a compound can't be instantiated directly"
1254 anyType.__init__(self, data, name, typed, attrs)
1257 if type(data) == DictType:
1258 self.__dict__.update(data)
1260 def _aslist(self, item=None):
1261 if item is not None:
1262 return self.__dict__[self._keyord[item]]
1264 return map( lambda x: self.__dict__[x], self._keyord)
1266 def _asdict(self, item=None, encoding=Config.dict_encoding):
1267 if item is not None:
1268 if type(item) in (UnicodeType,StringType):
1269 item = item.encode(encoding)
1270 return self.__dict__[item]
1273 def fun(x): retval[x.encode(encoding)] = self.__dict__[x]
1275 if hasattr(self, '_keyord'):
1276 map( fun, self._keyord)
1278 for name in dir(self):
1280 retval[name] = getattr(self,name)
1284 def __getitem__(self, item):
1285 if type(item) == IntType:
1286 return self.__dict__[self._keyord[item]]
1288 return getattr(self, item)
1291 return len(self._keyord)
1293 def __nonzero__(self):
1297 return filter(lambda x: x[0] != '_', self.__dict__.keys())
1299 def _addItem(self, name, value, attrs = None):
1301 if name in self._keyord:
1302 if type(self.__dict__[name]) != ListType:
1303 self.__dict__[name] = [self.__dict__[name]]
1304 self.__dict__[name].append(value)
1306 self.__dict__[name] = value
1307 self._keyord.append(name)
1309 def _placeItem(self, name, value, pos, subpos = 0, attrs = None):
1311 if subpos == 0 and type(self.__dict__[name]) != ListType:
1312 self.__dict__[name] = value
1314 self.__dict__[name][subpos] = value
1316 # only add to key order list if it does not already
1318 if not (name in self._keyord):
1320 self._keyord[pos] = name
1322 self._keyord.append(name)
1325 def _getItemAsList(self, name, default = []):
1327 d = self.__dict__[name]
1331 if type(d) == ListType:
1336 return anyType.__str__(self) + ": " + str(self._asdict())
1339 return self.__str__()
1341 class structType(compoundType):
1344 class headerType(structType):
1345 _validURIs = (NS.ENV,)
1347 def __init__(self, data = None, typed = 1, attrs = None):
1348 structType.__init__(self, data, "Header", typed, attrs)
1350 class bodyType(structType):
1351 _validURIs = (NS.ENV,)
1353 def __init__(self, data = None, typed = 1, attrs = None):
1354 structType.__init__(self, data, "Body", typed, attrs)
1356 class arrayType(UserList.UserList, compoundType):
1357 def __init__(self, data = None, name = None, attrs = None,
1358 offset = 0, rank = None, asize = 0, elemsname = None):
1361 if type(data) not in (ListType, TupleType):
1362 raise Error, "Data must be a sequence"
1364 UserList.UserList.__init__(self, data)
1365 compoundType.__init__(self, data, name, 0, attrs)
1367 self._elemsname = elemsname or "item"
1372 # According to 5.4.2.2 in the SOAP spec, each element in a
1373 # sparse array must have a position. _posstate keeps track of
1374 # whether we've seen a position or not. It's possible values
1376 # -1 No elements have been added, so the state is indeterminate
1377 # 0 An element without a position has been added, so no
1378 # elements can have positions
1379 # 1 An element with a position has been added, so all elements
1380 # must have positions
1386 if asize in ('', None):
1389 self._dims = map (lambda x: int(x), str(asize).split(','))
1390 self._dims.reverse() # It's easier to work with this way
1391 self._poss = [0] * len(self._dims) # This will end up
1394 for i in range(len(self._dims)):
1395 if self._dims[i] < 0 or \
1396 self._dims[i] == 0 and len(self._dims) > 1:
1397 raise TypeError, "invalid Array dimensions"
1400 self._poss[i] = offset % self._dims[i]
1401 offset = int(offset / self._dims[i])
1403 # Don't break out of the loop if offset is 0 so we test all the
1404 # dimensions for > 0.
1406 raise AttributeError, "invalid Array offset"
1408 a = [None] * self._dims[0]
1410 for i in range(1, len(self._dims)):
1413 for j in range(self._dims[i]):
1414 b.append(copy.deepcopy(a))
1421 def _aslist(self, item=None):
1422 if item is not None:
1423 return self.data[int(item)]
1427 def _asdict(self, item=None, encoding=Config.dict_encoding):
1428 if item is not None:
1429 if type(item) in (UnicodeType,StringType):
1430 item = item.encode(encoding)
1431 return self.data[int(item)]
1434 def fun(x): retval[str(x).encode(encoding)] = self.data[x]
1436 map( fun, range(len(self.data)) )
1439 def __getitem__(self, item):
1441 return self.data[int(item)]
1443 return getattr(self, item)
1446 return len(self.data)
1448 def __nonzero__(self):
1452 return anyType.__str__(self) + ": " + str(self._aslist())
1455 return filter(lambda x: x[0] != '_', self.__dict__.keys())
1457 def _addItem(self, name, value, attrs):
1459 raise ValueError, "Array is full"
1461 pos = attrs.get((NS.ENC, 'position'))
1464 if self._posstate == 0:
1465 raise AttributeError, \
1466 "all elements in a sparse Array must have a " \
1467 "position attribute"
1472 if pos[0] == '[' and pos[-1] == ']':
1473 pos = map (lambda x: int(x), pos[1:-1].split(','))
1479 curpos = [0] * len(self._dims)
1481 for i in range(len(self._dims)):
1482 curpos[i] = pos % self._dims[i]
1483 pos = int(pos / self._dims[i])
1490 elif len(pos) != len(self._dims):
1493 for i in range(len(self._dims)):
1494 if pos[i] >= self._dims[i]:
1501 raise AttributeError, \
1502 "invalid Array element position %s" % str(pos)
1504 if self._posstate == 1:
1505 raise AttributeError, \
1506 "only elements in a sparse Array may have a " \
1507 "position attribute"
1515 for i in range(len(self._dims) - 1, 0, -1):
1518 if curpos[0] >= len(a):
1519 a += [None] * (len(a) - curpos[0] + 1)
1521 a[curpos[0]] = value
1526 for i in range(len(self._dims) - 1):
1527 if self._poss[i] < self._dims[i]:
1531 self._poss[i + 1] += 1
1533 if self._dims[-1] and self._poss[-1] >= self._dims[-1]:
1535 #FIXME: why is this occuring?
1538 def _placeItem(self, name, value, pos, subpos, attrs = None):
1539 curpos = [0] * len(self._dims)
1541 for i in range(len(self._dims)):
1542 if self._dims[i] == 0:
1546 curpos[i] = pos % self._dims[i]
1547 pos = int(pos / self._dims[i])
1552 if self._dims[i] != 0 and pos:
1553 raise Error, "array index out of range"
1557 for i in range(len(self._dims) - 1, 0, -1):
1560 if curpos[0] >= len(a):
1561 a += [None] * (len(a) - curpos[0] + 1)
1563 a[curpos[0]] = value
1565 class typedArrayType(arrayType):
1566 def __init__(self, data = None, name = None, typed = None, attrs = None,
1567 offset = 0, rank = None, asize = 0, elemsname = None, complexType = 0):
1569 arrayType.__init__(self, data, name, attrs, offset, rank, asize,
1574 self._complexType = complexType
1576 class faultType(structType, Error):
1577 def __init__(self, faultcode = "", faultstring = "", detail = None):
1578 self.faultcode = faultcode
1579 self.faultstring = faultstring
1581 self.detail = detail
1583 structType.__init__(self, None, 0)
1585 def _setDetail(self, detail = None):
1587 self.detail = detail
1589 try: del self.detail
1590 except AttributeError: pass
1593 if getattr(self, 'detail', None) != None:
1594 return "<Fault %s: %s: %s>" % (self.faultcode,
1598 return "<Fault %s: %s>" % (self.faultcode, self.faultstring)
1603 return (self.faultcode, self.faultstring, self.detail)
1605 class SOAPException(Exception):
1606 def __init__(self, code="", string="", detail=None):
1607 self.value = ("SOAPpy SOAP Exception", code, string, detail)
1609 self.string = string
1610 self.detail = detail
1613 return repr(self.value)
1615 class RequiredHeaderMismatch(Exception):
1616 def __init__(self, value):
1620 return repr(self.value)
1622 class MethodNotFound(Exception):
1623 def __init__(self, value):
1624 (val, detail) = value.split(":")
1626 self.detail = detail
1629 return repr(self.value, self.detail)
1631 class AuthorizationFailed(Exception):
1632 def __init__(self, value):
1636 return repr(self.value)
1638 class MethodFailed(Exception):
1639 def __init__(self, value):
1643 return repr(self.value)
1646 # Convert complex SOAPpy objects to native python equivalents
1649 def simplify(object, level=0):
1651 Convert the SOAPpy objects and their contents to simple python types.
1653 This function recursively converts the passed 'container' object,
1654 and all public subobjects. (Private subobjects have names that
1658 - faultType --> raise python exception
1659 - arrayType --> array
1660 - compoundType --> dictionary
1666 if isinstance( object, faultType ):
1667 if object.faultstring == "Required Header Misunderstood":
1668 raise RequiredHeaderMismatch(object.detail)
1669 elif object.faultstring == "Method Not Found":
1670 raise MethodNotFound(object.detail)
1671 elif object.faultstring == "Authorization Failed":
1672 raise AuthorizationFailed(object.detail)
1673 elif object.faultstring == "Method Failed":
1674 raise MethodFailed(object.detail)
1676 se = SOAPException(object.faultcode, object.faultstring,
1679 elif isinstance( object, arrayType ):
1680 data = object._aslist()
1681 for k in range(len(data)):
1682 data[k] = simplify(data[k], level=level+1)
1684 elif isinstance( object, compoundType ) or isinstance(object, structType):
1685 data = object._asdict()
1686 for k in data.keys():
1688 data[k] = simplify(data[k], level=level+1)
1690 elif type(object)==DictType:
1691 for k in object.keys():
1693 object[k] = simplify(object[k])
1695 elif type(object)==list:
1696 for k in range(len(object)):
1697 object[k] = simplify(object[k])
1703 def simplify_contents(object, level=0):
1705 Convert the contents of SOAPpy objects to simple python types.
1707 This function recursively converts the sub-objects contained in a
1708 'container' object to simple python types.
1711 - faultType --> raise python exception
1712 - arrayType --> array
1713 - compoundType --> dictionary
1716 if level>10: return object
1718 if isinstance( object, faultType ):
1719 for k in object._keys():
1721 setattr(object, k, simplify(object[k], level=level+1))
1723 elif isinstance( object, arrayType ):
1724 data = object._aslist()
1725 for k in range(len(data)):
1726 object[k] = simplify(data[k], level=level+1)
1727 elif isinstance(object, structType):
1728 data = object._asdict()
1729 for k in data.keys():
1731 setattr(object, k, simplify(data[k], level=level+1))
1732 elif isinstance( object, compoundType ) :
1733 data = object._asdict()
1734 for k in data.keys():
1736 object[k] = simplify(data[k], level=level+1)
1737 elif type(object)==DictType:
1738 for k in object.keys():
1740 object[k] = simplify(object[k])
1741 elif type(object)==list:
1742 for k in range(len(object)):
1743 object[k] = simplify(object[k])