def test_from_response(self):
     response = mock.NonCallableMagicMock(spec=requests.Response)
     response.headers = {
         'content-type': 'multipart/related; boundary="samp1"'
     }
     cnt = io.BytesIO()
     cnt.write(b'\r\n--samp1\r\n')
     cnt.write(b'Header-1: Header-Value-1\r\n')
     cnt.write(b'Header-2: Header-Value-2\r\n')
     cnt.write(b'\r\n')
     cnt.write(b'Body 1, Line 1\r\n')
     cnt.write(b'Body 1, Line 2\r\n')
     cnt.write(b'--samp1\r\n')
     cnt.write(b'\r\n')
     cnt.write(b'Body 2, Line 1\r\n')
     cnt.write(b'--samp1--\r\n')
     response.content = cnt.getvalue()
     decoder_2 = MultipartDecoder.from_response(response)
     assert decoder_2.content_type == response.headers['content-type']
     assert (
         decoder_2.parts[0].content == b'Body 1, Line 1\r\nBody 1, Line 2'
     )
     assert decoder_2.parts[0].headers[b'Header-1'] == b'Header-Value-1'
     assert len(decoder_2.parts[1].headers) == 0
     assert decoder_2.parts[1].content == b'Body 2, Line 1'
Esempio n. 2
0
 def test_from_responsecaplarge(self):
     response = mock.NonCallableMagicMock(spec=requests.Response)
     response.headers = {
         'content-type': 'Multipart/Related; boundary="samp1"'
     }
     cnt = io.BytesIO()
     cnt.write(b'\r\n--samp1\r\n')
     cnt.write(b'Header-1: Header-Value-1\r\n')
     cnt.write(b'Header-2: Header-Value-2\r\n')
     cnt.write(b'\r\n')
     cnt.write(b'Body 1, Line 1\r\n')
     cnt.write(b'Body 1, Line 2\r\n')
     cnt.write(b'--samp1\r\n')
     cnt.write(b'\r\n')
     cnt.write(b'Body 2, Line 1\r\n')
     cnt.write(b'--samp1--\r\n')
     response.content = cnt.getvalue()
     decoder_2 = MultipartDecoder.from_response(response)
     assert decoder_2.content_type == response.headers['content-type']
     assert (
         decoder_2.parts[0].content == b'Body 1, Line 1\r\nBody 1, Line 2'
     )
     assert decoder_2.parts[0].headers[b'Header-1'] == b'Header-Value-1'
     assert len(decoder_2.parts[1].headers) == 0
     assert decoder_2.parts[1].content == b'Body 2, Line 1'
    def _eval_adhoc(self, lang, line, cell):
        self._check_for_session()

        valid_lang = ("xquery", "javascript")
        if lang not in valid_lang:
            raise TypeError("lang can only be " + ", ".join(valid_lang))
        
        args = shlex.split(line, comments = True)
        self._check_invalid_args(args, ("-raw", "-dataframe"))
        output_opt = "default"
        if "-raw" in args:
            output_opt = "raw"
        if "-dataframe" in args:
            output_opt = "dataframe"
        
        # execute code on MarkLogic
        url = self.session_baseurl + "/v1/eval"
        body = {
            lang: cell
        }
        output = []
        response = self.session.post(url, data = body)
        if response.status_code == 200:
            headers = { header.lower(): value for (header, value) in response.headers.items() } 
            # as per docs, /v1/eval should always return multipart/mixed
            if "content-type" in headers and headers["content-type"].startswith("multipart/mixed"):
                mp_data = MultipartDecoder.from_response(response)
                for part in mp_data.parts:
                    part_headers = { header.decode("utf-8").lower(): value.decode("utf-8") for (header, value) in part.headers.items() } 
                    part_content_type = part_headers["content-type"]
                    part_x_primitive = part_headers["x-primitive"]
                    part_content = part.content.decode("utf-8")
                    data = part_content if output_opt == "raw" else self._parse_content(part_content, part_content_type, part_x_primitive)
                    output.append(data)
        else:
            raise EvalError("Request to %s returned %s %s: %s" % (url, response.status_code, response.reason, response.text))

        output = output[0] if len(output) == 1 else output
        if output_opt == "dataframe":
            try:
                output = pandas.DataFrame(output) # try to fit into a dataframe, may raise an exception depending on result's shape
            except:
                raise CoercionError("Unable to fit response into a DataFrame")
        return {
            "status_code": response.status_code,
            "output": output,
            "output_opt": output_opt,
            "args": args
        }
Esempio n. 4
0
def parse_multipart(response: Response_) -> Sequence[Any]:
    """
    RFC 2045 describes the format of an Internet message body containing a MIME message. The
    body contains one or more body parts, each preceded by a boundary delimiter line, and the
    last one followed by a closing boundary delimiter line. After its boundary delimiter line,
    each body part then consists of a header area, a blank line, and a body area.

    HTTP/1.1 200 OK
    Server: Apache/2.0.13
    Date: Fri, 22 OCT 2004 12:03:38 GMT
    Cache-Control: private
    RETS-Version: RETS/1.7.2
    MIME-Version: 1.0
    Content-Type: multipart/parallel; boundary="simple boundary"

    --simple boundary
    Content-Type: image/jpeg
    Content-ID: 123456
    Object-ID: 1

    <binary data>

    --simple boundary
    Content-Type: text/xml
    Content-ID: 123457
    Object-ID: 1

    <RETS ReplyCode="20403" ReplyText="There is no listing with that ListingID"/>

    --simple boundary--
    """
    multipart = MultipartDecoder.from_response(response, response.encoding)
    # We need to decode the headers because MultipartDecoder returns bytes keys and values,
    # while requests.Response.headers uses str keys and values.
    for part in multipart.parts:
        part.headers = _decode_headers(part.headers, response.encoding)

    def parse_multipart(parts):
        for part in parts:
            try:
                yield parse_response(part)
            except RetsApiError as e:
                if e.reply_code != 20403:  # No object found
                    raise

    return tuple(parse_multipart(multipart.parts))
Esempio n. 5
0
def _parse_multipart(response: ResponseLike,
                     parser: Parser) -> Sequence[Object]:
    """
    RFC 2045 describes the format of an Internet message body containing a MIME message. The
    body contains one or more body parts, each preceded by a boundary delimiter line, and the
    last one followed by a closing boundary delimiter line. After its boundary delimiter line,
    each body part then consists of a header area, a blank line, and a body area.

    HTTP/1.1 200 OK
    Server: Apache/2.0.13
    Date: Fri, 22 OCT 2004 12:03:38 GMT
    Cache-Control: private
    RETS-Version: RETS/1.7.2
    MIME-Version: 1.0
    Content-Type: multipart/parallel; boundary="simple boundary"

    --simple boundary
    Content-Type: image/jpeg
    Content-ID: 123456
    Object-ID: 1

    <binary data>

    --simple boundary
    Content-Type: text/xml
    Content-ID: 123457
    Object-ID: 1

    <RETS ReplyCode="20403" ReplyText="There is no listing with that ListingID"/>

    --simple boundary--
    """
    encoding = response.encoding or DEFAULT_ENCODING
    multipart = MultipartDecoder.from_response(response, encoding)
    # We need to decode the headers because MultipartDecoder returns bytes keys and values,
    # while requests.Response.headers uses str keys and values.
    for part in multipart.parts:
        part.headers = _decode_headers(part.headers, encoding)

    objects = (_parse_body_part(part, parser) for part in multipart.parts)
    return tuple(object_ for object_ in objects if object_ is not None)
 def test_non_multipart_response_fails(self):
     jpeg_response = mock.NonCallableMagicMock(spec=requests.Response)
     jpeg_response.headers = {'content-type': 'image/jpeg'}
     with pytest.raises(NonMultipartContentTypeException):
         MultipartDecoder.from_response(jpeg_response)
Esempio n. 7
0
 def test_non_multipart_response_fails(self):
     jpeg_response = mock.NonCallableMagicMock(spec=requests.Response)
     jpeg_response.headers = {'content-type': 'image/jpeg'}
     with pytest.raises(NonMultipartContentTypeException):
         MultipartDecoder.from_response(jpeg_response)