def __init__(self, faultxml=[], client=None): DynamicObject.__init__(self) Exception.__init__(self) self.code = None self.message = None self.detail = None for node in faultxml: tag = node.tag.split('}')[-1] if tag == 'faultcode': self.code = ns.split(node.text, nsmap=faultxml.nsmap) elif tag == 'Code': self.code = ns.split(node[0].text, nsmap=faultxml.nsmap) elif tag == 'faultstring': self.message = node.text elif tag == 'Reason': self.message = node[0].text elif tag == 'detail' or tag == 'Detail': faultobj = node[0] type = faultobj.get(ET.QName(ns.XSI, 'type')) if not type: type = faultobj.tag try: faultobj = client.factory(type, faultobj) except: pass self.detail = faultobj
def __fromxml__(self, elem): if self.__validate__: self.__builder__.loader.validate(elem, self.__validate__) lat = len(self.__attrchar__) extra = False # Iterate over the template and construct the object from # the template descriptions for (name, type, default, minmax, flags) in self.__template__: # If this node is an "xs:any" node, note it for later and skip if flags & ANY: extra = True continue # I don't remember why I'm doing this if name in self: continue if (flags & ATTRIBUTE): # If this node is an attribute, get the value from the element attrs value = [ elem.get(self.__nsx__(name[lat:], flags & QUALIFIED), default) ] elif (flags & PROPERTY): # If its a property, get the value from the element text value = [elem.text] else: # Otherwise, find all XML elements with the field name value = elem.findall(self.__nsx__(name)) # If there is no value list, but this is an xs:choice node, skip if len(value) == 0 and (flags & CHOICE): continue if minmax == (0, 1) or minmax == (1, 1): # The field is a single value l = len(value) if l == 0: value = default elif l == 1: value = value[0] else: if self.__relax__: value = value[0] else: raise TypeError('Expecting exactly 0 or 1 items', name) # If the value is present in the XML, or is required # by the template if value is not None or minmax[0] == 1: value = self._make_type(value, type) else: # The field is a list value = [self._make_type(v, type) for v in value] self[name] = value # If there are xs:any items, fall back to the schemaless unmarshaller # in the base class if extra: DynamicObject.__fromxml__(self, elem, ignore=self.__keylist__[:])
def __fromxml__(self, elem): if self.__validate__: self.__builder__.loader.validate(elem, self.__validate__) lat = len(self.__attrchar__) extra = False # Iterate over the template and construct the object from # the template descriptions for (name, type, default, minmax, flags) in self.__template__: # If this node is an "xs:any" node, note it for later and skip if flags & ANY: extra = True continue # I don't remember why I'm doing this if name in self: continue if (flags & ATTRIBUTE): # If this node is an attribute, get the value from the element attrs value = [elem.get(self.__nsx__(name[lat:], flags & QUALIFIED), default)] elif (flags & PROPERTY): # If its a property, get the value from the element text value = [elem.text] else: # Otherwise, find all XML elements with the field name value = elem.findall(self.__nsx__(name)) # If there is no value list, but this is an xs:choice node, skip if len(value) == 0 and (flags & CHOICE): continue if minmax == (0,1) or minmax == (1,1): # The field is a single value l = len(value) if l == 0: value = default elif l == 1: value = value[0] else: if self.__relax__: value = value[0] else: raise TypeError('Expecting exactly 0 or 1 items', name) # If the value is present in the XML, or is required # by the template if value is not None or minmax[0] == 1: value = self._make_type(value, type) else: # The field is a list value = [self._make_type(v, type) for v in value] self[name] = value # If there are xs:any items, fall back to the schemaless unmarshaller # in the base class if extra: DynamicObject.__fromxml__(self, elem, ignore=self.__keylist__[:])
def __fromiter__(self, items): extra = False if not isinstance(items, dict): items = OrderedDict(items) # Iterate over the template and construct the object from # the template description for (name, type, default, minmax, flags) in self.__template__: # If this node is an "xs:any" node, note it for later and skip if flags & ANY: extra = True continue # I don't remember why I'm doing this if name in self: continue # Get the value out of the items dictionary, or use the # default if it doesn't exist value = items.pop(name, default) # If there is not value, but this is a choice element, skip if value is None and (flags & CHOICE): continue if minmax == (0, 1): # Optional element # If we have a value, create the type if value is not None: value = self._make_type(value, type) elif minmax == (1, 1): # Manditory element value = self._make_type(value, type) else: # List of elements if value is None: value = [] elif isinstance(value, (list, tuple)): # A real list value = [self._make_type(v, type) for v in value] elif isinstance(value, dict) and getattr( value, 'listlike', False): # A dict with integer keys (we hope) value = [self._make_type(v, type) for v in value] else: if self.__relax__: value = [] else: raise TypeError('Field must be a list', name) self[name] = value # If this type has an xs:any node, set all the remaining items # using the base class. if extra: DynamicObject.__fromiter__(self, items)
def __fromiter__(self, items): extra = False if not isinstance(items, dict): items = OrderedDict(items) # Iterate over the template and construct the object from # the template description for (name, type, default, minmax, flags) in self.__template__: # If this node is an "xs:any" node, note it for later and skip if flags & ANY: extra = True continue # I don't remember why I'm doing this if name in self: continue # Get the value out of the items dictionary, or use the # default if it doesn't exist value = items.pop(name, default) # If there is not value, but this is a choice element, skip if value is None and (flags & CHOICE): continue if minmax == (0,1): # Optional element # If we have a value, create the type if value is not None: value = self._make_type(value, type) elif minmax == (1,1): # Manditory element value = self._make_type(value, type) else: # List of elements if value is None: value = [] elif isinstance(value, (list, tuple)): # A real list value = [self._make_type(v, type) for v in value] elif isinstance(value, dict) and getattr(value, 'listlike', False): # A dict with integer keys (we hope) value = [self._make_type(v, type) for v in value] else: if self.__relax__: value = [] else: raise TypeError('Field must be a list', name) self[name] = value # If this type has an xs:any node, set all the remaining items # using the base class. if extra: DynamicObject.__fromiter__(self, items)
def guess(self, filename): text = file(filename).read() text = re.sub(r'xmlns="[^"]*"', '', text) xml = ET.fromstring(text) obj = DynamicObject(xml) tns, tag = ns.split(xml.tag) root = self.complexType(tag, obj) el = Element(name=tag, type=root.name) self._addElement(self.schema, el)
def __xml__(self, tag=None, node=None, nsmap=None): lat = len(self.__attrchar__) done = [] extra = False if tag is None: tag = self.__class__.__name__ tag = self.__nsx__(tag) if node is None: node = ET.Element(tag, nsmap=nsmap) # Construct reverse namespace map for doing xsi:type rmap = dict((v,k) for k, v in node.nsmap.items() if k is not None) # Iterate over the template to construct the XML representation. for (name, type, default, minmax, flags) in self.__template__: # If this field is an "xs:any" node, note it for later and skip if (flags & ANY): extra = True continue # If the field is choice/optional and doesn't exist, skip it if ((flags & CHOICE) or minmax[0] == 0) and name not in self: continue # Get the value value = self[name] done.append(name) if value is None and minmax[0] == 0 and not (flags & XSINIL): # Skip fields that are none and don't have to exist, as long # as they aren't nillable continue elif (flags & ATTRIBUTE): # Handle attributes. Skip attributes that are optional value = converter(type).tostr(value) if value is None: value = '' if value is not None or minmax[0]: node.set(self.__nsx__(name[lat:], flags & QUALIFIED), value) continue elif (flags & PROPERTY): # Property node.text = converter(type).tostr(value) continue qname = self.__nsx__(name) if not isinstance(value, (list, tuple)): value = [value] for v in value: if v is None and (flags & XSINIL): # Nil node n = ET.Element(qname, xsi_nil_true) node.append(n) elif ET.iselement(v): # User supplied XML Elements, so just add them node.append(v) elif type.startswith('xs:'): # Primitive type n = ET.Element(qname) n.text = converter(type).tostr(v) node.append(n) elif flags & SIMPLE: # Primitive type type = self.__builder__.factory(type).__simple__ n = ET.Element(qname) n.text = converter(type).tostr(v) node.append(n) elif isinstance(v, DynamicObject): # Dynamic object or subclass, so marshall and append n = v.__xml__(name) if type != v.__class__.__name__: (namespace, datatype) = ns.split(v.__class__.__name__) n.set(xsi_type, '%s:%s' % (rmap[namespace], datatype)) node.append(n) elif v == '': # Carry-over for dealing with SUDS bug pass else: if not self.__relax__: raise TypeError('Unknown type', name, type) # If there was an xs:any node, fall back to the schemaless marshaller # in the base class if extra: DynamicObject.__xml__(self, tag, node, ignore=done) return node
def __xml__(self, tag=None, node=None, nsmap=None): lat = len(self.__attrchar__) done = [] extra = False if tag is None: tag = self.__class__.__name__ tag = self.__nsx__(tag) if node is None: node = ET.Element(tag, nsmap=nsmap) # Construct reverse namespace map for doing xsi:type rmap = dict((v, k) for k, v in node.nsmap.items() if k is not None) # Iterate over the template to construct the XML representation. for (name, type, default, minmax, flags) in self.__template__: # If this field is an "xs:any" node, note it for later and skip if (flags & ANY): extra = True continue # If the field is choice/optional and doesn't exist, skip it if ((flags & CHOICE) or minmax[0] == 0) and name not in self: continue # Get the value value = self[name] done.append(name) if value is None and minmax[0] == 0 and not (flags & XSINIL): # Skip fields that are none and don't have to exist, as long # as they aren't nillable continue elif (flags & ATTRIBUTE): # Handle attributes. Skip attributes that are optional value = converter(type).tostr(value) if value is None: value = '' if value is not None or minmax[0]: node.set(self.__nsx__(name[lat:], flags & QUALIFIED), value) continue elif (flags & PROPERTY): # Property node.text = converter(type).tostr(value) continue qname = self.__nsx__(name) if not isinstance(value, (list, tuple)): value = [value] for v in value: if v is None and (flags & XSINIL): # Nil node n = ET.Element(qname, xsi_nil_true) node.append(n) elif ET.iselement(v): # User supplied XML Elements, so just add them node.append(v) elif type.startswith('xs:'): # Primitive type n = ET.Element(qname) n.text = converter(type).tostr(v) node.append(n) elif flags & SIMPLE: # Primitive type type = self.__builder__.factory(type).__simple__ n = ET.Element(qname) n.text = converter(type).tostr(v) node.append(n) elif isinstance(v, DynamicObject): # Dynamic object or subclass, so marshall and append n = v.__xml__(name) if type != v.__class__.__name__: (namespace, datatype) = ns.split(v.__class__.__name__) n.set(xsi_type, '%s:%s' % (rmap[namespace], datatype)) node.append(n) elif v == '': # Carry-over for dealing with SUDS bug pass else: if not self.__relax__: raise TypeError('Unknown type', name, type) # If there was an xs:any node, fall back to the schemaless marshaller # in the base class if extra: DynamicObject.__xml__(self, tag, node, ignore=done) return node