Ejemplo n.º 1
0
    def _load(self, url):
        doc = ET.parse(urllib2.urlopen(url))
        extrans = doc.getroot().nsmap
        targetns = doc.getroot().get('targetNamespace')
        schemas = doc.findall(ns.expand('*/xs:schema'))
        for s in schemas:
            for k,v in extrans.items():
                if k not in s.nsmap:
                    s.nsmap[k] = v
            self.schemaloader.load(s, pathinfo=self.url)
        self.documents.append(doc)

        wsdls = doc.findall(ns.expand('/wsdl:import'))
        for w in wsdls:
            location = w.get('location')
            location = urljoin(url, location)
            tns = self._load(location)
            if tns:
                targetns = tns

        return targetns
Ejemplo n.º 2
0
    def _load(self, url):
        doc = ET.parse(urllib2.urlopen(url))
        extrans = doc.getroot().nsmap
        targetns = doc.getroot().get('targetNamespace')
        schemas = doc.findall(ns.expand('*/xs:schema'))
        for s in schemas:
            for k,v in extrans.items():
                if k not in s.nsmap:
                    s.nsmap[k] = v
            self.schemaloader.load(s, pathinfo=self.url)
        self.documents.append(doc)

        wsdls = doc.findall(ns.expand('/wsdl:import'))
        for w in wsdls:
            location = w.get('location')
            location = urljoin(url, location)
            tns = self._load(location)
            if tns:
                targetns = tns

        return targetns
Ejemplo n.º 3
0
    def load(self, schema, force=False, fragment=False, pathinfo='', basecls=None):
        '''
        Load and pre-process an XML schema.

        @type schema: L{ElementTree.Element} or URL
        @param schema: A schema to load.
        @type force: bool
        @param force: Optional.  Reload an already loaded schema.
        @type fragment: bool
        @param fragment: Optional.  The schema is actually a fragment of a
            an already-loaded schema and should be integrated with it.
        @type pathinfo: str
        @param pathinfo: Optional.  A URL to help with loading the schema.
            Usually used by SchemaLoader to process xs:import directives.
        @rtype: str
        @return: The targetNamespace of the loaded schema
        '''
        # Is schema already parsed 
        if ET.iselement(schema):
            root = schema
        else:
            schema = urljoin(pathinfo, schema)
            root = ET.parse(u2.urlopen(schema)).getroot()

        # Get the target namespace.  Exit early if we already know this schema.
        targetNamespace = root.get('targetNamespace')
        if targetNamespace in self.schemas and not (force or fragment):
            return targetNamespace

        # Add a new entry to our dictionary
        if not fragment:
            self.schemas[targetNamespace] = { 'root': root, 'types': {}, 'elements': {}, 'groups': {}, 'validator': None, 'basecls': basecls }

        # Update our "all namespaces" dictionary and get references to the
        # various subdictionaries we'll need
        self.allns.update(root.nsmap)
        self.revns.update((v,k) for k,v in root.nsmap.items() if k not in (None, 'tns'))
        types = self.schemas[targetNamespace]['types']
        elements = self.schemas[targetNamespace]['elements']
        groups = self.schemas[targetNamespace]['groups']

        # Process includes
        includes = []
        while True:
            # Get the list of includes
            inclist = root.findall(ns.expand('xs:include'))
            if not inclist:
                break

            for el in inclist:
                # remove it from the document
                root.remove(el)
                
                # Get the schemaLocation and compute the URL
                location = el.get('schemaLocation')
                if location in includes:
                    # skip if we've processed this schema
                    continue
                includes.append(location)
                url = urljoin(pathinfo, location)

                # Parse the XML and append it to the root document
                # We probably *should* include it into the place where the
                # xs:include node was, but for now, punt and append it
                # to the end of the document
                inc = ET.parse(u2.urlopen(url)).getroot()
                root.extend(inc)

        # Process imports
        for el in root.findall(ns.expand('xs:import')):
            location = el.get('schemaLocation')
            if location:
                self.load(location, pathinfo=pathinfo)
        # Find all first-level tags we care about and reference them
        # in the types/elements/groups dictionaries
        for el in root.findall(ns.expand('xs:complexType')):
            types[el.get('name')] = el
        for el in root.findall(ns.expand('xs:simpleType')):
            types[el.get('name')] = el
        for el in root.findall(ns.expand('xs:element')):
            elements[el.get('name')] = el
        for el in root.findall(ns.expand('xs:group')):
            groups[el.get('name')] = el

        # If this is a schema fragment, integrate it into the
        # original schema element tree in memory
        if fragment:
            realroot = self.schemas[targetNamespace]['root']
            nsmap = dict(realroot.nsmap)
            nsmap.update(root.nsmap)
            attrib = dict(realroot.attrib)
            attrib.update(root.attrib)
            newroot = ET.Element(realroot.tag, attrib=attrib, nsmap=nsmap)
            newroot.text = realroot.text

            newroot.extend(realroot.getchildren())
            newroot.extend(root.getchildren())
            self.schemas[targetNamespace]['root'] = newroot

        return targetNamespace
Ejemplo n.º 4
0
    def invoke(self, operation, *args, **kwargs):
        '''
        Invoke a SOAP operation.
        '''
        self._reqno += 1
        retxml = kwargs.pop('__retxml__', self.retxml)
        timeout = kwargs.pop('__timeout__', self.timeout)
        transport_options = kwargs.pop('__transport__', {})
        # Create an instance of the request message and initialize
        # the object from the arguments
        param = self.factory(operation.imsg)
        tmpl = param.__template__
        for k,v in zip((t[0] for t in tmpl), args):
            param[k] = v
        for k,v in kwargs.items():
            param[k] = v

        # Build the soap envelope and set the http headers
        payload = self.envelope(self.headers, param, operation.imsg)
        httphdr = { 'Content-Type': 'text/xml', 'SOAPAction': operation.action }
        httphdr.update(self.httphdr)

        # Construct and issue the request, read the response
        payload = ET.tostring(payload, pretty_print=True)
        log.debug('=== SOAP REQUEST ===\n%s', re.sub(r'password>.*?<', r'password>*****<', payload ))
        req = urllib2.Request(self.url, payload, httphdr)
        try:
            if self._inject:
                xml = ET.fromstring(self._inject.next())
            else:
                if hasattr(self.transport, 'open'):
                    rsp = self.transport.open(req, timeout=timeout, **transport_options)
                else:
                    rsp = self.transport.urlopen(req, timeout=timeout, **transport_options)
                xml = ET.parse(rsp)
        except urllib2.HTTPError as ex:
            xml = ET.parse(ex)

        log.debug('=== SOAP RESPONSE ===\n%s', xmlstr(xml))
        # Get the soap body
        retval = xml.find(ns.expand('soapenv:Body', self.nsmap))
        if not retxml:
            # Does the body contain any nodes?
            if len(retval):
                # Get the first child and examine it
                retval = retval[0]
                namespace, tag = ns.split(retval.tag)
                # If it's a fault, convert it to an exception
                if tag == 'Fault':
                    raise SoapFault(retval, self)
                # Otherwise, deserialize
                obj = self.factory(operation.omsg, retval)
                # If the deserialized
                # object has only one item, return that item, otherwise the
                # whole object
                #
                # This is so if the return value is a single primitive type
                # (like a string), you don't have to dig into an object just
                # to get at the single primitive return value
                if len(obj) == 1:
                    obj = obj[0]
                retval = obj
            else:
                retval = None

        return retval
Ejemplo n.º 5
0
    def load(self,
             schema,
             force=False,
             fragment=False,
             pathinfo='',
             basecls=None):
        '''
        Load and pre-process an XML schema.

        @type schema: L{ElementTree.Element} or URL
        @param schema: A schema to load.
        @type force: bool
        @param force: Optional.  Reload an already loaded schema.
        @type fragment: bool
        @param fragment: Optional.  The schema is actually a fragment of a
            an already-loaded schema and should be integrated with it.
        @type pathinfo: str
        @param pathinfo: Optional.  A URL to help with loading the schema.
            Usually used by SchemaLoader to process xs:import directives.
        @rtype: str
        @return: The targetNamespace of the loaded schema
        '''
        # Is schema already parsed
        if ET.iselement(schema):
            root = schema
        else:
            schema = urljoin(pathinfo, schema)
            root = ET.parse(u2.urlopen(schema)).getroot()

        # Get the target namespace.  Exit early if we already know this schema.
        targetNamespace = root.get('targetNamespace')
        if targetNamespace in self.schemas and not (force or fragment):
            return targetNamespace

        # Add a new entry to our dictionary
        if not fragment:
            self.schemas[targetNamespace] = {
                'root': root,
                'types': {},
                'elements': {},
                'groups': {},
                'validator': None,
                'basecls': basecls
            }

        # Update our "all namespaces" dictionary and get references to the
        # various subdictionaries we'll need
        self.allns.update(root.nsmap)
        self.revns.update(
            (v, k) for k, v in root.nsmap.items() if k not in (None, 'tns'))
        types = self.schemas[targetNamespace]['types']
        elements = self.schemas[targetNamespace]['elements']
        groups = self.schemas[targetNamespace]['groups']

        # Process includes
        includes = []
        while True:
            # Get the list of includes
            inclist = root.findall(ns.expand('xs:include'))
            if not inclist:
                break

            for el in inclist:
                # remove it from the document
                root.remove(el)

                # Get the schemaLocation and compute the URL
                location = el.get('schemaLocation')
                if location in includes:
                    # skip if we've processed this schema
                    continue
                includes.append(location)
                url = urljoin(pathinfo, location)

                # Parse the XML and append it to the root document
                # We probably *should* include it into the place where the
                # xs:include node was, but for now, punt and append it
                # to the end of the document
                inc = ET.parse(u2.urlopen(url)).getroot()
                root.extend(inc)

        # Process imports
        for el in root.findall(ns.expand('xs:import')):
            location = el.get('schemaLocation')
            if location:
                self.load(location, pathinfo=pathinfo)
        # Find all first-level tags we care about and reference them
        # in the types/elements/groups dictionaries
        for el in root.findall(ns.expand('xs:complexType')):
            types[el.get('name')] = el
        for el in root.findall(ns.expand('xs:simpleType')):
            types[el.get('name')] = el
        for el in root.findall(ns.expand('xs:element')):
            elements[el.get('name')] = el
        for el in root.findall(ns.expand('xs:group')):
            groups[el.get('name')] = el

        # If this is a schema fragment, integrate it into the
        # original schema element tree in memory
        if fragment:
            realroot = self.schemas[targetNamespace]['root']
            nsmap = dict(realroot.nsmap)
            nsmap.update(root.nsmap)
            attrib = dict(realroot.attrib)
            attrib.update(root.attrib)
            newroot = ET.Element(realroot.tag, attrib=attrib, nsmap=nsmap)
            newroot.text = realroot.text

            newroot.extend(realroot.getchildren())
            newroot.extend(root.getchildren())
            self.schemas[targetNamespace]['root'] = newroot

        return targetNamespace
Ejemplo n.º 6
0
    def invoke(self, operation, *args, **kwargs):
        '''
        Invoke a SOAP operation.
        '''
        self._reqno += 1
        retxml = kwargs.pop('__retxml__', self.retxml)
        timeout = kwargs.pop('__timeout__', self.timeout)
        transport_options = kwargs.pop('__transport__', {})
        # Create an instance of the request message and initialize
        # the object from the arguments
        param = self.factory(operation.imsg)
        tmpl = param.__template__
        for k,v in zip((t[0] for t in tmpl), args):
            param[k] = v
        for k,v in kwargs.items():
            param[k] = v

        # Build the soap envelope and set the http headers
        payload = self.envelope(self.headers, param, operation.imsg)
        httphdr = { 'Content-Type': 'text/xml', 'SOAPAction': operation.action }
        httphdr.update(self.httphdr)

        # Construct and issue the request, read the response
        payload = ET.tostring(payload, pretty_print=True)
        log.debug('=== SOAP REQUEST ===\n%s', payload)
        req = urllib2.Request(self.url, payload, httphdr)
        try:
            if self._inject:
                xml = ET.fromstring(self._inject.next())
            else:
                if hasattr(self.transport, 'open'):
                    rsp = self.transport.open(req, timeout=timeout, **transport_options)
                else:
                    rsp = self.transport.urlopen(req, timeout=timeout, **transport_options)
                xml = ET.parse(rsp)
        except urllib2.HTTPError as ex:
            xml = ET.parse(ex)

        log.debug('=== SOAP RESPONSE ===\n%s', xmlstr(xml))
        # Get the soap body
        retval = xml.find(ns.expand('soapenv:Body', self.nsmap))
        if not retxml:
            # Does the body contain any nodes?
            if len(retval):
                # Get the first child and examine it
                retval = retval[0]
                namespace, tag = ns.split(retval.tag)
                # If it's a fault, convert it to an exception
                if tag == 'Fault':
                    raise SoapFault(retval, self)
                # Otherwise, deserialize
                obj = self.factory(operation.omsg, retval)
                # If the deserialized
                # object has only one item, return that item, otherwise the
                # whole object
                #
                # This is so if the return value is a single primitive type
                # (like a string), you don't have to dig into an object just
                # to get at the single primitive return value
                if len(obj) == 1:
                    obj = obj[0]
                retval = obj
            else:
                retval = None

        return retval