fix: repair Mistral OCR async upload (aiohttp.streams.FilePayload removed) (#25779)

_upload_file_async built its multipart body with
`aiohttp.streams.FilePayload(...)`, which no longer exists in aiohttp
(payload classes live in aiohttp.payload, and there is no FilePayload).
The reference sits inside a lazy closure, so import succeeds and only the
async Mistral OCR file-upload path blows up at runtime with
AttributeError on every call.

Mirror the working sync path: open the file in a context manager and let
MultipartWriter.append(file_obj, {...}) build a streaming
BufferedReaderPayload, with the POST issued inside the open() block so
the handle stays valid for the whole upload. Preserves the streaming /
memory-efficiency intent.

Found via the dependency-contract test suite (unit/deps/test_aiohttp.py),
which pins aiohttp.streams.FilePayload as absent.
This commit is contained in:
Classic298
2026-06-29 09:05:54 +02:00
committed by GitHub
parent 8a016931f1
commit c3394288bb

View File

@@ -261,33 +261,32 @@ class MistralLoader:
url = f'{self.base_url}/files'
async def upload_request():
# Create multipart writer for streaming upload
writer = aiohttp.MultipartWriter('form-data')
# Open inside the request so the handle stays valid for the whole
# streamed POST and is closed right after.
with open(self.file_path, 'rb') as f:
writer = aiohttp.MultipartWriter('form-data')
# Add purpose field
purpose_part = writer.append('ocr')
purpose_part.set_content_disposition('form-data', name='purpose')
# Add purpose field
purpose_part = writer.append('ocr')
purpose_part.set_content_disposition('form-data', name='purpose')
# Add file part with streaming
file_part = writer.append_payload(
aiohttp.streams.FilePayload(
self.file_path,
filename=self.file_name,
content_type='application/pdf',
)
)
file_part.set_content_disposition('form-data', name='file', filename=self.file_name)
# Stream the file. aiohttp builds a payload from the file object;
# the previous aiohttp.streams.FilePayload was removed upstream
# (payloads live in aiohttp.payload and there is no FilePayload),
# so this path raised AttributeError on every async OCR upload.
file_part = writer.append(f, {'Content-Type': 'application/pdf'})
file_part.set_content_disposition('form-data', name='file', filename=self.file_name)
self._debug_log(f'Uploading file: {self.file_name} ({self.file_size:,} bytes)')
self._debug_log(f'Uploading file: {self.file_name} ({self.file_size:,} bytes)')
async with session.post(
url,
data=writer,
headers=self.headers,
timeout=aiohttp.ClientTimeout(total=self.upload_timeout),
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as response:
return await self._handle_response_async(response)
async with session.post(
url,
data=writer,
headers=self.headers,
timeout=aiohttp.ClientTimeout(total=self.upload_timeout),
ssl=AIOHTTP_CLIENT_SESSION_SSL,
) as response:
return await self._handle_response_async(response)
response_data = await self._retry_request_async(upload_request)