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'
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 }
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))
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)
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)