From 77603a47a11fb8bb7a7720b8180331e906c52b2b Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Tue, 8 Oct 2024 15:17:17 +0300 Subject: [PATCH 01/11] fix add event with depends on --- src/msgraph_core/requests/batch_request_content.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/msgraph_core/requests/batch_request_content.py b/src/msgraph_core/requests/batch_request_content.py index 9a48ef0f..8e99d69c 100644 --- a/src/msgraph_core/requests/batch_request_content.py +++ b/src/msgraph_core/requests/batch_request_content.py @@ -52,7 +52,7 @@ def add_request(self, request_id: Optional[str], request: BatchRequestItem) -> N request.id = str(uuid.uuid4()) if hasattr(request, 'depends_on') and request.depends_on: for dependent_id in request.depends_on: - if dependent_id not in [req.id for req in self.requests]: + if dependent_id not in self.requests: dependent_request = self._request_by_id(dependent_id) if dependent_request: self._requests[dependent_id] = dependent_request From 5711d4f214209f1c1b9caff6a899b32cbeb79ca1 Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Tue, 8 Oct 2024 16:36:22 +0300 Subject: [PATCH 02/11] Enable batch request with content collection --- src/msgraph_core/requests/batch_request_builder.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/msgraph_core/requests/batch_request_builder.py b/src/msgraph_core/requests/batch_request_builder.py index 608876f0..bb8afaa6 100644 --- a/src/msgraph_core/requests/batch_request_builder.py +++ b/src/msgraph_core/requests/batch_request_builder.py @@ -108,6 +108,11 @@ async def _post_batch_collection( for batch_request_content in batch_request_content_collection.batches: request_info = await self.to_post_request_information(batch_request_content) + bytes_content = request_info.content + json_content = bytes_content.decode("utf-8") + updated_str = '{"requests":' + json_content + '}' + updated_bytes = updated_str.encode("utf-8") + request_info.content = updated_bytes response = await self._request_adapter.send_async( request_info, BatchResponseContent, error_map or self.error_map ) From ea8e9f1844ad1f9230d94c3473eeb5d66d4ed2ea Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Tue, 8 Oct 2024 21:19:13 +0300 Subject: [PATCH 03/11] allow post with body --- .../requests/batch_request_builder.py | 30 +++++++++++- .../requests/batch_request_content.py | 6 ++- .../requests/batch_request_item.py | 46 +++++++++++++++---- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/msgraph_core/requests/batch_request_builder.py b/src/msgraph_core/requests/batch_request_builder.py index bb8afaa6..a6dbd38d 100644 --- a/src/msgraph_core/requests/batch_request_builder.py +++ b/src/msgraph_core/requests/batch_request_builder.py @@ -1,5 +1,6 @@ from typing import TypeVar, Type, Dict, Optional, Union import logging +import json from kiota_abstractions.request_adapter import RequestAdapter from kiota_abstractions.request_information import RequestInformation @@ -110,9 +111,34 @@ async def _post_batch_collection( request_info = await self.to_post_request_information(batch_request_content) bytes_content = request_info.content json_content = bytes_content.decode("utf-8") - updated_str = '{"requests":' + json_content + '}' + + requests_list = json.loads(json_content) + for request in requests_list: + if 'body' in request: + request['headers'] = {"Content-Type": "application/json"} + updated_json_content = json.dumps(requests_list) + + updated_str = '{"requests":' + updated_json_content + '}' updated_bytes = updated_str.encode("utf-8") - request_info.content = updated_bytes + + # correct the data type + json_string = updated_bytes.decode('utf-8') + + # Step 2: Parse the string into a Python dictionary + data = json.loads(json_string) + + # Step 3: Convert the 'body' field from string to a dictionary in the first request + for request in data['requests']: + if 'body' in request and isinstance(request['body'], str): + # Convert the 'body' string to a dictionary + request['body'] = json.loads(request['body']) + + # Now 'data' is a proper Python dictionary with valid JSON format + print(json.dumps(data, indent=2)) + request_info.content = json.dumps(data, indent=2) + # request_info.content = updated_bytes + print(f"Request info headrrs: {request_info.headers.get_all()}") + print(f"Request info content: {request_info.content}") response = await self._request_adapter.send_async( request_info, BatchResponseContent, error_map or self.error_map ) diff --git a/src/msgraph_core/requests/batch_request_content.py b/src/msgraph_core/requests/batch_request_content.py index 8e99d69c..88e1c23f 100644 --- a/src/msgraph_core/requests/batch_request_content.py +++ b/src/msgraph_core/requests/batch_request_content.py @@ -137,4 +137,8 @@ def serialize(self, writer: SerializationWriter) -> None: Args: writer: Serialization writer to use to serialize this model """ - writer.write_collection_of_object_values("requests", self.requests) + if not writer: + raise ValueError("writer cannot be None") + + # Ensure requests are serialized correctly + writer.write_collection_of_object_values("requests", list(self.requests.values())) diff --git a/src/msgraph_core/requests/batch_request_item.py b/src/msgraph_core/requests/batch_request_item.py index 61fa480b..82793534 100644 --- a/src/msgraph_core/requests/batch_request_item.py +++ b/src/msgraph_core/requests/batch_request_item.py @@ -1,5 +1,6 @@ import re import json +import enum from uuid import uuid4 from typing import List, Optional, Dict, Union, Any from io import BytesIO @@ -39,8 +40,12 @@ def __init__( if request_information is None or not request_information.http_method: raise ValueError("HTTP method cannot be Null/Empty") self._id = id or str(uuid4()) - self.method = request_information.http_method + if isinstance(request_information.http_method, enum.Enum): + self._method = request_information.http_method.name + else: + self._method = request_information.http_method self._headers = request_information.request_headers + print(f"Body from request_information: {request_information.content}") self._body = request_information.content self.url = request_information.url.replace('/users/me-token-to-replace', '/me', 1) self._depends_on: Optional[List[str]] = [] @@ -232,16 +237,41 @@ def serialize(self, writer: SerializationWriter) -> None: Args: writer (SerializationWriter): The writer to write to. """ + if not writer: + raise ValueError("writer cannot be None") + + print(f"Serializing BatchRequestItem with id: {self.id}") writer.write_str_value('id', self.id) writer.write_str_value('method', self.method) writer.write_str_value('url', self.url) + writer.write_collection_of_primitive_values('depends_on', self._depends_on) - headers = {key: ", ".join(val) for key, val in self._headers.items()} + + headers = self._headers + print(f"Headers to serialize: {headers}") writer.write_collection_of_object_values('headers', headers) + print(self.body) + if self._body: - json_object = json.loads(self._body) - is_json_string = json_object and isinstance(json_object, dict) - writer.write_collection_of_object_values( - 'body', - json_object if is_json_string else base64.b64encode(self._body).decode('utf-8') - ) + if isinstance(self._body, bytes): + # If the body is bytes, encode it as base64 + # body_content = base64.b64encode(self._body).decode('utf-8') + body_content = self._body.decode('utf-8') + print(f"Body content to serialize: 1 {body_content}") + elif isinstance(self._body, str): + try: + # Check if the body is a JSON string + json.loads(self._body) + body_content = self._body # Use the original JSON string + print(f"Body content to serialize: 2 {body_content}") + except json.JSONDecodeError: + # If not, encode it as base64 + body_content = base64.b64encode(self._body.encode('utf-8')).decode('utf-8') + print(f"Body content to serialize:3 {body_content}") + else: + raise ValueError("Unsupported body type") + + print(f"Body to serialize: {body_content}") + writer.write_str_value('body', body_content) + else: + print("No body to serialize") From aeeb5b1eafb65fd54274850be642bede42839ec9 Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Wed, 9 Oct 2024 13:20:08 +0300 Subject: [PATCH 04/11] fix post method lacking body and content-type header --- .../requests/batch_request_builder.py | 62 ++++++++----------- .../requests/batch_request_item.py | 8 --- 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/src/msgraph_core/requests/batch_request_builder.py b/src/msgraph_core/requests/batch_request_builder.py index a6dbd38d..36df3141 100644 --- a/src/msgraph_core/requests/batch_request_builder.py +++ b/src/msgraph_core/requests/batch_request_builder.py @@ -61,11 +61,7 @@ async def post( if isinstance(batch_request_content, BatchRequestContent): request_info = await self.to_post_request_information(batch_request_content) - bytes_content = request_info.content - json_content = bytes_content.decode("utf-8") - updated_str = '{"requests":' + json_content + '}' - updated_bytes = updated_str.encode("utf-8") - request_info.content = updated_bytes + request_info.content = self._prepare_request_content(request_info.content) error_map = error_map or self.error_map response = None try: @@ -109,36 +105,8 @@ async def _post_batch_collection( for batch_request_content in batch_request_content_collection.batches: request_info = await self.to_post_request_information(batch_request_content) - bytes_content = request_info.content - json_content = bytes_content.decode("utf-8") - - requests_list = json.loads(json_content) - for request in requests_list: - if 'body' in request: - request['headers'] = {"Content-Type": "application/json"} - updated_json_content = json.dumps(requests_list) - - updated_str = '{"requests":' + updated_json_content + '}' - updated_bytes = updated_str.encode("utf-8") - - # correct the data type - json_string = updated_bytes.decode('utf-8') - - # Step 2: Parse the string into a Python dictionary - data = json.loads(json_string) - - # Step 3: Convert the 'body' field from string to a dictionary in the first request - for request in data['requests']: - if 'body' in request and isinstance(request['body'], str): - # Convert the 'body' string to a dictionary - request['body'] = json.loads(request['body']) - - # Now 'data' is a proper Python dictionary with valid JSON format - print(json.dumps(data, indent=2)) - request_info.content = json.dumps(data, indent=2) - # request_info.content = updated_bytes - print(f"Request info headrrs: {request_info.headers.get_all()}") - print(f"Request info content: {request_info.content}") + updated_bytes = self._prepare_request_content(request_info.content) + request_info.content = updated_bytes response = await self._request_adapter.send_async( request_info, BatchResponseContent, error_map or self.error_map ) @@ -146,6 +114,30 @@ async def _post_batch_collection( return batch_responses + def _prepare_request_content(self, content: bytes) -> bytes: + """ + Prepares the request content by updating the JSON structure and converting + the 'body' field from string to a dictionary if necessary. + + Args: + content (bytes): The original request content. + + Returns: + bytes: The updated request content. + """ + json_content = content.decode("utf-8") + requests_list = json.loads(json_content) + + for request in requests_list: + if 'body' in request: + request['headers'] = {"Content-Type": "application/json"} + if isinstance(request['body'], str): + request['body'] = json.loads(request['body']) + + updated_json_content = json.dumps(requests_list) + updated_str = '{"requests":' + updated_json_content + '}' + return updated_str.encode("utf-8") + async def to_post_request_information( self, batch_request_content: BatchRequestContent ) -> RequestInformation: diff --git a/src/msgraph_core/requests/batch_request_item.py b/src/msgraph_core/requests/batch_request_item.py index 447ba4ad..5f5fe310 100644 --- a/src/msgraph_core/requests/batch_request_item.py +++ b/src/msgraph_core/requests/batch_request_item.py @@ -46,7 +46,6 @@ def __init__( else: self._method = request_information.http_method self._headers = request_information.request_headers - print(f"Body from request_information: {request_information.content}") self._body = request_information.content self.url = request_information.url.replace('/users/me-token-to-replace', '/me', 1) self._depends_on: Optional[List[str]] = [] @@ -243,7 +242,6 @@ def serialize(self, writer: SerializationWriter) -> None: if not writer: raise ValueError("writer cannot be None") - print(f"Serializing BatchRequestItem with id: {self.id}") writer.write_str_value('id', self.id) writer.write_str_value('method', self.method) writer.write_str_value('url', self.url) @@ -251,30 +249,24 @@ def serialize(self, writer: SerializationWriter) -> None: writer.write_collection_of_primitive_values('depends_on', self._depends_on) headers = self._headers - print(f"Headers to serialize: {headers}") writer.write_collection_of_object_values('headers', headers) - print(self.body) if self._body: if isinstance(self._body, bytes): # If the body is bytes, encode it as base64 # body_content = base64.b64encode(self._body).decode('utf-8') body_content = self._body.decode('utf-8') - print(f"Body content to serialize: 1 {body_content}") elif isinstance(self._body, str): try: # Check if the body is a JSON string json.loads(self._body) body_content = self._body # Use the original JSON string - print(f"Body content to serialize: 2 {body_content}") except json.JSONDecodeError: # If not, encode it as base64 body_content = base64.b64encode(self._body.encode('utf-8')).decode('utf-8') - print(f"Body content to serialize:3 {body_content}") else: raise ValueError("Unsupported body type") - print(f"Body to serialize: {body_content}") writer.write_str_value('body', body_content) else: print("No body to serialize") From 982c1ce6a449819e3a7974b3f5b857788d926c78 Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Wed, 9 Oct 2024 13:54:57 +0300 Subject: [PATCH 05/11] update unit test for batch request content serializaton --- src/msgraph_core/requests/batch_request_item.py | 4 +++- tests/requests/test_batch_request_content.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/msgraph_core/requests/batch_request_item.py b/src/msgraph_core/requests/batch_request_item.py index 5f5fe310..1c7ba35b 100644 --- a/src/msgraph_core/requests/batch_request_item.py +++ b/src/msgraph_core/requests/batch_request_item.py @@ -6,6 +6,8 @@ from typing import List, Optional, Dict, Union, Any from io import BytesIO import base64 +import logging + import urllib.request from urllib.parse import urlparse @@ -269,4 +271,4 @@ def serialize(self, writer: SerializationWriter) -> None: writer.write_str_value('body', body_content) else: - print("No body to serialize") + logging.info("Content info: there is no body to serialize") diff --git a/tests/requests/test_batch_request_content.py b/tests/requests/test_batch_request_content.py index 3ee241af..2499b68b 100644 --- a/tests/requests/test_batch_request_content.py +++ b/tests/requests/test_batch_request_content.py @@ -105,7 +105,9 @@ def test_get_field_deserializers(batch_request_content): def test_serialize(batch_request_content): writer = Mock(spec=SerializationWriter) + batch_request_content.serialize(writer) + writer.write_collection_of_object_values.assert_called_once_with( - "requests", batch_request_content.requests + "requests", list(batch_request_content.requests.values()) ) From f3756d049d9edb592a6ba9ade152369d0c03cce5 Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Wed, 9 Oct 2024 13:59:59 +0300 Subject: [PATCH 06/11] fix(batch_requests): fix batch requests post and depends on --- src/msgraph_core/requests/batch_request_item.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/msgraph_core/requests/batch_request_item.py b/src/msgraph_core/requests/batch_request_item.py index 1c7ba35b..18db8587 100644 --- a/src/msgraph_core/requests/batch_request_item.py +++ b/src/msgraph_core/requests/batch_request_item.py @@ -1,7 +1,6 @@ import re import enum import json -import enum from uuid import uuid4 from typing import List, Optional, Dict, Union, Any from io import BytesIO @@ -255,16 +254,12 @@ def serialize(self, writer: SerializationWriter) -> None: if self._body: if isinstance(self._body, bytes): - # If the body is bytes, encode it as base64 - # body_content = base64.b64encode(self._body).decode('utf-8') body_content = self._body.decode('utf-8') elif isinstance(self._body, str): try: - # Check if the body is a JSON string json.loads(self._body) - body_content = self._body # Use the original JSON string + body_content = self._body except json.JSONDecodeError: - # If not, encode it as base64 body_content = base64.b64encode(self._body.encode('utf-8')).decode('utf-8') else: raise ValueError("Unsupported body type") From 5e036c12fd42434a6fffe87f9fc7118d9422684a Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Wed, 9 Oct 2024 14:03:43 +0300 Subject: [PATCH 07/11] fix(batch_requests): fix batch requests post and depends on --- src/msgraph_core/requests/batch_request_content.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/msgraph_core/requests/batch_request_content.py b/src/msgraph_core/requests/batch_request_content.py index 88e1c23f..b7ee6c7e 100644 --- a/src/msgraph_core/requests/batch_request_content.py +++ b/src/msgraph_core/requests/batch_request_content.py @@ -139,6 +139,4 @@ def serialize(self, writer: SerializationWriter) -> None: """ if not writer: raise ValueError("writer cannot be None") - - # Ensure requests are serialized correctly writer.write_collection_of_object_values("requests", list(self.requests.values())) From bd8eacca214864713afcd26d4b6999d43df0ab5e Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Mon, 14 Oct 2024 14:15:04 +0300 Subject: [PATCH 08/11] add unit tests for json and bytes bodies --- .../requests/batch_request_builder.py | 8 +- .../requests/batch_request_item.py | 12 +-- tests/requests/test_batch_request_item.py | 78 +++++++++++++++++++ 3 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/msgraph_core/requests/batch_request_builder.py b/src/msgraph_core/requests/batch_request_builder.py index 36df3141..c2fbcc0b 100644 --- a/src/msgraph_core/requests/batch_request_builder.py +++ b/src/msgraph_core/requests/batch_request_builder.py @@ -134,9 +134,11 @@ def _prepare_request_content(self, content: bytes) -> bytes: if isinstance(request['body'], str): request['body'] = json.loads(request['body']) - updated_json_content = json.dumps(requests_list) - updated_str = '{"requests":' + updated_json_content + '}' - return updated_str.encode("utf-8") + updated_json_content = json.dumps({"requests": requests_list}) + # updated_json_content = json.dumps(requests_list) + + # updated_str = '{"requests":' + updated_json_content + '}' + return updated_json_content.encode("utf-8") async def to_post_request_information( self, batch_request_content: BatchRequestContent diff --git a/src/msgraph_core/requests/batch_request_item.py b/src/msgraph_core/requests/batch_request_item.py index 18db8587..8e686d19 100644 --- a/src/msgraph_core/requests/batch_request_item.py +++ b/src/msgraph_core/requests/batch_request_item.py @@ -254,13 +254,13 @@ def serialize(self, writer: SerializationWriter) -> None: if self._body: if isinstance(self._body, bytes): - body_content = self._body.decode('utf-8') - elif isinstance(self._body, str): try: - json.loads(self._body) - body_content = self._body - except json.JSONDecodeError: - body_content = base64.b64encode(self._body.encode('utf-8')).decode('utf-8') + body_content = self._body.decode('utf-8') + json.loads(body_content) + except (UnicodeDecodeError, json.JSONDecodeError): + body_content = base64.b64encode(self._body).decode('utf-8') + elif isinstance(self._body, str): + body_content = self._body else: raise ValueError("Unsupported body type") diff --git a/tests/requests/test_batch_request_item.py b/tests/requests/test_batch_request_item.py index 2dd3d863..6d9092b1 100644 --- a/tests/requests/test_batch_request_item.py +++ b/tests/requests/test_batch_request_item.py @@ -1,5 +1,8 @@ import pytest from unittest.mock import Mock +import base64 +import json + from urllib.request import Request from kiota_abstractions.request_information import RequestInformation from kiota_abstractions.method import Method @@ -25,6 +28,51 @@ def batch_request_item(request_info): return BatchRequestItem(request_information=request_info) +@pytest.fixture +def request_info_json(): + request_info = RequestInformation() + request_info.http_method = "POST" + request_info.url = "https://graph.microsoft.com/v1.0/me/events" + request_info.headers = RequestHeaders() + request_info.headers.add("Content-Type", "application/json") + request_info.content = json.dumps( + { + "@odata.type": "#microsoft.graph.event", + "end": { + "dateTime": "2024-10-14T17:30:00", + "timeZone": "Pacific Standard Time" + }, + "start": { + "dateTime": "2024-10-14T17:00:00", + "timeZone": "Pacific Standard Time" + }, + "subject": "File end-of-day report" + } + ).encode('utf-8') + return request_info + + +@pytest.fixture +def request_info_bytes(): + request_info = RequestInformation() + request_info.http_method = "POST" + request_info.url = "https://graph.microsoft.com/v1.0/me/events" + request_info.headers = RequestHeaders() + request_info.headers.add("Content-Type", "application/json") + request_info.content = b'{"@odata.type": "#microsoft.graph.event", "end": {"dateTime": "2024-10-14T17:30:00", "timeZone": "Pacific Standard Time"}, "start": {"dateTime": "2024-10-14T17:00:00", "timeZone": "Pacific Standard Time"}, "subject": "File end-of-day report"}' + return request_info + + +@pytest.fixture +def batch_request_item_json(request_info_json): + return BatchRequestItem(request_information=request_info_json) + + +@pytest.fixture +def batch_request_item_bytes(request_info_bytes): + return BatchRequestItem(request_information=request_info_bytes) + + def test_initialization(batch_request_item, request_info): assert batch_request_item.method == "GET" assert batch_request_item.url == "f{base_url}/me" @@ -124,3 +172,33 @@ def test_batch_request_item_method_enum(): def test_depends_on_property(batch_request_item): batch_request_item.set_depends_on(["request1", "request2"]) assert batch_request_item.depends_on == ["request1", "request2"] + + +def test_serialize_with_json_body(batch_request_item_json): + writer = Mock(spec=SerializationWriter) + + batch_request_item_json.serialize(writer) + + writer.write_str_value.assert_any_call('id', batch_request_item_json.id) + writer.write_str_value.assert_any_call('method', batch_request_item_json.method) + writer.write_str_value.assert_any_call('url', batch_request_item_json.url) + writer.write_collection_of_primitive_values.assert_any_call( + 'depends_on', batch_request_item_json.depends_on + ) + + writer.write_str_value.assert_any_call('body', batch_request_item_json._body.decode('utf-8')) + + +def test_serialize_with_bytes_body(batch_request_item_bytes): + writer = Mock(spec=SerializationWriter) + + batch_request_item_bytes.serialize(writer) + + writer.write_str_value.assert_any_call('id', batch_request_item_bytes.id) + writer.write_str_value.assert_any_call('method', batch_request_item_bytes.method) + writer.write_str_value.assert_any_call('url', batch_request_item_bytes.url) + writer.write_collection_of_primitive_values.assert_any_call( + 'depends_on', batch_request_item_bytes.depends_on + ) + + writer.write_str_value.assert_any_call('body', batch_request_item_bytes._body.decode('utf-8')) From 01fbee02ed920903608dd3cc3eb5157dd4fabfc6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 14 Oct 2024 10:21:26 -0400 Subject: [PATCH 09/11] chore: removes commented out code --- src/msgraph_core/requests/batch_request_builder.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/msgraph_core/requests/batch_request_builder.py b/src/msgraph_core/requests/batch_request_builder.py index c2fbcc0b..9afe055c 100644 --- a/src/msgraph_core/requests/batch_request_builder.py +++ b/src/msgraph_core/requests/batch_request_builder.py @@ -135,9 +135,6 @@ def _prepare_request_content(self, content: bytes) -> bytes: request['body'] = json.loads(request['body']) updated_json_content = json.dumps({"requests": requests_list}) - # updated_json_content = json.dumps(requests_list) - - # updated_str = '{"requests":' + updated_json_content + '}' return updated_json_content.encode("utf-8") async def to_post_request_information( From 57fcbc5dbc0a92264238b4e943f971a94c39b604 Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Thu, 17 Oct 2024 13:30:33 +0300 Subject: [PATCH 10/11] enable bytes in batch request --- .../requests/batch_request_builder.py | 22 +++++++--- .../requests/batch_request_item.py | 7 +--- tests/requests/test_batch_request_item.py | 41 +++++++++---------- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/msgraph_core/requests/batch_request_builder.py b/src/msgraph_core/requests/batch_request_builder.py index c2fbcc0b..0a5a9967 100644 --- a/src/msgraph_core/requests/batch_request_builder.py +++ b/src/msgraph_core/requests/batch_request_builder.py @@ -1,6 +1,7 @@ from typing import TypeVar, Type, Dict, Optional, Union import logging import json +import base64 from kiota_abstractions.request_adapter import RequestAdapter from kiota_abstractions.request_information import RequestInformation @@ -127,17 +128,26 @@ def _prepare_request_content(self, content: bytes) -> bytes: """ json_content = content.decode("utf-8") requests_list = json.loads(json_content) - for request in requests_list: if 'body' in request: + if isinstance(request['body'], dict): + pass + elif isinstance(request['body'], str): + try: + request['body'] = json.loads(request['body']) + except json.JSONDecodeError: + pass + elif isinstance(request['body'], bytes): + request['body'] = base64.b64encode(request['body']).decode('utf-8') + + if isinstance(request['body'], dict): + request['headers'] = {"Content-Type": "application/json"} + else: + request['headers'] = {"Content-Type": "application/octet-stream"} + else: request['headers'] = {"Content-Type": "application/json"} - if isinstance(request['body'], str): - request['body'] = json.loads(request['body']) updated_json_content = json.dumps({"requests": requests_list}) - # updated_json_content = json.dumps(requests_list) - - # updated_str = '{"requests":' + updated_json_content + '}' return updated_json_content.encode("utf-8") async def to_post_request_information( diff --git a/src/msgraph_core/requests/batch_request_item.py b/src/msgraph_core/requests/batch_request_item.py index 8e686d19..57e81ba7 100644 --- a/src/msgraph_core/requests/batch_request_item.py +++ b/src/msgraph_core/requests/batch_request_item.py @@ -254,16 +254,11 @@ def serialize(self, writer: SerializationWriter) -> None: if self._body: if isinstance(self._body, bytes): - try: - body_content = self._body.decode('utf-8') - json.loads(body_content) - except (UnicodeDecodeError, json.JSONDecodeError): - body_content = base64.b64encode(self._body).decode('utf-8') + body_content = base64.b64encode(self._body).decode('utf-8') elif isinstance(self._body, str): body_content = self._body else: raise ValueError("Unsupported body type") - writer.write_str_value('body', body_content) else: logging.info("Content info: there is no body to serialize") diff --git a/tests/requests/test_batch_request_item.py b/tests/requests/test_batch_request_item.py index 6d9092b1..005bcf44 100644 --- a/tests/requests/test_batch_request_item.py +++ b/tests/requests/test_batch_request_item.py @@ -73,6 +73,15 @@ def batch_request_item_bytes(request_info_bytes): return BatchRequestItem(request_information=request_info_bytes) +def encode_body_to_base64(body): + if isinstance(body, bytes): + return base64.b64encode(body).decode('utf-8') + elif isinstance(body, str): + return base64.b64encode(body.encode('utf-8')).decode('utf-8') + else: + raise ValueError("Unsupported body type") + + def test_initialization(batch_request_item, request_info): assert batch_request_item.method == "GET" assert batch_request_item.url == "f{base_url}/me" @@ -175,30 +184,18 @@ def test_depends_on_property(batch_request_item): def test_serialize_with_json_body(batch_request_item_json): - writer = Mock(spec=SerializationWriter) - - batch_request_item_json.serialize(writer) + item = batch_request_item_json + writer = Mock() + processed_body = encode_body_to_base64(item.body) - writer.write_str_value.assert_any_call('id', batch_request_item_json.id) - writer.write_str_value.assert_any_call('method', batch_request_item_json.method) - writer.write_str_value.assert_any_call('url', batch_request_item_json.url) - writer.write_collection_of_primitive_values.assert_any_call( - 'depends_on', batch_request_item_json.depends_on - ) - - writer.write_str_value.assert_any_call('body', batch_request_item_json._body.decode('utf-8')) + item.serialize(writer) + writer.write_str_value.assert_called_with('body', processed_body) def test_serialize_with_bytes_body(batch_request_item_bytes): - writer = Mock(spec=SerializationWriter) - - batch_request_item_bytes.serialize(writer) - - writer.write_str_value.assert_any_call('id', batch_request_item_bytes.id) - writer.write_str_value.assert_any_call('method', batch_request_item_bytes.method) - writer.write_str_value.assert_any_call('url', batch_request_item_bytes.url) - writer.write_collection_of_primitive_values.assert_any_call( - 'depends_on', batch_request_item_bytes.depends_on - ) + item = batch_request_item_bytes + writer = Mock() + processed_body = encode_body_to_base64(item.body) - writer.write_str_value.assert_any_call('body', batch_request_item_bytes._body.decode('utf-8')) + item.serialize(writer) + writer.write_str_value.assert_called_with('body', processed_body) From 5e448a10e718c8a72158f9521f6e2e5bb3d103d2 Mon Sep 17 00:00:00 2001 From: shemogumbe Date: Thu, 17 Oct 2024 14:25:10 +0300 Subject: [PATCH 11/11] set headers in batch request item --- src/msgraph_core/requests/batch_request_builder.py | 7 +++++++ src/msgraph_core/requests/batch_request_content.py | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/msgraph_core/requests/batch_request_builder.py b/src/msgraph_core/requests/batch_request_builder.py index 0a5a9967..de0e7098 100644 --- a/src/msgraph_core/requests/batch_request_builder.py +++ b/src/msgraph_core/requests/batch_request_builder.py @@ -61,6 +61,7 @@ async def post( response_type = BatchResponseContent if isinstance(batch_request_content, BatchRequestContent): + print(f"Batch request content: {batch_request_content.requests}") request_info = await self.to_post_request_information(batch_request_content) request_info.content = self._prepare_request_content(request_info.content) error_map = error_map or self.error_map @@ -105,7 +106,10 @@ async def _post_batch_collection( batch_responses = BatchResponseContentCollection() for batch_request_content in batch_request_content_collection.batches: + print(f"Batch request content: {batch_request_content.requests}") + request_info = await self.to_post_request_information(batch_request_content) + print(f"content before processing {request_info.content}") updated_bytes = self._prepare_request_content(request_info.content) request_info.content = updated_bytes response = await self._request_adapter.send_async( @@ -127,6 +131,7 @@ def _prepare_request_content(self, content: bytes) -> bytes: bytes: The updated request content. """ json_content = content.decode("utf-8") + print(json_content) requests_list = json.loads(json_content) for request in requests_list: if 'body' in request: @@ -149,6 +154,7 @@ def _prepare_request_content(self, content: bytes) -> bytes: updated_json_content = json.dumps({"requests": requests_list}) return updated_json_content.encode("utf-8") + # return json.dumps(requests_list).encode("utf-8") async def to_post_request_information( self, batch_request_content: BatchRequestContent @@ -166,6 +172,7 @@ async def to_post_request_information( if batch_request_content is None: raise ValueError("batch_request_content cannot be Null.") batch_request_items = list(batch_request_content.requests.values()) + print(f"Batch request items: {batch_request_items}") request_info = RequestInformation() request_info.http_method = Method.POST diff --git a/src/msgraph_core/requests/batch_request_content.py b/src/msgraph_core/requests/batch_request_content.py index b7ee6c7e..1ba93622 100644 --- a/src/msgraph_core/requests/batch_request_content.py +++ b/src/msgraph_core/requests/batch_request_content.py @@ -139,4 +139,6 @@ def serialize(self, writer: SerializationWriter) -> None: """ if not writer: raise ValueError("writer cannot be None") - writer.write_collection_of_object_values("requests", list(self.requests.values())) + writer.write_collection_of_object_values({"requests", list(self.requests.values())}) + # requests_dict = {request_id: request for request_id, request in self.requests.items()} + # writer.write_object_value("requests", requests_dict)