A Python UPnP Media Server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1735 lines
50 KiB

  1. """
  2. ################################################################################
  3. # Copyright (c) 2003, Pfizer
  4. # Copyright (c) 2001, Cayce Ullman.
  5. # Copyright (c) 2001, Brian Matthews.
  6. #
  7. # All rights reserved.
  8. #
  9. # Redistribution and use in source and binary forms, with or without
  10. # modification, are permitted provided that the following conditions are met:
  11. # Redistributions of source code must retain the above copyright notice, this
  12. # list of conditions and the following disclaimer.
  13. #
  14. # Redistributions in binary form must reproduce the above copyright notice,
  15. # this list of conditions and the following disclaimer in the documentation
  16. # and/or other materials provided with the distribution.
  17. #
  18. # Neither the name of actzero, inc. nor the names of its contributors may
  19. # be used to endorse or promote products derived from this software without
  20. # specific prior written permission.
  21. #
  22. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
  26. # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  29. # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. #
  33. ################################################################################
  34. """
  35. ident = '$Id: Types.py,v 1.17 2004/09/11 03:03:33 warnes Exp $'
  36. from version import __version__
  37. from __future__ import nested_scopes
  38. import UserList
  39. import base64
  40. import cgi
  41. import urllib
  42. import copy
  43. import re
  44. import time
  45. from types import *
  46. # SOAPpy modules
  47. from Errors import *
  48. from NS import NS
  49. from Utilities import encodeHexString, cleanDate
  50. from Config import Config
  51. ###############################################################################
  52. # Utility functions
  53. ###############################################################################
  54. def isPrivate(name): return name[0]=='_'
  55. def isPublic(name): return name[0]!='_'
  56. ###############################################################################
  57. # Types and Wrappers
  58. ###############################################################################
  59. class anyType:
  60. _validURIs = (NS.XSD, NS.XSD2, NS.XSD3, NS.ENC)
  61. def __init__(self, data = None, name = None, typed = 1, attrs = None):
  62. if self.__class__ == anyType:
  63. raise Error, "anyType can't be instantiated directly"
  64. if type(name) in (ListType, TupleType):
  65. self._ns, self._name = name
  66. else:
  67. self._ns = self._validURIs[0]
  68. self._name = name
  69. self._typed = typed
  70. self._attrs = {}
  71. self._cache = None
  72. self._type = self._typeName()
  73. self._data = self._checkValueSpace(data)
  74. if attrs != None:
  75. self._setAttrs(attrs)
  76. def __str__(self):
  77. if hasattr(self,'_name') and self._name:
  78. return "<%s %s at %d>" % (self.__class__, self._name, id(self))
  79. return "<%s at %d>" % (self.__class__, id(self))
  80. __repr__ = __str__
  81. def _checkValueSpace(self, data):
  82. return data
  83. def _marshalData(self):
  84. return str(self._data)
  85. def _marshalAttrs(self, ns_map, builder):
  86. a = ''
  87. for attr, value in self._attrs.items():
  88. ns, n = builder.genns(ns_map, attr[0])
  89. a += n + ' %s%s="%s"' % \
  90. (ns, attr[1], cgi.escape(str(value), 1))
  91. return a
  92. def _fixAttr(self, attr):
  93. if type(attr) in (StringType, UnicodeType):
  94. attr = (None, attr)
  95. elif type(attr) == ListType:
  96. attr = tuple(attr)
  97. elif type(attr) != TupleType:
  98. raise AttributeError, "invalid attribute type"
  99. if len(attr) != 2:
  100. raise AttributeError, "invalid attribute length"
  101. if type(attr[0]) not in (NoneType, StringType, UnicodeType):
  102. raise AttributeError, "invalid attribute namespace URI type"
  103. return attr
  104. def _getAttr(self, attr):
  105. attr = self._fixAttr(attr)
  106. try:
  107. return self._attrs[attr]
  108. except:
  109. return None
  110. def _setAttr(self, attr, value):
  111. attr = self._fixAttr(attr)
  112. if type(value) is StringType:
  113. value = unicode(value)
  114. self._attrs[attr] = value
  115. def _setAttrs(self, attrs):
  116. if type(attrs) in (ListType, TupleType):
  117. for i in range(0, len(attrs), 2):
  118. self._setAttr(attrs[i], attrs[i + 1])
  119. return
  120. if type(attrs) == DictType:
  121. d = attrs
  122. elif isinstance(attrs, anyType):
  123. d = attrs._attrs
  124. else:
  125. raise AttributeError, "invalid attribute type"
  126. for attr, value in d.items():
  127. self._setAttr(attr, value)
  128. def _setMustUnderstand(self, val):
  129. self._setAttr((NS.ENV, "mustUnderstand"), val)
  130. def _getMustUnderstand(self):
  131. return self._getAttr((NS.ENV, "mustUnderstand"))
  132. def _setActor(self, val):
  133. self._setAttr((NS.ENV, "actor"), val)
  134. def _getActor(self):
  135. return self._getAttr((NS.ENV, "actor"))
  136. def _typeName(self):
  137. return self.__class__.__name__[:-4]
  138. def _validNamespaceURI(self, URI, strict):
  139. if not hasattr(self, '_typed') or not self._typed:
  140. return None
  141. if URI in self._validURIs:
  142. return URI
  143. if not strict:
  144. return self._ns
  145. raise AttributeError, \
  146. "not a valid namespace for type %s" % self._type
  147. class voidType(anyType):
  148. pass
  149. class stringType(anyType):
  150. def _checkValueSpace(self, data):
  151. if data == None:
  152. raise ValueError, "must supply initial %s value" % self._type
  153. if type(data) not in (StringType, UnicodeType):
  154. raise AttributeError, "invalid %s type:" % self._type
  155. return data
  156. class untypedType(stringType):
  157. def __init__(self, data = None, name = None, attrs = None):
  158. stringType.__init__(self, data, name, 0, attrs)
  159. class IDType(stringType): pass
  160. class NCNameType(stringType): pass
  161. class NameType(stringType): pass
  162. class ENTITYType(stringType): pass
  163. class IDREFType(stringType): pass
  164. class languageType(stringType): pass
  165. class NMTOKENType(stringType): pass
  166. class QNameType(stringType): pass
  167. class tokenType(anyType):
  168. _validURIs = (NS.XSD2, NS.XSD3)
  169. __invalidre = '[\n\t]|^ | $| '
  170. def _checkValueSpace(self, data):
  171. if data == None:
  172. raise ValueError, "must supply initial %s value" % self._type
  173. if type(data) not in (StringType, UnicodeType):
  174. raise AttributeError, "invalid %s type" % self._type
  175. if type(self.__invalidre) == StringType:
  176. self.__invalidre = re.compile(self.__invalidre)
  177. if self.__invalidre.search(data):
  178. raise ValueError, "invalid %s value" % self._type
  179. return data
  180. class normalizedStringType(anyType):
  181. _validURIs = (NS.XSD3,)
  182. __invalidre = '[\n\r\t]'
  183. def _checkValueSpace(self, data):
  184. if data == None:
  185. raise ValueError, "must supply initial %s value" % self._type
  186. if type(data) not in (StringType, UnicodeType):
  187. raise AttributeError, "invalid %s type" % self._type
  188. if type(self.__invalidre) == StringType:
  189. self.__invalidre = re.compile(self.__invalidre)
  190. if self.__invalidre.search(data):
  191. raise ValueError, "invalid %s value" % self._type
  192. return data
  193. class CDATAType(normalizedStringType):
  194. _validURIs = (NS.XSD2,)
  195. class booleanType(anyType):
  196. def __int__(self):
  197. return self._data
  198. __nonzero__ = __int__
  199. def _marshalData(self):
  200. return ['false', 'true'][self._data]
  201. def _checkValueSpace(self, data):
  202. if data == None:
  203. raise ValueError, "must supply initial %s value" % self._type
  204. if data in (0, '0', 'false', ''):
  205. return 0
  206. if data in (1, '1', 'true'):
  207. return 1
  208. raise ValueError, "invalid %s value" % self._type
  209. class decimalType(anyType):
  210. def _checkValueSpace(self, data):
  211. if data == None:
  212. raise ValueError, "must supply initial %s value" % self._type
  213. if type(data) not in (IntType, LongType, FloatType):
  214. raise Error, "invalid %s value" % self._type
  215. return data
  216. class floatType(anyType):
  217. def _checkValueSpace(self, data):
  218. if data == None:
  219. raise ValueError, "must supply initial %s value" % self._type
  220. if type(data) not in (IntType, LongType, FloatType) or \
  221. data < -3.4028234663852886E+38 or \
  222. data > 3.4028234663852886E+38:
  223. raise ValueError, "invalid %s value: %s" % (self._type, repr(data))
  224. return data
  225. def _marshalData(self):
  226. return "%.18g" % self._data # More precision
  227. class doubleType(anyType):
  228. def _checkValueSpace(self, data):
  229. if data == None:
  230. raise ValueError, "must supply initial %s value" % self._type
  231. if type(data) not in (IntType, LongType, FloatType) or \
  232. data < -1.7976931348623158E+308 or \
  233. data > 1.7976931348623157E+308:
  234. raise ValueError, "invalid %s value: %s" % (self._type, repr(data))
  235. return data
  236. def _marshalData(self):
  237. return "%.18g" % self._data # More precision
  238. class durationType(anyType):
  239. _validURIs = (NS.XSD3,)
  240. def _checkValueSpace(self, data):
  241. if data == None:
  242. raise ValueError, "must supply initial %s value" % self._type
  243. try:
  244. # A tuple or a scalar is OK, but make them into a list
  245. if type(data) == TupleType:
  246. data = list(data)
  247. elif type(data) != ListType:
  248. data = [data]
  249. if len(data) > 6:
  250. raise Exception, "too many values"
  251. # Now check the types of all the components, and find
  252. # the first nonzero element along the way.
  253. f = -1
  254. for i in range(len(data)):
  255. if data[i] == None:
  256. data[i] = 0
  257. continue
  258. if type(data[i]) not in \
  259. (IntType, LongType, FloatType):
  260. raise Exception, "element %d a bad type" % i
  261. if data[i] and f == -1:
  262. f = i
  263. # If they're all 0, just use zero seconds.
  264. if f == -1:
  265. self._cache = 'PT0S'
  266. return (0,) * 6
  267. # Make sure only the last nonzero element has a decimal fraction
  268. # and only the first element is negative.
  269. d = -1
  270. for i in range(f, len(data)):
  271. if data[i]:
  272. if d != -1:
  273. raise Exception, \
  274. "all except the last nonzero element must be " \
  275. "integers"
  276. if data[i] < 0 and i > f:
  277. raise Exception, \
  278. "only the first nonzero element can be negative"
  279. elif data[i] != long(data[i]):
  280. d = i
  281. # Pad the list on the left if necessary.
  282. if len(data) < 6:
  283. n = 6 - len(data)
  284. f += n
  285. d += n
  286. data = [0] * n + data
  287. # Save index of the first nonzero element and the decimal
  288. # element for _marshalData.
  289. self.__firstnonzero = f
  290. self.__decimal = d
  291. except Exception, e:
  292. raise ValueError, "invalid %s value - %s" % (self._type, e)
  293. return tuple(data)
  294. def _marshalData(self):
  295. if self._cache == None:
  296. d = self._data
  297. t = 0
  298. if d[self.__firstnonzero] < 0:
  299. s = '-P'
  300. else:
  301. s = 'P'
  302. t = 0
  303. for i in range(self.__firstnonzero, len(d)):
  304. if d[i]:
  305. if i > 2 and not t:
  306. s += 'T'
  307. t = 1
  308. if self.__decimal == i:
  309. s += "%g" % abs(d[i])
  310. else:
  311. s += "%d" % long(abs(d[i]))
  312. s += ['Y', 'M', 'D', 'H', 'M', 'S'][i]
  313. self._cache = s
  314. return self._cache
  315. class timeDurationType(durationType):
  316. _validURIs = (NS.XSD, NS.XSD2, NS.ENC)
  317. class dateTimeType(anyType):
  318. _validURIs = (NS.XSD3,)
  319. def _checkValueSpace(self, data):
  320. try:
  321. if data == None:
  322. data = time.time()
  323. if (type(data) in (IntType, LongType)):
  324. data = list(time.gmtime(data)[:6])
  325. elif (type(data) == FloatType):
  326. f = data - int(data)
  327. data = list(time.gmtime(int(data))[:6])
  328. data[5] += f
  329. elif type(data) in (ListType, TupleType):
  330. if len(data) < 6:
  331. raise Exception, "not enough values"
  332. if len(data) > 9:
  333. raise Exception, "too many values"
  334. data = list(data[:6])
  335. cleanDate(data)
  336. else:
  337. raise Exception, "invalid type"
  338. except Exception, e:
  339. raise ValueError, "invalid %s value - %s" % (self._type, e)
  340. return tuple(data)
  341. def _marshalData(self):
  342. if self._cache == None:
  343. d = self._data
  344. s = "%04d-%02d-%02dT%02d:%02d:%02d" % ((abs(d[0]),) + d[1:])
  345. if d[0] < 0:
  346. s = '-' + s
  347. f = d[5] - int(d[5])
  348. if f != 0:
  349. s += ("%g" % f)[1:]
  350. s += 'Z'
  351. self._cache = s
  352. return self._cache
  353. class recurringInstantType(anyType):
  354. _validURIs = (NS.XSD,)
  355. def _checkValueSpace(self, data):
  356. try:
  357. if data == None:
  358. data = list(time.gmtime(time.time())[:6])
  359. if (type(data) in (IntType, LongType)):
  360. data = list(time.gmtime(data)[:6])
  361. elif (type(data) == FloatType):
  362. f = data - int(data)
  363. data = list(time.gmtime(int(data))[:6])
  364. data[5] += f
  365. elif type(data) in (ListType, TupleType):
  366. if len(data) < 1:
  367. raise Exception, "not enough values"
  368. if len(data) > 9:
  369. raise Exception, "too many values"
  370. data = list(data[:6])
  371. if len(data) < 6:
  372. data += [0] * (6 - len(data))
  373. f = len(data)
  374. for i in range(f):
  375. if data[i] == None:
  376. if f < i:
  377. raise Exception, \
  378. "only leftmost elements can be none"
  379. else:
  380. f = i
  381. break
  382. cleanDate(data, f)
  383. else:
  384. raise Exception, "invalid type"
  385. except Exception, e:
  386. raise ValueError, "invalid %s value - %s" % (self._type, e)
  387. return tuple(data)
  388. def _marshalData(self):
  389. if self._cache == None:
  390. d = self._data
  391. e = list(d)
  392. neg = ''
  393. if not e[0]:
  394. e[0] = '--'
  395. else:
  396. if e[0] < 0:
  397. neg = '-'
  398. e[0] = abs(e[0])
  399. if e[0] < 100:
  400. e[0] = '-' + "%02d" % e[0]
  401. else:
  402. e[0] = "%04d" % e[0]
  403. for i in range(1, len(e)):
  404. if e[i] == None or (i < 3 and e[i] == 0):
  405. e[i] = '-'
  406. else:
  407. if e[i] < 0:
  408. neg = '-'
  409. e[i] = abs(e[i])
  410. e[i] = "%02d" % e[i]
  411. if d[5]:
  412. f = abs(d[5] - int(d[5]))
  413. if f:
  414. e[5] += ("%g" % f)[1:]
  415. s = "%s%s-%s-%sT%s:%s:%sZ" % ((neg,) + tuple(e))
  416. self._cache = s
  417. return self._cache
  418. class timeInstantType(dateTimeType):
  419. _validURIs = (NS.XSD, NS.XSD2, NS.ENC)
  420. class timePeriodType(dateTimeType):
  421. _validURIs = (NS.XSD2, NS.ENC)
  422. class timeType(anyType):
  423. def _checkValueSpace(self, data):
  424. try:
  425. if data == None:
  426. data = time.gmtime(time.time())[3:6]
  427. elif (type(data) == FloatType):
  428. f = data - int(data)
  429. data = list(time.gmtime(int(data))[3:6])
  430. data[2] += f
  431. elif type(data) in (IntType, LongType):
  432. data = time.gmtime(data)[3:6]
  433. elif type(data) in (ListType, TupleType):
  434. if len(data) == 9:
  435. data = data[3:6]
  436. elif len(data) > 3:
  437. raise Exception, "too many values"
  438. data = [None, None, None] + list(data)
  439. if len(data) < 6:
  440. data += [0] * (6 - len(data))
  441. cleanDate(data, 3)
  442. data = data[3:]
  443. else:
  444. raise Exception, "invalid type"
  445. except Exception, e:
  446. raise ValueError, "invalid %s value - %s" % (self._type, e)
  447. return tuple(data)
  448. def _marshalData(self):
  449. if self._cache == None:
  450. d = self._data
  451. s = ''
  452. s = time.strftime("%H:%M:%S", (0, 0, 0) + d + (0, 0, -1))
  453. f = d[2] - int(d[2])
  454. if f != 0:
  455. s += ("%g" % f)[1:]
  456. s += 'Z'
  457. self._cache = s
  458. return self._cache
  459. class dateType(anyType):
  460. def _checkValueSpace(self, data):
  461. try:
  462. if data == None:
  463. data = time.gmtime(time.time())[0:3]
  464. elif type(data) in (IntType, LongType, FloatType):
  465. data = time.gmtime(data)[0:3]
  466. elif type(data) in (ListType, TupleType):
  467. if len(data) == 9:
  468. data = data[0:3]
  469. elif len(data) > 3:
  470. raise Exception, "too many values"
  471. data = list(data)
  472. if len(data) < 3:
  473. data += [1, 1, 1][len(data):]
  474. data += [0, 0, 0]
  475. cleanDate(data)
  476. data = data[:3]
  477. else:
  478. raise Exception, "invalid type"
  479. except Exception, e:
  480. raise ValueError, "invalid %s value - %s" % (self._type, e)
  481. return tuple(data)
  482. def _marshalData(self):
  483. if self._cache == None:
  484. d = self._data
  485. s = "%04d-%02d-%02dZ" % ((abs(d[0]),) + d[1:])
  486. if d[0] < 0:
  487. s = '-' + s
  488. self._cache = s
  489. return self._cache
  490. class gYearMonthType(anyType):
  491. _validURIs = (NS.XSD3,)
  492. def _checkValueSpace(self, data):
  493. try:
  494. if data == None:
  495. data = time.gmtime(time.time())[0:2]
  496. elif type(data) in (IntType, LongType, FloatType):
  497. data = time.gmtime(data)[0:2]
  498. elif type(data) in (ListType, TupleType):
  499. if len(data) == 9:
  500. data = data[0:2]
  501. elif len(data) > 2:
  502. raise Exception, "too many values"
  503. data = list(data)
  504. if len(data) < 2:
  505. data += [1, 1][len(data):]
  506. data += [1, 0, 0, 0]
  507. cleanDate(data)
  508. data = data[:2]
  509. else:
  510. raise Exception, "invalid type"
  511. except Exception, e:
  512. raise ValueError, "invalid %s value - %s" % (self._type, e)
  513. return tuple(data)
  514. def _marshalData(self):
  515. if self._cache == None:
  516. d = self._data
  517. s = "%04d-%02dZ" % ((abs(d[0]),) + d[1:])
  518. if d[0] < 0:
  519. s = '-' + s
  520. self._cache = s
  521. return self._cache
  522. class gYearType(anyType):
  523. _validURIs = (NS.XSD3,)
  524. def _checkValueSpace(self, data):
  525. try:
  526. if data == None:
  527. data = time.gmtime(time.time())[0:1]
  528. elif type(data) in (IntType, LongType, FloatType):
  529. data = [data]
  530. if type(data) in (ListType, TupleType):
  531. if len(data) == 9:
  532. data = data[0:1]
  533. elif len(data) < 1:
  534. raise Exception, "too few values"
  535. elif len(data) > 1:
  536. raise Exception, "too many values"
  537. if type(data[0]) == FloatType:
  538. try: s = int(data[0])
  539. except: s = long(data[0])
  540. if s != data[0]:
  541. raise Exception, "not integral"
  542. data = [s]
  543. elif type(data[0]) not in (IntType, LongType):
  544. raise Exception, "bad type"
  545. else:
  546. raise Exception, "invalid type"
  547. except Exception, e:
  548. raise ValueError, "invalid %s value - %s" % (self._type, e)
  549. return data[0]
  550. def _marshalData(self):
  551. if self._cache == None:
  552. d = self._data
  553. s = "%04dZ" % abs(d)
  554. if d < 0:
  555. s = '-' + s
  556. self._cache = s
  557. return self._cache
  558. class centuryType(anyType):
  559. _validURIs = (NS.XSD2, NS.ENC)
  560. def _checkValueSpace(self, data):
  561. try:
  562. if data == None:
  563. data = time.gmtime(time.time())[0:1] / 100
  564. elif type(data) in (IntType, LongType, FloatType):
  565. data = [data]
  566. if type(data) in (ListType, TupleType):
  567. if len(data) == 9:
  568. data = data[0:1] / 100
  569. elif len(data) < 1:
  570. raise Exception, "too few values"
  571. elif len(data) > 1:
  572. raise Exception, "too many values"
  573. if type(data[0]) == FloatType:
  574. try: s = int(data[0])
  575. except: s = long(data[0])
  576. if s != data[0]:
  577. raise Exception, "not integral"
  578. data = [s]
  579. elif type(data[0]) not in (IntType, LongType):
  580. raise Exception, "bad type"
  581. else:
  582. raise Exception, "invalid type"
  583. except Exception, e:
  584. raise ValueError, "invalid %s value - %s" % (self._type, e)
  585. return data[0]
  586. def _marshalData(self):
  587. if self._cache == None:
  588. d = self._data
  589. s = "%02dZ" % abs(d)
  590. if d < 0:
  591. s = '-' + s
  592. self._cache = s
  593. return self._cache
  594. class yearType(gYearType):
  595. _validURIs = (NS.XSD2, NS.ENC)
  596. class gMonthDayType(anyType):
  597. _validURIs = (NS.XSD3,)
  598. def _checkValueSpace(self, data):
  599. try:
  600. if data == None:
  601. data = time.gmtime(time.time())[1:3]
  602. elif type(data) in (IntType, LongType, FloatType):
  603. data = time.gmtime(data)[1:3]
  604. elif type(data) in (ListType, TupleType):
  605. if len(data) == 9:
  606. data = data[0:2]
  607. elif len(data) > 2:
  608. raise Exception, "too many values"
  609. data = list(data)
  610. if len(data) < 2:
  611. data += [1, 1][len(data):]
  612. data = [0] + data + [0, 0, 0]
  613. cleanDate(data, 1)
  614. data = data[1:3]
  615. else:
  616. raise Exception, "invalid type"
  617. except Exception, e:
  618. raise ValueError, "invalid %s value - %s" % (self._type, e)
  619. return tuple(data)
  620. def _marshalData(self):
  621. if self._cache == None:
  622. self._cache = "--%02d-%02dZ" % self._data
  623. return self._cache
  624. class recurringDateType(gMonthDayType):
  625. _validURIs = (NS.XSD2, NS.ENC)
  626. class gMonthType(anyType):
  627. _validURIs = (NS.XSD3,)
  628. def _checkValueSpace(self, data):
  629. try:
  630. if data == None:
  631. data = time.gmtime(time.time())[1:2]
  632. elif type(data) in (IntType, LongType, FloatType):
  633. data = [data]
  634. if type(data) in (ListType, TupleType):
  635. if len(data) == 9:
  636. data = data[1:2]
  637. elif len(data) < 1:
  638. raise Exception, "too few values"
  639. elif len(data) > 1:
  640. raise Exception, "too many values"
  641. if type(data[0]) == FloatType:
  642. try: s = int(data[0])
  643. except: s = long(data[0])
  644. if s != data[0]:
  645. raise Exception, "not integral"
  646. data = [s]
  647. elif type(data[0]) not in (IntType, LongType):
  648. raise Exception, "bad type"
  649. if data[0] < 1 or data[0] > 12:
  650. raise Exception, "bad value"
  651. else:
  652. raise Exception, "invalid type"
  653. except Exception, e:
  654. raise ValueError, "invalid %s value - %s" % (self._type, e)
  655. return data[0]
  656. def _marshalData(self):
  657. if self._cache == None:
  658. self._cache = "--%02d--Z" % self._data
  659. return self._cache
  660. class monthType(gMonthType):
  661. _validURIs = (NS.XSD2, NS.ENC)
  662. class gDayType(anyType):
  663. _validURIs = (NS.XSD3,)
  664. def _checkValueSpace(self, data):
  665. try:
  666. if data == None:
  667. data = time.gmtime(time.time())[2:3]
  668. elif type(data) in (IntType, LongType, FloatType):
  669. data = [data]
  670. if type(data) in (ListType, TupleType):
  671. if len(data) == 9:
  672. data = data[2:3]
  673. elif len(data) < 1:
  674. raise Exception, "too few values"
  675. elif len(data) > 1:
  676. raise Exception, "too many values"
  677. if type(data[0]) == FloatType:
  678. try: s = int(data[0])
  679. except: s = long(data[0])
  680. if s != data[0]:
  681. raise Exception, "not integral"
  682. data = [s]
  683. elif type(data[0]) not in (IntType, LongType):
  684. raise Exception, "bad type"
  685. if data[0] < 1 or data[0] > 31:
  686. raise Exception, "bad value"
  687. else:
  688. raise Exception, "invalid type"
  689. except Exception, e:
  690. raise ValueError, "invalid %s value - %s" % (self._type, e)
  691. return data[0]
  692. def _marshalData(self):
  693. if self._cache == None:
  694. self._cache = "---%02dZ" % self._data
  695. return self._cache
  696. class recurringDayType(gDayType):
  697. _validURIs = (NS.XSD2, NS.ENC)
  698. class hexBinaryType(anyType):
  699. _validURIs = (NS.XSD3,)
  700. def _checkValueSpace(self, data):
  701. if data == None:
  702. raise ValueError, "must supply initial %s value" % self._type
  703. if type(data) not in (StringType, UnicodeType):
  704. raise AttributeError, "invalid %s type" % self._type
  705. return data
  706. def _marshalData(self):
  707. if self._cache == None:
  708. self._cache = encodeHexString(self._data)
  709. return self._cache
  710. class base64BinaryType(anyType):
  711. _validURIs = (NS.XSD3,)
  712. def _checkValueSpace(self, data):
  713. if data == None:
  714. raise ValueError, "must supply initial %s value" % self._type
  715. if type(data) not in (StringType, UnicodeType):
  716. raise AttributeError, "invalid %s type" % self._type
  717. return data
  718. def _marshalData(self):
  719. if self._cache == None:
  720. self._cache = base64.encodestring(self._data)
  721. return self._cache
  722. class base64Type(base64BinaryType):
  723. _validURIs = (NS.ENC,)
  724. class binaryType(anyType):
  725. _validURIs = (NS.XSD, NS.ENC)
  726. def __init__(self, data, name = None, typed = 1, encoding = 'base64',
  727. attrs = None):
  728. anyType.__init__(self, data, name, typed, attrs)
  729. self._setAttr('encoding', encoding)
  730. def _marshalData(self):
  731. if self._cache == None:
  732. if self._getAttr((None, 'encoding')) == 'base64':
  733. self._cache = base64.encodestring(self._data)
  734. else:
  735. self._cache = encodeHexString(self._data)
  736. return self._cache
  737. def _checkValueSpace(self, data):
  738. if data == None:
  739. raise ValueError, "must supply initial %s value" % self._type
  740. if type(data) not in (StringType, UnicodeType):
  741. raise AttributeError, "invalid %s type" % self._type
  742. return data
  743. def _setAttr(self, attr, value):
  744. attr = self._fixAttr(attr)
  745. if attr[1] == 'encoding':
  746. if attr[0] != None or value not in ('base64', 'hex'):
  747. raise AttributeError, "invalid encoding"
  748. self._cache = None
  749. anyType._setAttr(self, attr, value)
  750. class anyURIType(anyType):
  751. _validURIs = (NS.XSD3,)
  752. def _checkValueSpace(self, data):
  753. if data == None:
  754. raise ValueError, "must supply initial %s value" % self._type
  755. if type(data) not in (StringType, UnicodeType):
  756. raise AttributeError, "invalid %s type" % self._type
  757. return data
  758. def _marshalData(self):
  759. if self._cache == None:
  760. self._cache = urllib.quote(self._data)
  761. return self._cache
  762. class uriType(anyURIType):
  763. _validURIs = (NS.XSD,)
  764. class uriReferenceType(anyURIType):
  765. _validURIs = (NS.XSD2,)
  766. class NOTATIONType(anyType):
  767. def __init__(self, data, name = None, typed = 1, attrs = None):
  768. if self.__class__ == NOTATIONType:
  769. raise Error, "a NOTATION can't be instantiated directly"
  770. anyType.__init__(self, data, name, typed, attrs)
  771. class ENTITIESType(anyType):
  772. def _checkValueSpace(self, data):
  773. if data == None:
  774. raise ValueError, "must supply initial %s value" % self._type
  775. if type(data) in (StringType, UnicodeType):
  776. return (data,)
  777. if type(data) not in (ListType, TupleType) or \
  778. filter (lambda x: type(x) not in (StringType, UnicodeType), data):
  779. raise AttributeError, "invalid %s type" % self._type
  780. return data
  781. def _marshalData(self):
  782. return ' '.join(self._data)
  783. class IDREFSType(ENTITIESType): pass
  784. class NMTOKENSType(ENTITIESType): pass
  785. class integerType(anyType):
  786. def _checkValueSpace(self, data):
  787. if data == None:
  788. raise ValueError, "must supply initial %s value" % self._type
  789. if type(data) not in (IntType, LongType):
  790. raise ValueError, "invalid %s value" % self._type
  791. return data
  792. class nonPositiveIntegerType(anyType):
  793. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  794. def _checkValueSpace(self, data):
  795. if data == None:
  796. raise ValueError, "must supply initial %s value" % self._type
  797. if type(data) not in (IntType, LongType) or data > 0:
  798. raise ValueError, "invalid %s value" % self._type
  799. return data
  800. class non_Positive_IntegerType(nonPositiveIntegerType):
  801. _validURIs = (NS.XSD,)
  802. def _typeName(self):
  803. return 'non-positive-integer'
  804. class negativeIntegerType(anyType):
  805. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  806. def _checkValueSpace(self, data):
  807. if data == None:
  808. raise ValueError, "must supply initial %s value" % self._type
  809. if type(data) not in (IntType, LongType) or data >= 0:
  810. raise ValueError, "invalid %s value" % self._type
  811. return data
  812. class negative_IntegerType(negativeIntegerType):
  813. _validURIs = (NS.XSD,)
  814. def _typeName(self):
  815. return 'negative-integer'
  816. class longType(anyType):
  817. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  818. def _checkValueSpace(self, data):
  819. if data == None:
  820. raise ValueError, "must supply initial %s value" % self._type
  821. if type(data) not in (IntType, LongType) or \
  822. data < -9223372036854775808L or \
  823. data > 9223372036854775807L:
  824. raise ValueError, "invalid %s value" % self._type
  825. return data
  826. class intType(anyType):
  827. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  828. def _checkValueSpace(self, data):
  829. if data == None:
  830. raise ValueError, "must supply initial %s value" % self._type
  831. if type(data) not in (IntType, LongType) or \
  832. data < -2147483648L or \
  833. data > 2147483647:
  834. raise ValueError, "invalid %s value" % self._type
  835. return data
  836. class shortType(anyType):
  837. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  838. def _checkValueSpace(self, data):
  839. if data == None:
  840. raise ValueError, "must supply initial %s value" % self._type
  841. if type(data) not in (IntType, LongType) or \
  842. data < -32768 or \
  843. data > 32767:
  844. raise ValueError, "invalid %s value" % self._type
  845. return data
  846. class byteType(anyType):
  847. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  848. def _checkValueSpace(self, data):
  849. if data == None:
  850. raise ValueError, "must supply initial %s value" % self._type
  851. if type(data) not in (IntType, LongType) or \
  852. data < -128 or \
  853. data > 127:
  854. raise ValueError, "invalid %s value" % self._type
  855. return data
  856. class nonNegativeIntegerType(anyType):
  857. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  858. def _checkValueSpace(self, data):
  859. if data == None:
  860. raise ValueError, "must supply initial %s value" % self._type
  861. if type(data) not in (IntType, LongType) or data < 0:
  862. raise ValueError, "invalid %s value" % self._type
  863. return data
  864. class non_Negative_IntegerType(nonNegativeIntegerType):
  865. _validURIs = (NS.XSD,)
  866. def _typeName(self):
  867. return 'non-negative-integer'
  868. class unsignedLongType(anyType):
  869. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  870. def _checkValueSpace(self, data):
  871. if data == None:
  872. raise ValueError, "must supply initial %s value" % self._type
  873. if type(data) not in (IntType, LongType) or \
  874. data < 0 or \
  875. data > 18446744073709551615L:
  876. raise ValueError, "invalid %s value" % self._type
  877. return data
  878. class unsignedIntType(anyType):
  879. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  880. def _checkValueSpace(self, data):
  881. if data == None:
  882. raise ValueError, "must supply initial %s value" % self._type
  883. if type(data) not in (IntType, LongType) or \
  884. data < 0 or \
  885. data > 4294967295L:
  886. raise ValueError, "invalid %s value" % self._type
  887. return data
  888. class unsignedShortType(anyType):
  889. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  890. def _checkValueSpace(self, data):
  891. if data == None:
  892. raise ValueError, "must supply initial %s value" % self._type
  893. if type(data) not in (IntType, LongType) or \
  894. data < 0 or \
  895. data > 65535:
  896. raise ValueError, "invalid %s value" % self._type
  897. return data
  898. class unsignedByteType(anyType):
  899. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  900. def _checkValueSpace(self, data):
  901. if data == None:
  902. raise ValueError, "must supply initial %s value" % self._type
  903. if type(data) not in (IntType, LongType) or \
  904. data < 0 or \
  905. data > 255:
  906. raise ValueError, "invalid %s value" % self._type
  907. return data
  908. class positiveIntegerType(anyType):
  909. _validURIs = (NS.XSD2, NS.XSD3, NS.ENC)
  910. def _checkValueSpace(self, data):
  911. if data == None:
  912. raise ValueError, "must supply initial %s value" % self._type
  913. if type(data) not in (IntType, LongType) or data <= 0:
  914. raise ValueError, "invalid %s value" % self._type
  915. return data
  916. class positive_IntegerType(positiveIntegerType):
  917. _validURIs = (NS.XSD,)
  918. def _typeName(self):
  919. return 'positive-integer'
  920. # Now compound types
  921. class compoundType(anyType):
  922. def __init__(self, data = None, name = None, typed = 1, attrs = None):
  923. if self.__class__ == compoundType:
  924. raise Error, "a compound can't be instantiated directly"
  925. anyType.__init__(self, data, name, typed, attrs)
  926. self._keyord = []
  927. if type(data) == DictType:
  928. self.__dict__.update(data)
  929. def _aslist(self, item=None):
  930. if item:
  931. return self.__dict__[self._keyord[item]]
  932. else:
  933. return map( lambda x: self.__dict__[x], self._keyord)
  934. def _asdict(self, item=None, encoding=Config.dict_encoding):
  935. if item:
  936. if type(item) in (UnicodeType,StringType):
  937. item = item.encode(encoding)
  938. return self.__dict__[item]
  939. else:
  940. retval = {}
  941. def fun(x): retval[x.encode(encoding)] = self.__dict__[x]
  942. if hasattr(self, '_keyord'):
  943. map( fun, self._keyord)
  944. else:
  945. for name in dir(self):
  946. if isPublic(name):
  947. retval[name] = getattr(self,name)
  948. return retval
  949. def __getitem__(self, item):
  950. if type(item) == IntType:
  951. return self.__dict__[self._keyord[item]]
  952. else:
  953. return getattr(self, item)
  954. def __len__(self):
  955. return len(self._keyord)
  956. def __nonzero__(self):
  957. return 1
  958. def _keys(self):
  959. return filter(lambda x: x[0] != '_', self.__dict__.keys())
  960. def _addItem(self, name, value, attrs = None):
  961. if name in self._keyord:
  962. if type(self.__dict__[name]) != ListType:
  963. self.__dict__[name] = [self.__dict__[name]]
  964. self.__dict__[name].append(value)
  965. else:
  966. self.__dict__[name] = value
  967. self._keyord.append(name)
  968. def _placeItem(self, name, value, pos, subpos = 0, attrs = None):
  969. if subpos == 0 and type(self.__dict__[name]) != ListType:
  970. self.__dict__[name] = value
  971. else:
  972. self.__dict__[name][subpos] = value
  973. self._keyord[pos] = name
  974. def _getItemAsList(self, name, default = []):
  975. try:
  976. d = self.__dict__[name]
  977. except:
  978. return default
  979. if type(d) == ListType:
  980. return d
  981. return [d]
  982. def __str__(self):
  983. return anyType.__str__(self) + ": " + str(self._asdict())
  984. def __repr__(self):
  985. return self.__str__()
  986. class structType(compoundType):
  987. pass
  988. class headerType(structType):
  989. _validURIs = (NS.ENV,)
  990. def __init__(self, data = None, typed = 1, attrs = None):
  991. structType.__init__(self, data, "Header", typed, attrs)
  992. class bodyType(structType):
  993. _validURIs = (NS.ENV,)
  994. def __init__(self, data = None, typed = 1, attrs = None):
  995. structType.__init__(self, data, "Body", typed, attrs)
  996. class arrayType(UserList.UserList, compoundType):
  997. def __init__(self, data = None, name = None, attrs = None,
  998. offset = 0, rank = None, asize = 0, elemsname = None):
  999. if data:
  1000. if type(data) not in (ListType, TupleType):
  1001. raise Error, "Data must be a sequence"
  1002. UserList.UserList.__init__(self, data)
  1003. compoundType.__init__(self, data, name, 0, attrs)
  1004. self._elemsname = elemsname or "item"
  1005. if data == None:
  1006. self._rank = rank
  1007. # According to 5.4.2.2 in the SOAP spec, each element in a
  1008. # sparse array must have a position. _posstate keeps track of
  1009. # whether we've seen a position or not. It's possible values
  1010. # are:
  1011. # -1 No elements have been added, so the state is indeterminate
  1012. # 0 An element without a position has been added, so no
  1013. # elements can have positions
  1014. # 1 An element with a position has been added, so all elements
  1015. # must have positions
  1016. self._posstate = -1
  1017. self._full = 0
  1018. if asize in ('', None):
  1019. asize = '0'
  1020. self._dims = map (lambda x: int(x), str(asize).split(','))
  1021. self._dims.reverse() # It's easier to work with this way
  1022. self._poss = [0] * len(self._dims) # This will end up
  1023. # reversed too
  1024. for i in range(len(self._dims)):
  1025. if self._dims[i] < 0 or \
  1026. self._dims[i] == 0 and len(self._dims) > 1:
  1027. raise TypeError, "invalid Array dimensions"
  1028. if offset > 0:
  1029. self._poss[i] = offset % self._dims[i]
  1030. offset = int(offset / self._dims[i])
  1031. # Don't break out of the loop if offset is 0 so we test all the
  1032. # dimensions for > 0.
  1033. if offset:
  1034. raise AttributeError, "invalid Array offset"
  1035. a = [None] * self._dims[0]
  1036. for i in range(1, len(self._dims)):
  1037. b = []
  1038. for j in range(self._dims[i]):
  1039. b.append(copy.deepcopy(a))
  1040. a = b
  1041. self.data = a
  1042. def _aslist(self, item=None):
  1043. if item:
  1044. return self.data[int(item)]
  1045. else:
  1046. return self.data
  1047. def _asdict(self, item=None, encoding=Config.dict_encoding):
  1048. if item:
  1049. if type(item) in (UnicodeType,StringType):
  1050. item = item.encode(encoding)
  1051. return self.data[int(item)]
  1052. else:
  1053. retval = {}
  1054. def fun(x): retval[str(x).encode(encoding)] = self.data[x]
  1055. map( fun, range(len(self.data)) )
  1056. return retval
  1057. def __getitem__(self, item):
  1058. try:
  1059. return self.data[int(item)]
  1060. except ValueError:
  1061. return getattr(self, item)
  1062. def __len__(self):
  1063. return len(self.data)
  1064. def __nonzero__(self):
  1065. return 1
  1066. def __str__(self):
  1067. return anyType.__str__(self) + ": " + str(self._aslist())
  1068. def _keys(self):
  1069. return filter(lambda x: x[0] != '_', self.__dict__.keys())
  1070. def _addItem(self, name, value, attrs):
  1071. if self._full:
  1072. raise ValueError, "Array is full"
  1073. pos = attrs.get((NS.ENC, 'position'))
  1074. if pos != None:
  1075. if self._posstate == 0:
  1076. raise AttributeError, \
  1077. "all elements in a sparse Array must have a " \
  1078. "position attribute"
  1079. self._posstate = 1
  1080. try:
  1081. if pos[0] == '[' and pos[-1] == ']':
  1082. pos = map (lambda x: int(x), pos[1:-1].split(','))
  1083. pos.reverse()
  1084. if len(pos) == 1:
  1085. pos = pos[0]
  1086. curpos = [0] * len(self._dims)
  1087. for i in range(len(self._dims)):
  1088. curpos[i] = pos % self._dims[i]
  1089. pos = int(pos / self._dims[i])
  1090. if pos == 0:
  1091. break
  1092. if pos:
  1093. raise Exception
  1094. elif len(pos) != len(self._dims):
  1095. raise Exception
  1096. else:
  1097. for i in range(len(self._dims)):
  1098. if pos[i] >= self._dims[i]:
  1099. raise Exception
  1100. curpos = pos
  1101. else:
  1102. raise Exception
  1103. except:
  1104. raise AttributeError, \
  1105. "invalid Array element position %s" % str(pos)
  1106. else:
  1107. if self._posstate == 1:
  1108. raise AttributeError, \
  1109. "only elements in a sparse Array may have a " \
  1110. "position attribute"
  1111. self._posstate = 0
  1112. curpos = self._poss
  1113. a = self.data
  1114. for i in range(len(self._dims) - 1, 0, -1):
  1115. a = a[curpos[i]]
  1116. if curpos[0] >= len(a):
  1117. a += [None] * (len(a) - curpos[0] + 1)
  1118. a[curpos[0]] = value
  1119. if pos == None:
  1120. self._poss[0] += 1
  1121. for i in range(len(self._dims) - 1):
  1122. if self._poss[i] < self._dims[i]:
  1123. break
  1124. self._poss[i] = 0
  1125. self._poss[i + 1] += 1
  1126. if self._dims[-1] and self._poss[-1] >= self._dims[-1]:
  1127. self._full = 1
  1128. def _placeItem(self, name, value, pos, subpos, attrs = None):
  1129. curpos = [0] * len(self._dims)
  1130. for i in range(len(self._dims)):
  1131. if self._dims[i] == 0:
  1132. curpos[0] = pos
  1133. break
  1134. curpos[i] = pos % self._dims[i]
  1135. pos = int(pos / self._dims[i])
  1136. if pos == 0:
  1137. break
  1138. if self._dims[i] != 0 and pos:
  1139. raise Error, "array index out of range"
  1140. a = self.data
  1141. for i in range(len(self._dims) - 1, 0, -1):
  1142. a = a[curpos[i]]
  1143. if curpos[0] >= len(a):
  1144. a += [None] * (len(a) - curpos[0] + 1)
  1145. a[curpos[0]] = value
  1146. class typedArrayType(arrayType):
  1147. def __init__(self, data = None, name = None, typed = None, attrs = None,
  1148. offset = 0, rank = None, asize = 0, elemsname = None, complexType = 0):
  1149. arrayType.__init__(self, data, name, attrs, offset, rank, asize,
  1150. elemsname)
  1151. self._typed = 1
  1152. self._type = typed
  1153. self._complexType = complexType
  1154. class faultType(structType, Error):
  1155. def __init__(self, faultcode = "", faultstring = "", detail = None):
  1156. self.faultcode = faultcode
  1157. self.faultstring = faultstring
  1158. if detail != None:
  1159. self.detail = detail
  1160. structType.__init__(self, None, 0)
  1161. def _setDetail(self, detail = None):
  1162. if detail != None:
  1163. self.detail = detail
  1164. else:
  1165. try: del self.detail
  1166. except AttributeError: pass
  1167. def __repr__(self):
  1168. if getattr(self, 'detail', None) != None:
  1169. return "<Fault %s: %s: %s>" % (self.faultcode,
  1170. self.faultstring,
  1171. self.detail)
  1172. else:
  1173. return "<Fault %s: %s>" % (self.faultcode, self.faultstring)
  1174. __str__ = __repr__
  1175. def __call__(self):
  1176. return (self.faultcode, self.faultstring, self.detail)
  1177. class SOAPException(Exception):
  1178. def __init__(self, code="", string="", detail=None):
  1179. self.value = ("SOAPpy SOAP Exception", code, string, detail)
  1180. self.code = code
  1181. self.string = string
  1182. self.detail = detail
  1183. def __str__(self):
  1184. return repr(self.value)
  1185. class RequiredHeaderMismatch(Exception):
  1186. def __init__(self, value):
  1187. self.value = value
  1188. def __str__(self):
  1189. return repr(self.value)
  1190. class MethodNotFound(Exception):
  1191. def __init__(self, value):
  1192. (val, detail) = value.split(":")
  1193. self.value = val
  1194. self.detail = detail
  1195. def __str__(self):
  1196. return repr(self.value, self.detail)
  1197. class AuthorizationFailed(Exception):
  1198. def __init__(self, value):
  1199. self.value = value
  1200. def __str__(self):
  1201. return repr(self.value)
  1202. class MethodFailed(Exception):
  1203. def __init__(self, value):
  1204. self.value = value
  1205. def __str__(self):
  1206. return repr(self.value)
  1207. #######
  1208. # Convert complex SOAPpy objects to native python equivalents
  1209. #######
  1210. def simplify(object, level=0):
  1211. """
  1212. Convert the SOAPpy objects and thier contents to simple python types.
  1213. This function recursively converts the passed 'container' object,
  1214. and all public subobjects. (Private subobjects have names that
  1215. start with '_'.)
  1216. Conversions:
  1217. - faultType --> raise python exception
  1218. - arrayType --> array
  1219. - compoundType --> dictionary
  1220. """
  1221. if level > 10:
  1222. return object
  1223. if isinstance( object, faultType ):
  1224. if object.faultstring == "Required Header Misunderstood":
  1225. raise RequiredHeaderMismatch(object.detail)
  1226. elif object.faultstring == "Method Not Found":
  1227. raise MethodNotFound(object.detail)
  1228. elif object.faultstring == "Authorization Failed":
  1229. raise AuthorizationFailed(object.detail)
  1230. elif object.faultstring == "Method Failed":
  1231. raise MethodFailed(object.detail)
  1232. else:
  1233. se = SOAPException(object.faultcode, object.faultstring,
  1234. object.detail)
  1235. raise se
  1236. elif isinstance( object, arrayType ):
  1237. data = object._aslist()
  1238. for k in range(len(data)):
  1239. data[k] = simplify(data[k], level=level+1)
  1240. return data
  1241. elif isinstance( object, compoundType ) or isinstance(object, structType):
  1242. data = object._asdict()
  1243. for k in data.keys():
  1244. if isPublic(k):
  1245. data[k] = simplify(data[k], level=level+1)
  1246. return data
  1247. elif type(object)==DictType:
  1248. for k in object.keys():
  1249. if isPublic(k):
  1250. object[k] = simplify(object[k])
  1251. return object
  1252. elif type(object)==list:
  1253. for k in range(len(object)):
  1254. object[k] = simplify(object[k])
  1255. return object
  1256. else:
  1257. return object
  1258. def simplify_contents(object, level=0):
  1259. """
  1260. Convert the contents of SOAPpy objects to simple python types.
  1261. This function recursively converts the sub-objects contained in a
  1262. 'container' object to simple python types.
  1263. Conversions:
  1264. - faultType --> raise python exception
  1265. - arrayType --> array
  1266. - compoundType --> dictionary
  1267. """
  1268. if level>10: return object
  1269. if isinstance( object, faultType ):
  1270. for k in object._keys():
  1271. if isPublic(k):
  1272. setattr(object, k, simplify(object[k], level=level+1))
  1273. raise object
  1274. elif isinstance( object, arrayType ):
  1275. data = object._aslist()
  1276. for k in range(len(data)):
  1277. object[k] = simplify(data[k], level=level+1)
  1278. elif isinstance(object, structType):
  1279. data = object._asdict()
  1280. for k in data.keys():
  1281. if isPublic(k):
  1282. setattr(object, k, simplify(data[k], level=level+1))
  1283. elif isinstance( object, compoundType ) :
  1284. data = object._asdict()
  1285. for k in data.keys():
  1286. if isPublic(k):
  1287. object[k] = simplify(data[k], level=level+1)
  1288. elif type(object)==DictType:
  1289. for k in object.keys():
  1290. if isPublic(k):
  1291. object[k] = simplify(object[k])
  1292. elif type(object)==list:
  1293. for k in range(len(object)):
  1294. object[k] = simplify(object[k])
  1295. return object