clarifai 11.1.5__py3-none-any.whl → 11.1.5rc2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- clarifai/__init__.py +1 -1
- clarifai/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/__pycache__/errors.cpython-310.pyc +0 -0
- clarifai/__pycache__/versions.cpython-310.pyc +0 -0
- clarifai/cli/__main__.py~ +4 -0
- clarifai/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/__main__.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/compute_cluster.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/deployment.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/model.cpython-310.pyc +0 -0
- clarifai/cli/__pycache__/nodepool.cpython-310.pyc +0 -0
- clarifai/cli/model.py +25 -0
- clarifai/client/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/app.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/dataset.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/input.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/lister.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/model.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/module.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/runner.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/search.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/user.cpython-310.pyc +0 -0
- clarifai/client/__pycache__/workflow.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/helper.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/register.cpython-310.pyc +0 -0
- clarifai/client/auth/__pycache__/stub.cpython-310.pyc +0 -0
- clarifai/client/model.py +89 -365
- clarifai/client/model_client.py +422 -0
- clarifai/constants/__pycache__/dataset.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/model.cpython-310.pyc +0 -0
- clarifai/constants/__pycache__/search.cpython-310.pyc +0 -0
- clarifai/datasets/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/export/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/export/__pycache__/inputs_annotations.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/features.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/image.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/text.cpython-310.pyc +0 -0
- clarifai/datasets/upload/__pycache__/utils.cpython-310.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-310.pyc +0 -0
- clarifai/models/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/__pycache__/constants.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/_utils.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/build.cpython-310.pyc +0 -0
- clarifai/models/model_serving/cli/__pycache__/create.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/base.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/config.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/inference_parameter.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/__pycache__/output.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/serializer.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/triton_config.cpython-310.pyc +0 -0
- clarifai/models/model_serving/model_config/triton/__pycache__/wrappers.cpython-310.pyc +0 -0
- clarifai/models/model_serving/repo_build/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/models/model_serving/repo_build/__pycache__/build.cpython-310.pyc +0 -0
- clarifai/models/model_serving/repo_build/static_files/__pycache__/base_test.cpython-310-pytest-7.2.0.pyc +0 -0
- clarifai/rag/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/rag/__pycache__/rag.cpython-310.pyc +0 -0
- clarifai/rag/__pycache__/utils.cpython-310.pyc +0 -0
- clarifai/runners/__init__.py +2 -7
- clarifai/runners/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/runners/__pycache__/server.cpython-310.pyc +0 -0
- clarifai/runners/dockerfile_template/Dockerfile.debug +11 -0
- clarifai/runners/dockerfile_template/Dockerfile.debug~ +9 -0
- clarifai/runners/dockerfile_template/Dockerfile.template +3 -0
- clarifai/runners/models/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/base_typed_model.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_builder.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_class.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_run_locally.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_runner.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_servicer.cpython-310.pyc +0 -0
- clarifai/runners/models/__pycache__/model_upload.cpython-310.pyc +0 -0
- clarifai/runners/models/model_builder.py +33 -7
- clarifai/runners/models/model_class.py +269 -28
- clarifai/runners/models/model_run_locally.py +3 -78
- clarifai/runners/models/model_runner.py +2 -0
- clarifai/runners/models/model_servicer.py +11 -2
- clarifai/runners/server.py +5 -1
- clarifai/runners/utils/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/const.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_handler.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_types.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/loader.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/logging.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/method_signatures.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/serializers.cpython-310.pyc +0 -0
- clarifai/runners/utils/__pycache__/url_fetcher.cpython-310.pyc +0 -0
- clarifai/runners/utils/data_handler.py +308 -205
- clarifai/runners/utils/data_types.py +334 -0
- clarifai/runners/utils/method_signatures.py +452 -0
- clarifai/runners/utils/serializers.py +132 -0
- clarifai/schema/__pycache__/search.cpython-310.pyc +0 -0
- clarifai/urls/__pycache__/helper.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/logging.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/misc.cpython-310.pyc +0 -0
- clarifai/utils/__pycache__/model_train.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/helpers.cpython-310.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/main.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/__init__.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/export.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/utils.cpython-310.pyc +0 -0
- clarifai/workflows/__pycache__/validate.cpython-310.pyc +0 -0
- {clarifai-11.1.5.dist-info → clarifai-11.1.5rc2.dist-info}/METADATA +16 -26
- clarifai-11.1.5rc2.dist-info/RECORD +203 -0
- {clarifai-11.1.5.dist-info → clarifai-11.1.5rc2.dist-info}/WHEEL +1 -1
- clarifai/runners/models/base_typed_model.py +0 -238
- clarifai-11.1.5.dist-info/RECORD +0 -101
- {clarifai-11.1.5.dist-info → clarifai-11.1.5rc2.dist-info}/LICENSE +0 -0
- {clarifai-11.1.5.dist-info → clarifai-11.1.5rc2.dist-info}/entry_points.txt +0 -0
- {clarifai-11.1.5.dist-info → clarifai-11.1.5rc2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,334 @@
|
|
1
|
+
import io
|
2
|
+
from typing import Iterable, List, get_args, get_origin
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Audio as AudioProto
|
6
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Concept as ConceptProto
|
7
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Frame as FrameProto
|
8
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Image as ImageProto
|
9
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Region as RegionProto
|
10
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Text as TextProto
|
11
|
+
from clarifai_grpc.grpc.api.resources_pb2 import Video as VideoProto
|
12
|
+
from PIL import Image as PILImage
|
13
|
+
|
14
|
+
|
15
|
+
class MessageData:
|
16
|
+
|
17
|
+
def to_proto(self):
|
18
|
+
raise NotImplementedError
|
19
|
+
|
20
|
+
@classmethod
|
21
|
+
def from_proto(cls, proto):
|
22
|
+
raise NotImplementedError
|
23
|
+
|
24
|
+
def cast(self, python_type):
|
25
|
+
if python_type == self.__class__:
|
26
|
+
return self
|
27
|
+
raise TypeError(f'Incompatible type for {self.__class__.__name__}: {python_type}')
|
28
|
+
|
29
|
+
|
30
|
+
class Output(dict):
|
31
|
+
__getattr__ = dict.__getitem__
|
32
|
+
__setattr__ = dict.__setitem__
|
33
|
+
|
34
|
+
def __origin__(self):
|
35
|
+
return self
|
36
|
+
|
37
|
+
def __args__(self):
|
38
|
+
return list(self.keys())
|
39
|
+
|
40
|
+
|
41
|
+
class Input(dict):
|
42
|
+
__getattr__ = dict.__getitem__
|
43
|
+
__setattr__ = dict.__setitem__
|
44
|
+
|
45
|
+
def __origin__(self):
|
46
|
+
return self
|
47
|
+
|
48
|
+
def __args__(self):
|
49
|
+
return list(self.keys())
|
50
|
+
|
51
|
+
|
52
|
+
class Stream(Iterable):
|
53
|
+
pass
|
54
|
+
|
55
|
+
|
56
|
+
class Text(MessageData):
|
57
|
+
|
58
|
+
def __init__(self, text: str, url: str = None):
|
59
|
+
self.text = text
|
60
|
+
self.url = url
|
61
|
+
|
62
|
+
def to_proto(self) -> TextProto:
|
63
|
+
return TextProto(raw=self.text or '', url=self.url or '')
|
64
|
+
|
65
|
+
@classmethod
|
66
|
+
def from_proto(cls, proto: TextProto) -> "Text":
|
67
|
+
return cls(proto.raw, proto.url or None)
|
68
|
+
|
69
|
+
def cast(self, python_type):
|
70
|
+
if python_type == str:
|
71
|
+
return self.text
|
72
|
+
if python_type == Text:
|
73
|
+
return self
|
74
|
+
raise TypeError(f'Incompatible type for Text: {python_type}')
|
75
|
+
|
76
|
+
|
77
|
+
class Concept(MessageData):
|
78
|
+
|
79
|
+
def __init__(self, name: str, value: float = 0):
|
80
|
+
self.name = name
|
81
|
+
self.value = value
|
82
|
+
|
83
|
+
def __repr__(self) -> str:
|
84
|
+
return f"Concept(name={self.name!r}, value={self.value})"
|
85
|
+
|
86
|
+
def to_proto(self):
|
87
|
+
return ConceptProto(name=self.name, value=self.value)
|
88
|
+
|
89
|
+
@classmethod
|
90
|
+
def from_proto(cls, proto: ConceptProto) -> "Concept":
|
91
|
+
return cls(proto.name, proto.value)
|
92
|
+
|
93
|
+
|
94
|
+
class Region(MessageData):
|
95
|
+
|
96
|
+
def __init__(self, proto_region: RegionProto):
|
97
|
+
self.proto = proto_region
|
98
|
+
|
99
|
+
@property
|
100
|
+
def box(self) -> List[float]:
|
101
|
+
bbox = self.proto.region_info.bounding_box
|
102
|
+
return [bbox.left_col, bbox.top_row, bbox.right_col, bbox.bottom_row] # x1, y1, x2, y2
|
103
|
+
|
104
|
+
@box.setter
|
105
|
+
def box(self, value: List[float]):
|
106
|
+
bbox = self.proto.region_info.bounding_box
|
107
|
+
bbox.left_col, bbox.top_row, bbox.right_col, bbox.bottom_row = value
|
108
|
+
|
109
|
+
@property
|
110
|
+
def concepts(self) -> List[Concept]:
|
111
|
+
return [Concept.from_proto(proto) for proto in self.proto.data.concepts]
|
112
|
+
|
113
|
+
@concepts.setter
|
114
|
+
def concepts(self, value: List[Concept]):
|
115
|
+
self.proto.data.concepts.extend([concept.to_proto() for concept in value])
|
116
|
+
|
117
|
+
def __repr__(self) -> str:
|
118
|
+
return f"Region(box={self.box}, concepts={self.concepts})"
|
119
|
+
|
120
|
+
def to_proto(self) -> RegionProto:
|
121
|
+
return self.proto
|
122
|
+
|
123
|
+
@classmethod
|
124
|
+
def from_proto(cls, proto: RegionProto) -> "Region":
|
125
|
+
return cls(proto)
|
126
|
+
|
127
|
+
|
128
|
+
class Image(MessageData):
|
129
|
+
|
130
|
+
def __init__(self, proto_image: ImageProto = None, url: str = None, bytes: bytes = None):
|
131
|
+
if proto_image is None:
|
132
|
+
proto_image = ImageProto()
|
133
|
+
self.proto = proto_image
|
134
|
+
# use setters for init vals
|
135
|
+
if url:
|
136
|
+
self.url = url
|
137
|
+
if bytes:
|
138
|
+
self.bytes = bytes
|
139
|
+
|
140
|
+
@property
|
141
|
+
def url(self) -> str:
|
142
|
+
return self.proto.url
|
143
|
+
|
144
|
+
@url.setter
|
145
|
+
def url(self, value: str):
|
146
|
+
self.proto.url = value
|
147
|
+
|
148
|
+
@property
|
149
|
+
def bytes(self) -> bytes:
|
150
|
+
return self.proto.base64
|
151
|
+
|
152
|
+
@bytes.setter
|
153
|
+
def bytes(self, value: bytes):
|
154
|
+
self.proto.base64 = value
|
155
|
+
|
156
|
+
def __repr__(self) -> str:
|
157
|
+
attrs = []
|
158
|
+
if self.url:
|
159
|
+
attrs.append(f"url={self.url!r}")
|
160
|
+
if self.bytes:
|
161
|
+
attrs.append(f"bytes=<{len(self.bytes)} bytes>")
|
162
|
+
return f"Image({', '.join(attrs)})"
|
163
|
+
|
164
|
+
@classmethod
|
165
|
+
def from_url(cls, url: str) -> "Image":
|
166
|
+
proto_image = ImageProto(url=url)
|
167
|
+
return cls(proto_image)
|
168
|
+
|
169
|
+
@classmethod
|
170
|
+
def from_pil(cls, pil_image: PILImage.Image) -> "Image":
|
171
|
+
with io.BytesIO() as output:
|
172
|
+
pil_image.save(output, format="PNG")
|
173
|
+
image_bytes = output.getvalue()
|
174
|
+
proto_image = ImageProto(base64=image_bytes)
|
175
|
+
return cls(proto_image)
|
176
|
+
|
177
|
+
def to_pil(self) -> PILImage.Image:
|
178
|
+
if not self.proto.base64:
|
179
|
+
raise ValueError("Image has no bytes")
|
180
|
+
return PILImage.open(io.BytesIO(self.proto.base64))
|
181
|
+
|
182
|
+
def to_numpy(self) -> np.ndarray:
|
183
|
+
return np.asarray(self.to_pil())
|
184
|
+
|
185
|
+
def to_proto(self) -> ImageProto:
|
186
|
+
return self.proto
|
187
|
+
|
188
|
+
@classmethod
|
189
|
+
def from_proto(cls, proto: ImageProto) -> "Image":
|
190
|
+
return cls(proto)
|
191
|
+
|
192
|
+
def cast(self, python_type):
|
193
|
+
if python_type == Image:
|
194
|
+
return self
|
195
|
+
if python_type in (PILImage.Image, PILImage):
|
196
|
+
return self.to_pil()
|
197
|
+
if python_type == np.ndarray or get_origin(python_type) == np.ndarray:
|
198
|
+
return self.to_numpy()
|
199
|
+
raise TypeError(f'Incompatible type for Image: {python_type}')
|
200
|
+
|
201
|
+
|
202
|
+
class Audio(MessageData):
|
203
|
+
|
204
|
+
def __init__(self, proto_audio: AudioProto):
|
205
|
+
self.proto = proto_audio
|
206
|
+
|
207
|
+
@property
|
208
|
+
def url(self) -> str:
|
209
|
+
return self.proto.url
|
210
|
+
|
211
|
+
@url.setter
|
212
|
+
def url(self, value: str):
|
213
|
+
self.proto.url = value
|
214
|
+
|
215
|
+
@property
|
216
|
+
def bytes(self) -> bytes:
|
217
|
+
return self.proto.base64
|
218
|
+
|
219
|
+
@bytes.setter
|
220
|
+
def bytes(self, value: bytes):
|
221
|
+
self.proto.base64 = value
|
222
|
+
|
223
|
+
@classmethod
|
224
|
+
def from_url(cls, url: str) -> "Audio":
|
225
|
+
proto_audio = AudioProto(url=url)
|
226
|
+
return cls(proto_audio)
|
227
|
+
|
228
|
+
def __repr__(self) -> str:
|
229
|
+
attrs = []
|
230
|
+
if self.url:
|
231
|
+
attrs.append(f"url={self.url!r}")
|
232
|
+
if self.bytes:
|
233
|
+
attrs.append(f"bytes=<{len(self.bytes)} bytes>")
|
234
|
+
return f"Audio({', '.join(attrs)})"
|
235
|
+
|
236
|
+
def to_proto(self) -> AudioProto:
|
237
|
+
return self.proto
|
238
|
+
|
239
|
+
@classmethod
|
240
|
+
def from_proto(cls, proto: AudioProto) -> "Audio":
|
241
|
+
return cls(proto)
|
242
|
+
|
243
|
+
|
244
|
+
class Frame(MessageData):
|
245
|
+
|
246
|
+
def __init__(self, proto_frame: FrameProto):
|
247
|
+
self.proto = proto_frame
|
248
|
+
|
249
|
+
@property
|
250
|
+
def time(self) -> float:
|
251
|
+
# TODO: time is a uint32, so this will overflow at 49.7 days
|
252
|
+
# we should be using double or uint64 in the proto instead
|
253
|
+
return self.proto.frame_info.time / 1000.0
|
254
|
+
|
255
|
+
@time.setter
|
256
|
+
def time(self, value: float):
|
257
|
+
self.proto.frame_info.time = int(value * 1000)
|
258
|
+
|
259
|
+
@property
|
260
|
+
def image(self) -> Image:
|
261
|
+
return Image.from_proto(self.proto.data.image)
|
262
|
+
|
263
|
+
@image.setter
|
264
|
+
def image(self, value: Image):
|
265
|
+
self.proto.data.image.CopyFrom(value.to_proto())
|
266
|
+
|
267
|
+
@property
|
268
|
+
def regions(self) -> List[Region]:
|
269
|
+
return [Region(region) for region in self.proto.data.regions]
|
270
|
+
|
271
|
+
@regions.setter
|
272
|
+
def regions(self, value: List[Region]):
|
273
|
+
self.proto.data.regions.extend([region.proto for region in value])
|
274
|
+
|
275
|
+
def to_proto(self) -> FrameProto:
|
276
|
+
return self.proto
|
277
|
+
|
278
|
+
@classmethod
|
279
|
+
def from_proto(cls, proto: FrameProto) -> "Frame":
|
280
|
+
return cls(proto)
|
281
|
+
|
282
|
+
|
283
|
+
class Video(MessageData):
|
284
|
+
|
285
|
+
def __init__(self, proto_video: VideoProto):
|
286
|
+
self.proto = proto_video
|
287
|
+
|
288
|
+
@property
|
289
|
+
def url(self) -> str:
|
290
|
+
return self.proto.url
|
291
|
+
|
292
|
+
@url.setter
|
293
|
+
def url(self, value: str):
|
294
|
+
self.proto.url = value
|
295
|
+
|
296
|
+
@property
|
297
|
+
def bytes(self) -> bytes:
|
298
|
+
return self.proto.base64
|
299
|
+
|
300
|
+
@bytes.setter
|
301
|
+
def bytes(self, value: bytes):
|
302
|
+
self.proto.base64 = value
|
303
|
+
|
304
|
+
@classmethod
|
305
|
+
def from_url(cls, url: str) -> "Video":
|
306
|
+
proto_video = VideoProto(url=url)
|
307
|
+
return cls(proto_video)
|
308
|
+
|
309
|
+
def __repr__(self) -> str:
|
310
|
+
attrs = []
|
311
|
+
if self.url:
|
312
|
+
attrs.append(f"url={self.url!r}")
|
313
|
+
if self.bytes:
|
314
|
+
attrs.append(f"bytes=<{len(self.bytes)} bytes>")
|
315
|
+
return f"Video({', '.join(attrs)})"
|
316
|
+
|
317
|
+
def to_proto(self) -> VideoProto:
|
318
|
+
return self.proto
|
319
|
+
|
320
|
+
@classmethod
|
321
|
+
def from_proto(cls, proto: VideoProto) -> "Video":
|
322
|
+
return cls(proto)
|
323
|
+
|
324
|
+
|
325
|
+
def cast(value, python_type):
|
326
|
+
list_type = (get_origin(python_type) == list)
|
327
|
+
if isinstance(value, MessageData):
|
328
|
+
return value.cast(python_type)
|
329
|
+
if list_type and isinstance(value, np.ndarray):
|
330
|
+
return value.tolist()
|
331
|
+
if list_type and isinstance(value, list):
|
332
|
+
inner_type = get_args(python_type)[0]
|
333
|
+
return [cast(item, inner_type) for item in value]
|
334
|
+
return value
|