1- from typing import AsyncIterator , Iterator , Optional
2- import re
1+ import json
32
43from httpx import Response
5- from httpx ._types import RequestFiles
4+ from httpx ._types import FileTypes
65
76from mpt_api_client .http import AsyncService , Service
8- from mpt_api_client .models import File , Model , ResourceData
7+ from mpt_api_client .models import DownloadFile , Model , ResourceData
98
109
1110class AgreementAttachment (Model ):
@@ -24,13 +23,45 @@ class AgreementsAttachmentService(Service[AgreementAttachment], AgreementsAttach
2423 """Attachments service."""
2524
2625 def create (
27- self , resource_data : ResourceData , files : RequestFiles | None = None
26+ self , resource_data : ResourceData , files : dict [ str , FileTypes ] | None = None
2827 ) -> AgreementAttachment :
29- response = self .http_client .post (self .endpoint , json = resource_data , files = files )
28+ """Create AgreementAttachment resource.
29+
30+ Args:
31+ resource_data: Resource data.
32+ files: Files data.
33+
34+ Returns:
35+ AgreementAttachment resource.
36+ """
37+ files = files or {}
38+
39+ # Note: This is a workaround to fulfill MPT API request format
40+ #
41+ # HTTPx does not support sending json and files in the same call
42+ # currently only supports sending form-data and files in the same call.
43+ # https://www.python-httpx.org/quickstart/#sending-multipart-file-uploads
44+ #
45+ # MPT API expects files and data to be submitted in a multipart form-data upload.
46+ # https://softwareone.atlassian.net/wiki/spaces/mpt/pages/5212079859/Commerce+API#Create-Agreement-Attachment
47+ #
48+ # Current workaround is to send the json data as an unnamed file.
49+ # This ends adding the json as payload multipart data.
50+ #
51+ # json.dumps is setup using the same params of httpx json encoder to produce the same
52+ # encodings.
53+
54+ if resource_data :
55+ json_payload = json .dumps (
56+ resource_data , ensure_ascii = False , separators = ("," , ":" ), allow_nan = False
57+ ).encode ("utf-8" )
58+ files ["_attachment_data" ] = (None , json_payload , "application/json" )
59+
60+ response = self .http_client .post (self .endpoint , files = files )
3061 response .raise_for_status ()
3162 return AgreementAttachment .from_response (response )
3263
33- def download (self , agreement_id : str ) -> File :
64+ def download (self , agreement_id : str ) -> DownloadFile :
3465 """Renders the template for the given Agreement id.
3566
3667 Args:
@@ -40,18 +71,17 @@ def download(self, agreement_id: str) -> File:
4071 Agreement template.
4172 """
4273 response : Response = self ._resource_do_request (
43- agreement_id ,
44- method = "GET" ,
74+ agreement_id , method = "GET" , headers = {"Accept" : "*" }
4575 )
46- return File (response )
76+ return DownloadFile (response )
4777
4878
4979class AsyncAgreementsAttachmentService (
5080 AsyncService [AgreementAttachment ], AgreementsAttachmentServiceConfig
5181):
5282 """Attachments service."""
5383
54- async def download (self , agreement_id : str ) -> File :
84+ async def download (self , agreement_id : str ) -> DownloadFile :
5585 """Renders the template for the given Agreement id.
5686
5787 Args:
@@ -63,4 +93,4 @@ async def download(self, agreement_id: str) -> File:
6393 response = await self ._resource_do_request (
6494 agreement_id , method = "GET" , headers = {"Accept" : "*" }
6595 )
66- return File (response )
96+ return DownloadFile (response )
0 commit comments