|
69 | 69 | except ImportError: |
70 | 70 | has_cloudpickle = False |
71 | 71 |
|
| 72 | +try: |
| 73 | + from pydantic import BaseModel |
| 74 | + has_pydantic = True |
| 75 | +except ImportError: |
| 76 | + has_pydantic = False |
| 77 | + |
72 | 78 |
|
73 | 79 | logger = utils.get_logger('singlestoredb.functions.ext.asgi') |
74 | 80 |
|
@@ -138,13 +144,24 @@ def get_func_names(funcs: str) -> List[Tuple[str, str]]: |
138 | 144 |
|
139 | 145 |
|
140 | 146 | def as_tuple(x: Any) -> Any: |
141 | | - if hasattr(x, 'model_fields'): |
142 | | - return tuple(x.model_fields.values()) |
| 147 | + """Convert object to tuple.""" |
| 148 | + if has_pydantic and isinstance(x, BaseModel): |
| 149 | + return tuple(x.model_dump().values()) |
143 | 150 | if dataclasses.is_dataclass(x): |
144 | 151 | return dataclasses.astuple(x) |
145 | 152 | return x |
146 | 153 |
|
147 | 154 |
|
| 155 | +def as_list_of_tuples(x: Any) -> Any: |
| 156 | + """Convert object to a list of tuples.""" |
| 157 | + if isinstance(x, (list, tuple)) and len(x) > 0: |
| 158 | + if has_pydantic and isinstance(x[0], BaseModel): |
| 159 | + return [tuple(y.model_dump().values()) for y in x] |
| 160 | + if dataclasses.is_dataclass(x[0]): |
| 161 | + return [dataclasses.astuple(y) for y in x] |
| 162 | + return x |
| 163 | + |
| 164 | + |
148 | 165 | def make_func( |
149 | 166 | name: str, |
150 | 167 | func: Callable[..., Any], |
@@ -183,7 +200,7 @@ async def do_func( |
183 | 200 | out_ids: List[int] = [] |
184 | 201 | out = [] |
185 | 202 | for i, res in zip(row_ids, func_map(func, rows)): |
186 | | - out.extend(as_tuple(res)) |
| 203 | + out.extend(as_list_of_tuples(res)) |
187 | 204 | out_ids.extend([row_ids[i]] * (len(out)-len(out_ids))) |
188 | 205 | return out_ids, out |
189 | 206 |
|
|
0 commit comments