Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,14 @@ def __init__(self) -> None:

def write_str_value(self, key: Optional[str], value: Optional[str]) -> None:
"""Writes the specified string value to the stream with an optional given key.
If value is None, no output is written to avoid emitting bare header names.

Args:
key (Optional[str]): The key to be used for the written value. May be null.
value (Optional[str]): The string value to be written.
value (Optional[str]): The string value to be written. If None, the value is omitted.
"""
if value is None:
return
if key:
self.writer.write(key)
if value:
Expand Down Expand Up @@ -161,7 +165,10 @@ def write_collection_of_object_values(
raise NotImplementedError()

def write_object_value(
self, key: Optional[str], value: Optional[U], *additional_values_to_merge: Optional[U]
self,
key: Optional[str],
value: Optional[U],
*additional_values_to_merge: Optional[U],
) -> None:
"""Writes the specified model object to the stream with an optional given key.
Args:
Expand All @@ -170,7 +177,8 @@ def write_object_value(
additional_values_to_merge (tuple[Parsable]): The additional values to merge to the
main value when serializing an intersection wrapper.
"""
temp_writer = self._create_new_writer()
if value is None:
return
Comment thread
baywet marked this conversation as resolved.

if not isinstance(value, MultipartBody):
raise ValueError(f"Expected a MultipartBody instance but got {type(value)}")
Expand Down Expand Up @@ -260,13 +268,13 @@ def on_start_object_serialization(
"""
self._on_start_object_serialization = value

def _serialize_value(self, temp_writer: MultipartSerializationWriter, value: U) -> None:
def _serialize_value(self, writer: MultipartSerializationWriter, value: U) -> None:
if on_before := self.on_before_object_serialization:
on_before(value)
if on_start := self.on_start_object_serialization:
on_start(value, self)

value.serialize(temp_writer)
value.serialize(writer)

def _create_new_writer(self) -> SerializationWriter:
writer = MultipartSerializationWriter()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
from uuid import UUID
from datetime import date, datetime, time, timedelta
from unittest.mock import Mock
from uuid import UUID

import pytest

from datetime import datetime, timedelta, date, time
from kiota_serialization_multipart.multipart_serialization_writer import MultipartSerializationWriter
from kiota_serialization_multipart.multipart_serialization_writer import (
MultipartSerializationWriter,
)

from ..helpers import TestEntity, TestEnum


Expand Down Expand Up @@ -33,84 +37,140 @@ def test_not_implemented():
writer.write_collection_of_object_values("users", [TestEntity()])
with pytest.raises(NotImplementedError):
writer.write_collection_of_primitive_values("numbers", [1, 2.0, "3"])



def test_write_string_value():
serialization_writer = MultipartSerializationWriter()
serialization_writer.write_str_value("message", "Hello world")
content = serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == "message: Hello world\r\n"


def test_write_bytes_value_bytes():
serialization_writer = MultipartSerializationWriter()
serialization_writer.write_bytes_value("", b"Hello world")
content = serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == "Hello world"



def test_write_object_value_raises_exception_on_parseable_object():
serialization_writer = MultipartSerializationWriter()
with pytest.raises(ValueError) as excinfo:
serialization_writer.write_object_value("user", TestEntity())
assert "Expected a MultipartBody instance but got" in str(excinfo.value)

def test_write_object_value(user_1, mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body):
mock_request_adapter.get_serialization_writer_factory = Mock(return_value=mock_serialization_writer_factory)


def test_write_object_value(
user_1, mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body
):
mock_request_adapter.get_serialization_writer_factory = Mock(
return_value=mock_serialization_writer_factory
)
mock_multipart_body.request_adapter = mock_request_adapter
mock_multipart_body.add_or_replace_part("test user", "application/json", user_1)
mock_multipart_body.add_or_replace_part("img", "application/octet-stream", b"Hello world")

serialization_writer = MultipartSerializationWriter()
serialization_writer.write_object_value("", mock_multipart_body, None)
content = serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == f'--{mock_multipart_body.boundary}'+'\r\nContent-Type: application/json\r\nContent-Disposition: form-data; name="test user"\r\n\r\n{"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845", "workDuration": "2:00:00", "birthDay": "2017-09-04", "startWorkTime": "00:00:00", "createdDateTime": "2022-01-27T12:59:45", "businessPhones": ["+1 412 555 0109"], "mobilePhone": null, "accountEnabled": false, "jobTitle": "Auditor", "manager": {"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845"}}\r\n'+f'--{mock_multipart_body.boundary}'+'\r\nContent-Type: application/octet-stream\r\nContent-Disposition: form-data; name="img"\r\n\r\nHello world\r\n'+f'--{mock_multipart_body.boundary}--\r\n'

def test_write_object_value_inverted(user_1, mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body):
mock_request_adapter.get_serialization_writer_factory = Mock(return_value=mock_serialization_writer_factory)
assert content_string == f'--{mock_multipart_body.boundary}' + '\r\nContent-Type: application/json\r\nContent-Disposition: form-data; name="test user"\r\n\r\n{"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845", "workDuration": "2:00:00", "birthDay": "2017-09-04", "startWorkTime": "00:00:00", "createdDateTime": "2022-01-27T12:59:45", "businessPhones": ["+1 412 555 0109"], "mobilePhone": null, "accountEnabled": false, "jobTitle": "Auditor", "manager": {"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845"}}\r\n' + f'--{mock_multipart_body.boundary}' + '\r\nContent-Type: application/octet-stream\r\nContent-Disposition: form-data; name="img"\r\n\r\nHello world\r\n' + f'--{mock_multipart_body.boundary}--\r\n'


def test_write_object_value_inverted(
user_1, mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body
):
mock_request_adapter.get_serialization_writer_factory = Mock(
return_value=mock_serialization_writer_factory
)
mock_multipart_body.request_adapter = mock_request_adapter
mock_multipart_body.add_or_replace_part("img", "application/octet-stream", b"Hello world")
mock_multipart_body.add_or_replace_part("test user", "application/json", user_1)

serialization_writer = MultipartSerializationWriter()
serialization_writer.write_object_value("", mock_multipart_body, None)
content = serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == f'--{mock_multipart_body.boundary}'+'\r\nContent-Type: application/octet-stream\r\nContent-Disposition: form-data; name="img"\r\n\r\nHello world\r\n'+f'--{mock_multipart_body.boundary}'+'\r\nContent-Type: application/json\r\nContent-Disposition: form-data; name="test user"\r\n\r\n{"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845", "workDuration": "2:00:00", "birthDay": "2017-09-04", "startWorkTime": "00:00:00", "createdDateTime": "2022-01-27T12:59:45", "businessPhones": ["+1 412 555 0109"], "mobilePhone": null, "accountEnabled": false, "jobTitle": "Auditor", "manager": {"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845"}}\r\n'+f'--{mock_multipart_body.boundary}--\r\n'
assert content_string == f'--{mock_multipart_body.boundary}' + '\r\nContent-Type: application/octet-stream\r\nContent-Disposition: form-data; name="img"\r\n\r\nHello world\r\n' + f'--{mock_multipart_body.boundary}' + '\r\nContent-Type: application/json\r\nContent-Disposition: form-data; name="test user"\r\n\r\n{"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845", "workDuration": "2:00:00", "birthDay": "2017-09-04", "startWorkTime": "00:00:00", "createdDateTime": "2022-01-27T12:59:45", "businessPhones": ["+1 412 555 0109"], "mobilePhone": null, "accountEnabled": false, "jobTitle": "Auditor", "manager": {"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845"}}\r\n' + f'--{mock_multipart_body.boundary}--\r\n'


def test_write_object_value_with_filename(user_1, mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body):
mock_request_adapter.get_serialization_writer_factory = Mock(return_value=mock_serialization_writer_factory)
def test_write_object_value_with_filename(
user_1, mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body
):
mock_request_adapter.get_serialization_writer_factory = Mock(
return_value=mock_serialization_writer_factory
)
mock_multipart_body.request_adapter = mock_request_adapter
mock_multipart_body.add_or_replace_part("test user", "application/json", user_1)
mock_multipart_body.add_or_replace_part("file", "application/octet-stream", b"Hello world", "file.txt")
mock_multipart_body.add_or_replace_part(
"file", "application/octet-stream", b"Hello world", "file.txt"
)

serialization_writer = MultipartSerializationWriter()
serialization_writer.write_object_value("", mock_multipart_body, None)
content = serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == f'--{mock_multipart_body.boundary}' + '\r\nContent-Type: application/json\r\nContent-Disposition: form-data; name="test user"\r\n\r\n{"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845", "workDuration": "2:00:00", "birthDay": "2017-09-04", "startWorkTime": "00:00:00", "createdDateTime": "2022-01-27T12:59:45", "businessPhones": ["+1 412 555 0109"], "mobilePhone": null, "accountEnabled": false, "jobTitle": "Auditor", "manager": {"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845"}}\r\n' + f'--{mock_multipart_body.boundary}' + '\r\nContent-Type: application/octet-stream\r\nContent-Disposition: form-data; name="file"; filename="file.txt"\r\n\r\nHello world\r\n' + f'--{mock_multipart_body.boundary}--\r\n'


def test_write_object_value_with_string_part(
mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body
):
mock_request_adapter.get_serialization_writer_factory = Mock(
return_value=mock_serialization_writer_factory
)
mock_multipart_body.request_adapter = mock_request_adapter
mock_multipart_body.add_or_replace_part("message", "text/plain", "Hello world")

serialization_writer = MultipartSerializationWriter()
serialization_writer.write_object_value("", mock_multipart_body, None)
content = serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == f'--{mock_multipart_body.boundary}'+'\r\nContent-Type: application/json\r\nContent-Disposition: form-data; name="test user"\r\n\r\n{"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845", "workDuration": "2:00:00", "birthDay": "2017-09-04", "startWorkTime": "00:00:00", "createdDateTime": "2022-01-27T12:59:45", "businessPhones": ["+1 412 555 0109"], "mobilePhone": null, "accountEnabled": false, "jobTitle": "Auditor", "manager": {"id": "eac79bd3-fd08-4abf-9df2-2565cf3a3845"}}\r\n'+f'--{mock_multipart_body.boundary}'+'\r\nContent-Type: application/octet-stream\r\nContent-Disposition: form-data; name="file"; filename="file.txt"\r\n\r\nHello world\r\n'+f'--{mock_multipart_body.boundary}--\r\n'
assert content_string == f'--{mock_multipart_body.boundary}' + '\r\nContent-Type: text/plain\r\nContent-Disposition: form-data; name="message"\r\n\r\nHello world\r\n' + f'--{mock_multipart_body.boundary}--\r\n'

def test_write_object_value_with_string_part(mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body):
mock_request_adapter.get_serialization_writer_factory = Mock(return_value=mock_serialization_writer_factory)
mock_multipart_body.request_adapter = mock_request_adapter
mock_multipart_body.add_or_replace_part("message", "text/plain", "Hello world")

def test_write_object_value_with_multiple_string_parts(
mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body
):
mock_request_adapter.get_serialization_writer_factory = Mock(
return_value=mock_serialization_writer_factory
)
mock_multipart_body.request_adapter = mock_request_adapter
mock_multipart_body.add_or_replace_part("message1", "text/plain", "Hello world")
mock_multipart_body.add_or_replace_part("message2", "text/plain", "Goodbye world")

serialization_writer = MultipartSerializationWriter()
serialization_writer.write_object_value("", mock_multipart_body, None)
content = serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == f'--{mock_multipart_body.boundary}' + '\r\nContent-Type: text/plain\r\nContent-Disposition: form-data; name="message1"\r\n\r\nHello world\r\n' + f'--{mock_multipart_body.boundary}' + '\r\nContent-Type: text/plain\r\nContent-Disposition: form-data; name="message2"\r\n\r\nGoodbye world\r\n' + f'--{mock_multipart_body.boundary}--\r\n'

serialization_writer = MultipartSerializationWriter()
serialization_writer.write_object_value("", mock_multipart_body, None)
content = serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == f'--{mock_multipart_body.boundary}'+'\r\nContent-Type: text/plain\r\nContent-Disposition: form-data; name="message"\r\n\r\nHello world\r\n'+f'--{mock_multipart_body.boundary}--\r\n'

def test_write_object_value_with_multiple_string_parts(mock_request_adapter, mock_serialization_writer_factory, mock_multipart_body):
mock_request_adapter.get_serialization_writer_factory = Mock(return_value=mock_serialization_writer_factory)
mock_multipart_body.request_adapter = mock_request_adapter
mock_multipart_body.add_or_replace_part("message1", "text/plain", "Hello world")
mock_multipart_body.add_or_replace_part("message2", "text/plain", "Goodbye world")
def test_write_str_value_omits_nil_value():
serialization_writer = MultipartSerializationWriter()
serialization_writer.write_str_value("Content-Type", None)
content = serialization_writer.get_serialized_content()
assert content == b""


serialization_writer = MultipartSerializationWriter()
serialization_writer.write_object_value("", mock_multipart_body, None)
content = serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == f'--{mock_multipart_body.boundary}'+'\r\nContent-Type: text/plain\r\nContent-Disposition: form-data; name="message1"\r\n\r\nHello world\r\n'+f'--{mock_multipart_body.boundary}'+'\r\nContent-Type: text/plain\r\nContent-Disposition: form-data; name="message2"\r\n\r\nGoodbye world\r\n'+f'--{mock_multipart_body.boundary}--\r\n'
def test_write_str_value_omits_both_nil():
serialization_writer = MultipartSerializationWriter()
serialization_writer.write_str_value(None, None)
content = serialization_writer.get_serialized_content()
assert content == b""


def test_write_object_value_handles_none_gracefully():
serialization_writer = MultipartSerializationWriter()
serialization_writer.write_object_value("", None)
content = serialization_writer.get_serialized_content()
assert content == b""


def test_write_object_value_none_primary_with_none_additional_values_noop():
serialization_writer = MultipartSerializationWriter()
serialization_writer.write_object_value("", None, None, None)
assert len(serialization_writer.get_serialized_content()) == 0

Loading