Skip to content

Commit 922e88f

Browse files
author
Cyrus Radfar
committed
Improved handling of file to work with script.
1 parent 352d03e commit 922e88f

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

python_anvil/models.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from typing import Any
22
from io import BytesIO, BufferedReader
3+
from mimetypes import guess_type
4+
import base64
5+
import os
36

47
try:
58
from pydantic import BaseModel
@@ -14,10 +17,10 @@
1417
from pydantic import ConfigDict
1518
class FileCompatibleBaseModel(BaseModel):
1619
"""
17-
Patched model_dump to extract file objects from SerializationIterator in V2
18-
and return as BufferedReader
20+
Patched model_dump to extract file objects from SerializationIterator in V2
21+
and return as BufferedReader or base64 encoded dict as needed.
1922
"""
20-
# Allow extra fields even if it is not defined. This will allow models
23+
# Allow extra fields even if it is not defined. This will allow models
2124
# to be more flexible if features are added in the Anvil API, but
2225
# explicit support hasn't been added yet to this library.
2326
model_config = ConfigDict(
@@ -46,21 +49,41 @@ def _iterator_to_buffered_reader(self, value):
4649
def _check_if_serialization_iterator(self, value):
4750
return str(type(value).__name__) == 'SerializationIterator' and hasattr(value, '__next__')
4851

52+
def _process_file_data(self, file_obj):
53+
"""Process file object into base64 encoded dict format."""
54+
# Read the file data and encode it as base64
55+
file_content = file_obj.read()
56+
57+
# Get filename - handle both regular files and BytesIO objects
58+
filename = getattr(file_obj, 'name', "document.pdf")
59+
60+
if isinstance(filename, (bytes, bytearray)):
61+
filename = filename.decode('utf-8')
62+
63+
# manage mimetype based on file extension
64+
mimetype = guess_type(filename)[0] or 'application/pdf'
65+
66+
return {
67+
'data': base64.b64encode(file_content).decode('utf-8'),
68+
'mimetype': mimetype,
69+
'filename': os.path.basename(filename)
70+
}
71+
4972
def model_dump(self, **kwargs):
5073
data = super().model_dump(**kwargs)
5174
for key, value in data.items():
5275
if key == 'file' and self._check_if_serialization_iterator(value):
5376
# Direct file case
54-
data[key] = self._iterator_to_buffered_reader(value)
77+
file_obj = self._iterator_to_buffered_reader(value)
78+
data[key] = self._process_file_data(file_obj)
5579
elif key == 'files' and isinstance(value, list):
5680
# List of objects case
5781
for index, item in enumerate(value):
5882
if isinstance(item, dict) and 'file' in item:
5983
if self._check_if_serialization_iterator(item['file']):
60-
data[key][index]['file'] = self._iterator_to_buffered_reader(item['file'])
84+
file_obj = self._iterator_to_buffered_reader(item['file'])
85+
data[key][index]['file'] = self._process_file_data(file_obj)
6186
return data
62-
63-
6487

6588
else:
6689
FileCompatibleBaseModel = BaseModel

0 commit comments

Comments
 (0)