Exemplo n.º 1
0
    def analyze_reply_code(self, xml_response_dict):
        """
        Checks the RETS Response Code and handles non-zero answers.
        :param xml_response_dict:
        :return: None
        """
        if 'RETS' not in xml_response_dict:  # pragma: no cover
            raise RETSException(
                "The <RETS> tag was expected in the response XML but it was not found."
            )

        attributes = self.get_attributes(input_dict=xml_response_dict['RETS'])
        if 'ReplyCode' not in attributes:  # pragma: no cover
            # The RETS server did not return a response code.
            return True

        reply_code = attributes['ReplyCode']
        reply_text = attributes.get('ReplyText',
                                    'RETS did not supply a Reply Text.')

        logger.debug(
            "Received ReplyCode of {0!s} from the RETS Server: {0!s}".format(
                reply_code, reply_text))
        if reply_code != '0':
            raise RETSException(reply_text, reply_code)
Exemplo n.º 2
0
    def generator(self, response):
        """
        Takes a response socket connection and iteratively parses and yields the results as python dictionaries.
        :param response: a Requests response object with stream=True
        :return:
        """

        delim = "\t"  # Default to tab delimited
        columns = []
        response.raw.decode_content = True
        events = ET.iterparse(BytesIO(response.content))

        for event, elem in events:
            # Analyze search record data
            if "DATA" == elem.tag:
                data_dict = {
                    column: data
                    for column, data in zip(columns, elem.text.split(delim))
                    if column != ""
                }
                self.parsed_rows += 1  # Rows parsed with all requests
                yield data_dict

            # Handle reply code
            elif "RETS" == elem.tag:
                reply_code = elem.get("ReplyCode")
                reply_text = elem.get("ReplyText")

                if reply_code == "20201":
                    # RETS Response 20201 - No Records Found
                    # Generator should continue and return nothing
                    continue
                elif reply_code != "0":
                    msg = "RETS Error {0!s}: {1!s}".format(
                        reply_code, reply_text)
                    raise RETSException(msg)

            # Analyze delimiter
            elif "DELIMITER" == elem.tag:
                val = elem.get("value")
                delim = chr(int(val))

            # Analyze columns
            elif "COLUMNS" == elem.tag:
                columns = elem.text.split(delim)

            # handle max rows
            elif "MAXROWS" == elem.tag:
                logger.debug("MAXROWS Tag reached in XML")
                logger.debug("Received {0!s} results from this search".format(
                    self.parsed_rows))
                raise MaxrowException(self.parsed_rows)

            else:
                # This is a tag we don't process (like COUNT)
                continue

            elem.clear()
Exemplo n.º 3
0
 def generator(self, response):
     results = []
     rets = xmltodict.parse(response.content)["RETS"]
     reply_code = rets["@ReplyCode"]
     reply_text = rets["@ReplyText"]
     if reply_code != "0":
         raise RETSException(reply_text, reply_code)
     results = rets["RETS-RESPONSE"]["PropertyDetails"]
     if isinstance(results, dict):
         results = [results]
     return results
Exemplo n.º 4
0
 def generator(self, response):
     results = []
     rets = xmltodict.parse(response.content)['RETS']
     reply_code = rets['@ReplyCode']
     reply_text = rets['@ReplyText']
     if reply_code != '0':
         raise RETSException(reply_text, reply_code)
     results = rets['RETS-RESPONSE']['PropertyDetails']
     if isinstance(results, dict):
         results = [results]
     return results
Exemplo n.º 5
0
    def _make_metadata_request(self, meta_id, metadata_type=None):
        """
        Get the Metadata. The Session initializes with 'COMPACT-DECODED' as the format type. If that returns a DTD error
        then we change to the 'STANDARD-XML' format and try again.
        :param meta_id: The name of the resource, class, or lookup to get metadata for
        :param metadata_type: The RETS metadata type
        :return: list
        """
        # If this metadata _request has already happened, returned the saved result.
        key = "{0!s}:{1!s}".format(metadata_type, meta_id)
        if key in self.metadata_responses and self.cache_metadata:
            response = self.metadata_responses[key]
        else:
            response = self._request(
                capability="GetMetadata",
                options={
                    "query": {
                        "Type": metadata_type,
                        "ID": meta_id,
                        "Format": self.metadata_format,
                    }
                },
            )
            self.metadata_responses[key] = response

        if self.metadata_format == "COMPACT-DECODED":
            parser = CompactMetadata()
        else:
            parser = StandardXMLMetadata()

        try:
            # Process generator here to raise RETSException if it happens
            return list(parser.parse(response=response, metadata_type=metadata_type))
        except RETSException as rets_er:
            # Remove response from cache
            self.metadata_responses.pop(key, None)

            # If the server responds with an invalid parameter for COMPACT-DECODED, try STANDARD-XML
            if self.metadata_format != "STANDARD-XML" and rets_er.reply_code in [
                "20513",
                "20514",
            ]:
                self.metadata_responses.pop(key, None)
                self.metadata_format = "STANDARD-XML"
                return self._make_metadata_request(
                    meta_id=meta_id, metadata_type=metadata_type
                )
            raise RETSException(rets_er.reply_text, rets_er.reply_code)
Exemplo n.º 6
0
    def _make_metadata_request(self, meta_id, metadata_type=None):
        """
        Get the Metadata. The Session initializes with 'COMPACT-DECODED' as the format type. If that returns a DTD error
        then we change to the 'STANDARD-XML' format and try again.
        :param meta_id: The name of the resource, class, or lookup to get metadata for
        :param metadata_type: The RETS metadata type
        :return: list
        """
        # If this metadata _request has already happened, returned the saved result.
        key = '{0!s}:{1!s}'.format(metadata_type, meta_id)
        if key in self.metadata_responses and self.cache_metadata:
            response = self.metadata_responses[key]
        else:
            response = self._request(capability='GetMetadata',
                                     options={
                                         'query': {
                                             'Type': metadata_type,
                                             'ID': meta_id,
                                             'Format': self.metadata_format
                                         }
                                     })
            self.metadata_responses[key] = response

        if self.metadata_format == 'COMPACT-DECODED':
            parser = CompactMetadata()
        else:
            parser = StandardXMLetadata()

        try:
            return parser.parse(response=response, metadata_type=metadata_type)
        except RETSException as e:
            # Remove response from cache
            self.metadata_responses.pop(key, None)

            # If the server responds with an invalid parameter for COMPACT-DECODED, try STANDARD-XML
            if self.metadata_format != 'STANDARD-XML' and e.reply_code in [
                    '20513', '20514'
            ]:
                self.metadata_responses.pop(key, None)
                self.metadata_format = 'STANDARD-XML'
                return self._make_metadata_request(meta_id=meta_id,
                                                   metadata_type=metadata_type)
            raise RETSException(e.reply_text, e.reply_code)
Exemplo n.º 7
0
    def parse(self, response):

        if response.status_code != 200:
            raise RETSException("")

        headers = response.headers

        obj = Object()
        obj.content = response.text
        obj.content_description = headers.get('Content-Description')
        obj.content_sub_description = headers.get('Content-Sub-Description')
        obj.content_id = headers.get('Content-ID')
        obj.object_id = headers.get('Object-ID')
        obj.content_type = headers.get('Content-Type')
        obj.location = headers.get('Location')
        obj.mime_version = headers.get('MIME-Version')
        obj.preferred = headers.get('Preferred')

        return obj