dashscope 1.15.0__py3-none-any.whl → 1.18.0__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.

Potentially problematic release.


This version of dashscope might be problematic. Click here for more details.

Files changed (56) hide show
  1. dashscope/__init__.py +57 -10
  2. dashscope/aigc/code_generation.py +12 -9
  3. dashscope/aigc/conversation.py +3 -0
  4. dashscope/aigc/generation.py +3 -0
  5. dashscope/aigc/image_synthesis.py +26 -6
  6. dashscope/aigc/multimodal_conversation.py +3 -0
  7. dashscope/api_entities/aiohttp_request.py +1 -0
  8. dashscope/api_entities/api_request_factory.py +28 -12
  9. dashscope/api_entities/dashscope_response.py +63 -0
  10. dashscope/api_entities/http_request.py +21 -31
  11. dashscope/api_entities/websocket_request.py +3 -0
  12. dashscope/app/application.py +16 -18
  13. dashscope/assistants/__init__.py +14 -0
  14. dashscope/assistants/assistant_types.py +164 -0
  15. dashscope/assistants/assistants.py +280 -0
  16. dashscope/assistants/files.py +189 -0
  17. dashscope/audio/asr/asr_phrase_manager.py +27 -5
  18. dashscope/audio/asr/recognition.py +10 -2
  19. dashscope/audio/asr/transcription.py +21 -3
  20. dashscope/audio/tts/speech_synthesizer.py +3 -0
  21. dashscope/cli.py +7 -7
  22. dashscope/client/base_api.py +317 -70
  23. dashscope/common/base_type.py +130 -0
  24. dashscope/common/constants.py +1 -0
  25. dashscope/common/error.py +4 -0
  26. dashscope/common/utils.py +159 -27
  27. dashscope/deployment.py +40 -6
  28. dashscope/embeddings/batch_text_embedding.py +24 -7
  29. dashscope/embeddings/multimodal_embedding.py +3 -0
  30. dashscope/embeddings/text_embedding.py +8 -1
  31. dashscope/files.py +107 -0
  32. dashscope/finetune.py +31 -7
  33. dashscope/model.py +9 -2
  34. dashscope/models.py +47 -0
  35. dashscope/nlp/understanding.py +2 -2
  36. dashscope/rerank/__init__.py +0 -0
  37. dashscope/rerank/text_rerank.py +67 -0
  38. dashscope/threads/__init__.py +24 -0
  39. dashscope/threads/messages/__init__.py +0 -0
  40. dashscope/threads/messages/files.py +111 -0
  41. dashscope/threads/messages/messages.py +218 -0
  42. dashscope/threads/runs/__init__.py +0 -0
  43. dashscope/threads/runs/runs.py +483 -0
  44. dashscope/threads/runs/steps.py +110 -0
  45. dashscope/threads/thread_types.py +651 -0
  46. dashscope/threads/threads.py +210 -0
  47. dashscope/tokenizers/tokenization.py +3 -0
  48. dashscope/utils/oss_utils.py +11 -0
  49. dashscope/version.py +1 -1
  50. {dashscope-1.15.0.dist-info → dashscope-1.18.0.dist-info}/METADATA +2 -3
  51. dashscope-1.18.0.dist-info/RECORD +84 -0
  52. dashscope-1.15.0.dist-info/RECORD +0 -66
  53. {dashscope-1.15.0.dist-info → dashscope-1.18.0.dist-info}/LICENSE +0 -0
  54. {dashscope-1.15.0.dist-info → dashscope-1.18.0.dist-info}/WHEEL +0 -0
  55. {dashscope-1.15.0.dist-info → dashscope-1.18.0.dist-info}/entry_points.txt +0 -0
  56. {dashscope-1.15.0.dist-info → dashscope-1.18.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,651 @@
1
+ # adapter from openai sdk
2
+ # yapf: disable
3
+ from dataclasses import dataclass
4
+ from typing import Dict, List, Literal, Optional, Union
5
+
6
+ from dashscope.assistants.assistant_types import (
7
+ Tool, convert_tools_dict_to_objects)
8
+ from dashscope.common.base_type import BaseList, BaseObjectMixin
9
+
10
+ __all__ = [
11
+ 'MessageFile', 'MessageFileList', 'Usage', 'ImageFile',
12
+ 'MessageContentImageFile', 'Text', 'MessageContentText', 'ThreadMessage',
13
+ 'ThreadMessageList', 'Thread', 'Function',
14
+ 'RequiredActionFunctionToolCall', 'RequiredActionSubmitToolOutputs',
15
+ 'RequiredAction', 'LastError', 'Run', 'RunList', 'MessageCreation',
16
+ 'MessageCreationStepDetails', 'CodeInterpreterOutputLogs',
17
+ 'CodeInterpreterOutputImageImage', 'CodeInterpreterOutputImage',
18
+ 'CodeInterpreter', 'CodeToolCall', 'RetrievalToolCall', 'FunctionToolCall',
19
+ 'ToolCallsStepDetails', 'RunStep', 'RunStepList'
20
+ ]
21
+
22
+
23
+ @dataclass(init=False)
24
+ class MessageFile(BaseObjectMixin):
25
+ id: str
26
+ message_id: str
27
+ created_at: int
28
+ object: str
29
+
30
+ def __init__(self, **kwargs):
31
+ super().__init__(**kwargs)
32
+
33
+
34
+ @dataclass(init=False)
35
+ class MessageFileList(BaseList):
36
+ data: List[MessageFile]
37
+
38
+ def __init__(self, **kwargs):
39
+ super().__init__(**kwargs)
40
+
41
+
42
+ @dataclass(init=False)
43
+ class Usage(BaseObjectMixin):
44
+ completion_tokens: int
45
+ """Number of completion tokens used over the course of the run."""
46
+
47
+ prompt_tokens: int
48
+ """Number of prompt tokens used over the course of the run."""
49
+
50
+ total_tokens: int
51
+ """Total number of tokens used (prompt + completion)."""
52
+ def __init__(self, **kwargs):
53
+ super().__init__(**kwargs)
54
+
55
+
56
+ @dataclass(init=False)
57
+ class ImageFile(BaseObjectMixin):
58
+ file_id: str
59
+
60
+ def __init__(self, file_id, **kwargs):
61
+ super().__init__(**kwargs)
62
+
63
+
64
+ @dataclass(init=False)
65
+ class MessageContentImageFile(BaseObjectMixin):
66
+ type: str = 'image_file'
67
+ image_file: ImageFile
68
+
69
+ def __init__(self, **kwargs):
70
+ self.image_file = ImageFile(**kwargs.pop(self.type, {}))
71
+ super().__init__(**kwargs)
72
+
73
+
74
+ TextAnnotation = Union[Dict]
75
+
76
+
77
+ @dataclass(init=False)
78
+ class Text(BaseObjectMixin):
79
+ annotations: List[TextAnnotation]
80
+ value: str
81
+
82
+ def __init__(self, **kwargs):
83
+ annotations = kwargs.pop('annotations', None)
84
+ if annotations:
85
+ self.annotations = []
86
+ for annotation in annotations:
87
+ self.annotations.append(annotation)
88
+ else:
89
+ self.annotations = annotations
90
+ super().__init__(**kwargs)
91
+
92
+
93
+ @dataclass(init=False)
94
+ class MessageContentText(BaseObjectMixin):
95
+ text: Text
96
+ type: str = 'text'
97
+
98
+ def __init__(self, **kwargs):
99
+ input_text = kwargs.pop('text', {})
100
+ if input_text:
101
+ self.text = Text(**input_text)
102
+ super().__init__(**kwargs)
103
+
104
+
105
+ MESSAGE_SUPPORT_CONTENT = {
106
+ 'text': MessageContentText,
107
+ 'image_file': MessageContentImageFile,
108
+ }
109
+
110
+ Content = Union[MessageContentImageFile, MessageContentText]
111
+
112
+
113
+ @dataclass(init=False)
114
+ class ThreadMessageDeltaContent(BaseObjectMixin):
115
+ content: Content
116
+ role: str
117
+
118
+ def __init__(self, **kwargs):
119
+ contents = kwargs.pop('content', None)
120
+ if contents:
121
+ for item in contents:
122
+ if item['type'] == 'text':
123
+ self.content = MessageContentText(**item)
124
+ elif item['type'] == 'image_file':
125
+ self.content = MessageContentImageFile(**item)
126
+ else:
127
+ self.content = item
128
+ else:
129
+ self.content = contents
130
+ super().__init__(**kwargs)
131
+
132
+
133
+ @dataclass(init=False)
134
+ class ThreadMessageDelta(BaseObjectMixin):
135
+ status_code: int
136
+ id: str
137
+ object: str = 'thread.message.delta'
138
+ delta: ThreadMessageDeltaContent
139
+
140
+ def __init__(self, **kwargs):
141
+ content = kwargs.pop('delta', None)
142
+ if content:
143
+ self.delta = ThreadMessageDeltaContent(**content)
144
+ else:
145
+ self.delta = None
146
+ super().__init__(**kwargs)
147
+
148
+
149
+ @dataclass(init=False)
150
+ class ThreadMessage(BaseObjectMixin):
151
+ status_code: int
152
+ id: str
153
+ created_at: int
154
+ thread_id: str
155
+ role: str
156
+ content: List[Content]
157
+ metadata: Optional[object] = None
158
+ object: str = 'thread.message'
159
+ assistant_id: Optional[str] = None
160
+ file_ids: List[str] = None
161
+ run_id: Optional[str] = None
162
+
163
+ def __init__(self, **kwargs):
164
+ input_content = kwargs.pop('content', None)
165
+ if input_content:
166
+ content_list = []
167
+ for content in input_content:
168
+ if 'type' in content:
169
+ content_type = MESSAGE_SUPPORT_CONTENT.get(
170
+ content['type'], None)
171
+ if content_type:
172
+ content_list.append(content_type(**content))
173
+ else:
174
+ content_list.append(content)
175
+ else:
176
+ content_list.append(content)
177
+ self.content = content_list
178
+ else:
179
+ self.content = input_content
180
+
181
+ super().__init__(**kwargs)
182
+
183
+
184
+ @dataclass(init=False)
185
+ class ThreadMessageList(BaseList):
186
+ data: List[ThreadMessage]
187
+
188
+ def __init__(self,
189
+ has_more: bool = None,
190
+ last_id: Optional[str] = None,
191
+ first_id: Optional[str] = None,
192
+ data: List[ThreadMessage] = [],
193
+ **kwargs):
194
+ super().__init__(has_more=has_more,
195
+ last_id=last_id,
196
+ first_id=first_id,
197
+ data=data,
198
+ **kwargs)
199
+
200
+
201
+ @dataclass(init=False)
202
+ class Thread(BaseObjectMixin):
203
+ status_code: int
204
+ id: str
205
+ created_at: int
206
+ metadata: Optional[object] = None
207
+ object: str = 'thread'
208
+
209
+ def __init__(self, **kwargs):
210
+ super().__init__(**kwargs)
211
+
212
+
213
+ @dataclass(init=False)
214
+ class Function(BaseObjectMixin):
215
+ arguments: str
216
+ name: str
217
+ output: Optional[str] = None
218
+
219
+ def __init__(self, **kwargs):
220
+ super().__init__(**kwargs)
221
+
222
+
223
+ @dataclass(init=False)
224
+ class RequiredActionFunctionToolCall(BaseObjectMixin):
225
+ id: str
226
+
227
+ function: Function
228
+
229
+ type: str = 'function'
230
+
231
+ def __init__(self, **kwargs):
232
+ self.function = Function(**kwargs.pop('function', {}))
233
+ super().__init__(**kwargs)
234
+
235
+
236
+ @dataclass(init=False)
237
+ class RequiredActionSubmitToolOutputs(BaseObjectMixin):
238
+ tool_calls: List[RequiredActionFunctionToolCall]
239
+
240
+ def __init__(self, **kwargs):
241
+ tcs = kwargs.pop('tool_calls', [])
242
+ if tcs:
243
+ self.tool_calls = []
244
+ for tc in tcs:
245
+ self.tool_calls.append(RequiredActionFunctionToolCall(**tc))
246
+ else:
247
+ self.tool_calls = tcs
248
+ super().__init__(**kwargs)
249
+
250
+
251
+ @dataclass(init=False)
252
+ class RequiredAction(BaseObjectMixin):
253
+ submit_tool_outputs: RequiredActionSubmitToolOutputs
254
+
255
+ type: Literal['submit_tool_outputs']
256
+
257
+ def __init__(self, **kwargs):
258
+ self.submit_tool_outputs = RequiredActionSubmitToolOutputs(
259
+ **kwargs.pop('submit_tool_outputs', {}))
260
+ super().__init__(**kwargs)
261
+
262
+
263
+ @dataclass(init=False)
264
+ class LastError(BaseObjectMixin):
265
+ code: Literal['server_error', 'rate_limit_exceeded']
266
+ message: str
267
+
268
+ def __init__(self, **kwargs):
269
+ super().__init__(**kwargs)
270
+
271
+
272
+ @dataclass(init=False)
273
+ class Run(BaseObjectMixin):
274
+ status_code: int
275
+ id: str
276
+ assistant_id: str
277
+ cancelled_at: Optional[int] = None
278
+ completed_at: Optional[int] = None
279
+ created_at: int = None
280
+ expires_at: int = None
281
+ failed_at: Optional[int] = None
282
+ file_ids: List[str] = None
283
+
284
+ instructions: str = None
285
+
286
+ metadata: Optional[object] = None
287
+ last_error: Optional[LastError] = None
288
+ model: str = None
289
+
290
+ object: str = 'thread.run'
291
+
292
+ required_action: Optional[RequiredAction] = None
293
+
294
+ started_at: Optional[int] = None
295
+
296
+ status: Literal['queued', 'in_progress', 'requires_action', 'cancelling',
297
+ 'cancelled', 'failed', 'completed', 'expired']
298
+
299
+ thread_id: str
300
+
301
+ tools: List[Tool]
302
+
303
+ usage: Optional[Usage] = None
304
+
305
+ def __init__(self, **kwargs):
306
+ self.tools = convert_tools_dict_to_objects(kwargs.pop('tools', []))
307
+ actions = kwargs.pop('required_action', None)
308
+ if actions:
309
+ self.required_action = RequiredAction(**actions)
310
+ else:
311
+ self.required_action = actions
312
+
313
+ super().__init__(**kwargs)
314
+
315
+
316
+ @dataclass(init=False)
317
+ class RunList(BaseObjectMixin):
318
+ data: List[Run]
319
+
320
+ def __init__(self,
321
+ has_more: bool = None,
322
+ last_id: Optional[str] = None,
323
+ first_id: Optional[str] = None,
324
+ data: List[Run] = [],
325
+ **kwargs):
326
+ super().__init__(has_more=has_more,
327
+ last_id=last_id,
328
+ first_id=first_id,
329
+ data=data,
330
+ **kwargs)
331
+
332
+
333
+ @dataclass(init=False)
334
+ class MessageCreation(BaseObjectMixin):
335
+ message_id: str
336
+ """The ID of the message that was created by this run step."""
337
+ def __init__(self, **kwargs):
338
+ super().__init__(**kwargs)
339
+
340
+
341
+ @dataclass(init=False)
342
+ class MessageCreationStepDetails(BaseObjectMixin):
343
+ message_creation: MessageCreation
344
+
345
+ type: Literal['message_creation']
346
+ """Always `message_creation`."""
347
+ def __init__(self, **kwargs):
348
+ super().__init__(**kwargs)
349
+
350
+
351
+ @dataclass(init=False)
352
+ class CodeInterpreterOutputLogs(BaseObjectMixin):
353
+ logs: str
354
+ """The text output from the Code Interpreter tool call."""
355
+
356
+ type: Literal['logs']
357
+ """Always `logs`."""
358
+ def __init__(self, **kwargs):
359
+ super().__init__(**kwargs)
360
+
361
+
362
+ @dataclass(init=False)
363
+ class CodeInterpreterOutputImageImage(BaseObjectMixin):
364
+ file_id: str
365
+ """
366
+ The [file](https://platform.openai.com/docs/api-reference/files) ID of the
367
+ image.
368
+ """
369
+ def __init__(self, **kwargs):
370
+ super().__init__(**kwargs)
371
+
372
+
373
+ @dataclass(init=False)
374
+ class CodeInterpreterOutputImage(BaseObjectMixin):
375
+ image: CodeInterpreterOutputImageImage
376
+
377
+ type: Literal['image']
378
+ """Always `image`."""
379
+ def __init__(self, **kwargs):
380
+ self.image = CodeInterpreterOutputImageImage(**kwargs.pop('image', {}))
381
+ super().__init__(**kwargs)
382
+
383
+
384
+ CodeInterpreterOutput = Union[CodeInterpreterOutputLogs,
385
+ CodeInterpreterOutputImage]
386
+
387
+
388
+ @dataclass(init=False)
389
+ class CodeInterpreter(BaseObjectMixin):
390
+ input: str
391
+ """The input to the Code Interpreter tool call."""
392
+
393
+ outputs: List[CodeInterpreterOutput]
394
+ """The outputs from the Code Interpreter tool call.
395
+
396
+ Code Interpreter can output one or more items, including text (`logs`) or images
397
+ (`image`). Each of these are represented by a different object type.
398
+ """
399
+ def __init__(self, **kwargs):
400
+ self.outputs = []
401
+ for output in kwargs.pop('outputs', []):
402
+ self.outputs.append(CodeInterpreterOutput(**output))
403
+
404
+ super().__init__(**kwargs)
405
+
406
+
407
+ @dataclass(init=False)
408
+ class CodeToolCall(BaseObjectMixin):
409
+ id: str
410
+ """The ID of the tool call."""
411
+
412
+ code_interpreter: CodeInterpreter
413
+ """The Code Interpreter tool call definition."""
414
+
415
+ type: Literal['code_interpreter']
416
+ """The type of tool call.
417
+
418
+ This is always going to be `code_interpreter` for this type of tool call.
419
+ """
420
+ def __init__(self, **kwargs):
421
+ self.code_interpreter = CodeInterpreter(
422
+ **kwargs.pop('code_interpreter', {}))
423
+ super().__init__(**kwargs)
424
+
425
+
426
+ @dataclass(init=False)
427
+ class RetrievalToolCall(BaseObjectMixin):
428
+ id: str
429
+ """The ID of the tool call object."""
430
+
431
+ retrieval: object
432
+ """For now, this is always going to be an empty object."""
433
+
434
+ type: Literal['quark_search']
435
+ """The type of tool call.
436
+
437
+ This is always going to be `quark_search` for this type of tool call.
438
+ """
439
+ def __init__(self, **kwargs):
440
+ super().__init__(**kwargs)
441
+
442
+
443
+ @dataclass(init=False)
444
+ class FunctionToolCall(BaseObjectMixin):
445
+ id: str
446
+ """The ID of the tool call object."""
447
+
448
+ function: Function
449
+ """The definition of the function that was called."""
450
+
451
+ type: Literal['function']
452
+ """The type of tool call.
453
+
454
+ This is always going to be `function` for this type of tool call.
455
+ """
456
+ def __init__(self, **kwargs):
457
+ self.function = Function(**kwargs.pop('function', {}))
458
+ super().__init__(**kwargs)
459
+
460
+
461
+ ToolCall = Union[CodeToolCall, RetrievalToolCall, FunctionToolCall]
462
+
463
+ TOOL_CALL_TYPES = {
464
+ 'function': FunctionToolCall,
465
+ 'code_interpreter': CodeToolCall,
466
+ 'retrieval': RetrievalToolCall,
467
+ }
468
+
469
+
470
+ def convert_tool_calls_dict_to_object(tool_calls):
471
+ tool_calls_object = []
472
+ for tool_call in tool_calls:
473
+ if 'type' in tool_call:
474
+ tool_call_type = TOOL_CALL_TYPES.get(tool_call['type'], None)
475
+ if tool_call_type:
476
+ tool_calls_object.append(tool_call_type(**tool_call))
477
+ else:
478
+ tool_calls_object.append(tool_call)
479
+ else:
480
+ tool_calls_object.append(tool_call)
481
+ return tool_calls_object
482
+
483
+
484
+ @dataclass(init=False)
485
+ class ToolCallsStepDetails(BaseObjectMixin):
486
+ tool_calls: List[ToolCall]
487
+ """An array of tool calls the run step was involved in.
488
+
489
+ These can be associated with one of three types of tools: `code_interpreter`,
490
+ `retrieval`, or `function`.
491
+ """
492
+
493
+ type: Literal['tool_calls']
494
+ """Always `tool_calls`."""
495
+ def __init__(self, **kwargs):
496
+ self.tool_calls = convert_tool_calls_dict_to_object(
497
+ kwargs.pop('tool_calls', []))
498
+ super().__init__(**kwargs)
499
+
500
+
501
+ StepDetails = Union[MessageCreationStepDetails, ToolCallsStepDetails]
502
+ STEP_TYPES = {
503
+ 'tool_calls': ToolCallsStepDetails,
504
+ 'message_creation': MessageCreationStepDetails,
505
+ }
506
+
507
+
508
+ def convert_step_details_dict_to_objects(step_details):
509
+ if 'type' in step_details:
510
+ tool_type = STEP_TYPES.get(step_details['type'], None)
511
+ if tool_type:
512
+ return tool_type(**step_details)
513
+ return step_details
514
+
515
+
516
+ @dataclass(init=False)
517
+ class RunStepDeltaContent(BaseObjectMixin):
518
+ step_details: StepDetails
519
+
520
+ def __init__(self, **kwargs):
521
+ self.step_details = convert_step_details_dict_to_objects(
522
+ kwargs.pop('step_details', {}))
523
+ super().__init__(**kwargs)
524
+
525
+
526
+ @dataclass(init=False)
527
+ class RunStepDelta(BaseObjectMixin):
528
+ id: str
529
+ object: str = 'thread.run.step.delta'
530
+ delta: RunStepDeltaContent
531
+
532
+ def __init__(self, **kwargs):
533
+ delta = kwargs.pop('delta', None)
534
+ if delta:
535
+ self.delta = RunStepDeltaContent(**delta)
536
+ else:
537
+ self.delta = delta
538
+ super().__init__(**kwargs)
539
+
540
+
541
+ @dataclass(init=False)
542
+ class RunStep(BaseObjectMixin):
543
+ status_code: int = None
544
+ id: str
545
+ """The identifier of the run step, which can be referenced in API endpoints."""
546
+
547
+ assistant_id: str
548
+ """
549
+ The ID of the
550
+ [assistant](https://platform.openai.com/docs/api-reference/assistants)
551
+ associated with the run step.
552
+ """
553
+
554
+ cancelled_at: Optional[int] = None
555
+ """The Unix timestamp (in seconds) for when the run step was cancelled."""
556
+
557
+ completed_at: Optional[int] = None
558
+ """The Unix timestamp (in seconds) for when the run step completed."""
559
+
560
+ created_at: int
561
+ """The Unix timestamp (in seconds) for when the run step was created."""
562
+
563
+ expired_at: Optional[int] = None
564
+ """The Unix timestamp (in seconds) for when the run step expired.
565
+
566
+ A step is considered expired if the parent run is expired.
567
+ """
568
+
569
+ failed_at: Optional[int] = None
570
+ """The Unix timestamp (in seconds) for when the run step failed."""
571
+
572
+ last_error: Optional[LastError] = None
573
+ """The last error associated with this run step.
574
+
575
+ Will be `null` if there are no errors.
576
+ """
577
+
578
+ metadata: Optional[object] = None
579
+ """Set of 16 key-value pairs that can be attached to an object.
580
+
581
+ This can be useful for storing additional information about the object in a
582
+ structured format. Keys can be a maximum of 64 characters long and values can be
583
+ a maxium of 512 characters long.
584
+ """
585
+
586
+ object: Literal['thread.run.step']
587
+ """The object type, which is always `thread.run.step`."""
588
+
589
+ run_id: str
590
+ """
591
+ The ID of the [run](https://platform.openai.com/docs/api-reference/runs) that
592
+ this run step is a part of.
593
+ """
594
+
595
+ status: Literal['in_progress', 'cancelled', 'failed', 'completed',
596
+ 'expired']
597
+ """
598
+ The status of the run step, which can be either `in_progress`, `cancelled`,
599
+ `failed`, `completed`, or `expired`.
600
+ """
601
+
602
+ step_details: StepDetails
603
+ """The details of the run step."""
604
+
605
+ thread_id: str
606
+ """
607
+ The ID of the [thread](https://platform.openai.com/docs/api-reference/threads)
608
+ that was run.
609
+ """
610
+
611
+ type: Literal['message_creation', 'tool_calls']
612
+ """The type of run step, which can be either `message_creation` or `tool_calls`."""
613
+
614
+ usage: Optional[Usage] = None
615
+
616
+ def __init__(self, **kwargs):
617
+ self.step_details = convert_step_details_dict_to_objects(
618
+ kwargs.pop('step_details', {}))
619
+ if 'usage' in kwargs and kwargs['usage'] is not None and kwargs['usage']:
620
+ self.usage = Usage(**kwargs.pop('usage', {}))
621
+ else:
622
+ self.usage = None
623
+ last_error = kwargs.pop('last_error', None)
624
+ if last_error:
625
+ self.last_error = LastError(**last_error)
626
+ else:
627
+ last_error = last_error
628
+ super().__init__(**kwargs)
629
+
630
+
631
+ @dataclass(init=False)
632
+ class RunStepList(BaseList):
633
+ data: List[RunStep]
634
+
635
+ def __init__(self,
636
+ has_more: bool = None,
637
+ last_id: Optional[str] = None,
638
+ first_id: Optional[str] = None,
639
+ data: List[RunStep] = [],
640
+ **kwargs):
641
+ if data:
642
+ steps = []
643
+ for step in data:
644
+ steps.append(RunStep(**step))
645
+ self.data = steps
646
+ else:
647
+ self.data = []
648
+ super().__init__(has_more=has_more,
649
+ last_id=last_id,
650
+ first_id=first_id,
651
+ **kwargs)