synapse-sdk 1.0.0b24__py3-none-any.whl → 2025.9.3__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 synapse-sdk might be problematic. Click here for more details.

Files changed (83) hide show
  1. synapse_sdk/clients/agent/ray.py +50 -0
  2. synapse_sdk/devtools/docs/docs/api/clients/annotation-mixin.md +378 -0
  3. synapse_sdk/devtools/docs/docs/api/clients/backend.md +368 -1
  4. synapse_sdk/devtools/docs/docs/api/clients/core-mixin.md +477 -0
  5. synapse_sdk/devtools/docs/docs/api/clients/data-collection-mixin.md +422 -0
  6. synapse_sdk/devtools/docs/docs/api/clients/hitl-mixin.md +554 -0
  7. synapse_sdk/devtools/docs/docs/api/clients/index.md +391 -0
  8. synapse_sdk/devtools/docs/docs/api/clients/integration-mixin.md +571 -0
  9. synapse_sdk/devtools/docs/docs/api/clients/ml-mixin.md +578 -0
  10. synapse_sdk/devtools/docs/docs/api/clients/ray.md +23 -2
  11. synapse_sdk/devtools/docs/docs/plugins/developing-upload-template.md +1463 -0
  12. synapse_sdk/devtools/docs/docs/plugins/export-plugins.md +161 -34
  13. synapse_sdk/devtools/docs/docs/plugins/upload-plugins.md +1497 -213
  14. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/annotation-mixin.md +289 -0
  15. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/backend.md +378 -11
  16. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/core-mixin.md +417 -0
  17. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/data-collection-mixin.md +356 -0
  18. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/hitl-mixin.md +192 -0
  19. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/index.md +391 -0
  20. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/integration-mixin.md +479 -0
  21. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ml-mixin.md +284 -0
  22. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ray.md +23 -2
  23. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/developing-upload-template.md +1463 -0
  24. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/export-plugins.md +161 -34
  25. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/upload-plugins.md +1752 -572
  26. synapse_sdk/devtools/docs/sidebars.ts +7 -0
  27. synapse_sdk/plugins/README.md +1 -2
  28. synapse_sdk/plugins/categories/base.py +23 -0
  29. synapse_sdk/plugins/categories/export/actions/__init__.py +3 -0
  30. synapse_sdk/plugins/categories/export/actions/export/__init__.py +28 -0
  31. synapse_sdk/plugins/categories/export/actions/export/action.py +160 -0
  32. synapse_sdk/plugins/categories/export/actions/export/enums.py +113 -0
  33. synapse_sdk/plugins/categories/export/actions/export/exceptions.py +53 -0
  34. synapse_sdk/plugins/categories/export/actions/export/models.py +74 -0
  35. synapse_sdk/plugins/categories/export/actions/export/run.py +195 -0
  36. synapse_sdk/plugins/categories/export/actions/export/utils.py +187 -0
  37. synapse_sdk/plugins/categories/export/templates/plugin/__init__.py +1 -1
  38. synapse_sdk/plugins/categories/upload/actions/upload/__init__.py +1 -2
  39. synapse_sdk/plugins/categories/upload/actions/upload/action.py +154 -531
  40. synapse_sdk/plugins/categories/upload/actions/upload/context.py +185 -0
  41. synapse_sdk/plugins/categories/upload/actions/upload/factory.py +143 -0
  42. synapse_sdk/plugins/categories/upload/actions/upload/models.py +66 -29
  43. synapse_sdk/plugins/categories/upload/actions/upload/orchestrator.py +182 -0
  44. synapse_sdk/plugins/categories/upload/actions/upload/registry.py +113 -0
  45. synapse_sdk/plugins/categories/upload/actions/upload/steps/__init__.py +1 -0
  46. synapse_sdk/plugins/categories/upload/actions/upload/steps/base.py +106 -0
  47. synapse_sdk/plugins/categories/upload/actions/upload/steps/cleanup.py +62 -0
  48. synapse_sdk/plugins/categories/upload/actions/upload/steps/collection.py +62 -0
  49. synapse_sdk/plugins/categories/upload/actions/upload/steps/generate.py +80 -0
  50. synapse_sdk/plugins/categories/upload/actions/upload/steps/initialize.py +66 -0
  51. synapse_sdk/plugins/categories/upload/actions/upload/steps/metadata.py +101 -0
  52. synapse_sdk/plugins/categories/upload/actions/upload/steps/organize.py +89 -0
  53. synapse_sdk/plugins/categories/upload/actions/upload/steps/upload.py +96 -0
  54. synapse_sdk/plugins/categories/upload/actions/upload/steps/validate.py +61 -0
  55. synapse_sdk/plugins/categories/upload/actions/upload/strategies/__init__.py +1 -0
  56. synapse_sdk/plugins/categories/upload/actions/upload/strategies/base.py +86 -0
  57. synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/__init__.py +1 -0
  58. synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/batch.py +39 -0
  59. synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/single.py +34 -0
  60. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/__init__.py +1 -0
  61. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/flat.py +233 -0
  62. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/recursive.py +238 -0
  63. synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/__init__.py +1 -0
  64. synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/excel.py +174 -0
  65. synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/none.py +16 -0
  66. synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/__init__.py +1 -0
  67. synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/async_upload.py +109 -0
  68. synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/sync.py +43 -0
  69. synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/__init__.py +1 -0
  70. synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/default.py +45 -0
  71. synapse_sdk/plugins/categories/upload/actions/upload/utils.py +194 -83
  72. synapse_sdk/plugins/categories/upload/templates/config.yaml +4 -0
  73. synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py +269 -0
  74. synapse_sdk/plugins/categories/upload/templates/plugin/upload.py +71 -27
  75. synapse_sdk/plugins/models.py +5 -0
  76. {synapse_sdk-1.0.0b24.dist-info → synapse_sdk-2025.9.3.dist-info}/METADATA +3 -2
  77. {synapse_sdk-1.0.0b24.dist-info → synapse_sdk-2025.9.3.dist-info}/RECORD +81 -30
  78. synapse_sdk/plugins/categories/export/actions/export.py +0 -385
  79. synapse_sdk/plugins/categories/export/enums.py +0 -7
  80. {synapse_sdk-1.0.0b24.dist-info → synapse_sdk-2025.9.3.dist-info}/WHEEL +0 -0
  81. {synapse_sdk-1.0.0b24.dist-info → synapse_sdk-2025.9.3.dist-info}/entry_points.txt +0 -0
  82. {synapse_sdk-1.0.0b24.dist-info → synapse_sdk-2025.9.3.dist-info}/licenses/LICENSE +0 -0
  83. {synapse_sdk-1.0.0b24.dist-info → synapse_sdk-2025.9.3.dist-info}/top_level.txt +0 -0
@@ -1,385 +0,0 @@
1
- import json
2
- from abc import ABC, abstractmethod
3
- from datetime import datetime
4
- from itertools import tee
5
- from typing import Annotated, Any, Literal
6
-
7
- from pydantic import AfterValidator, BaseModel, field_validator
8
- from pydantic_core import PydanticCustomError
9
-
10
- from synapse_sdk.clients.exceptions import ClientError
11
- from synapse_sdk.i18n import gettext as _
12
- from synapse_sdk.plugins.categories.base import Action
13
- from synapse_sdk.plugins.categories.decorators import register_action
14
- from synapse_sdk.plugins.categories.export.enums import ExportStatus
15
- from synapse_sdk.plugins.enums import PluginCategory, RunMethod
16
- from synapse_sdk.plugins.models import Run
17
- from synapse_sdk.shared.enums import Context
18
- from synapse_sdk.utils.pydantic.validators import non_blank
19
- from synapse_sdk.utils.storage import get_pathlib
20
-
21
-
22
- class ExportRun(Run):
23
- class ExportEventLog(BaseModel):
24
- """Export event log model."""
25
-
26
- target_id: int
27
- info: str | None = None
28
- status: Context
29
- created: str
30
-
31
- class DataFileLog(BaseModel):
32
- """Data file log model."""
33
-
34
- target_id: int
35
- data_file_info: str | None
36
- status: ExportStatus
37
- error: str | None = None
38
- created: str
39
-
40
- class MetricsRecord(BaseModel):
41
- """Metrics record model."""
42
-
43
- stand_by: int
44
- failed: int
45
- success: int
46
-
47
- LOG_MESSAGES = {
48
- 'NULL_DATA_DETECTED': {
49
- 'message': 'Data is null for export item',
50
- 'level': Context.WARNING,
51
- },
52
- }
53
-
54
- def log_file(
55
- self, log_type: str, target_id: int, data_file_info: dict, status: ExportStatus, error: str | None = None
56
- ):
57
- """Log export file information.
58
-
59
- Args:
60
- log_type (str): The type of log ('export_data_file' or 'export_original_file').
61
- target_id (int): The ID of the data file.
62
- data_file_info (dict): The JSON info of the data file.
63
- status (ExportStatus): The status of the data file.
64
- error (str | None): The error message, if any.
65
- """
66
- now = datetime.now().isoformat()
67
- self.log(
68
- log_type,
69
- self.DataFileLog(
70
- target_id=target_id,
71
- data_file_info=json.dumps(data_file_info),
72
- status=status.value,
73
- error=error,
74
- created=now,
75
- ).model_dump(),
76
- )
77
-
78
- def log_export_event(self, code: str, target_id: int, *args, level: Context | None = None):
79
- """Log export event using predefined code.
80
-
81
- Args:
82
- code (str): The log message code.
83
- target_id (int): The ID of the export target.
84
- *args: Arguments to format the message.
85
- level (Context | None): Optional context level override.
86
- """
87
- if code not in self.LOG_MESSAGES:
88
- now = datetime.now().isoformat()
89
- self.log(
90
- 'export_event',
91
- self.ExportEventLog(
92
- target_id=target_id, info=f'Unknown log code: {code}', status=Context.DANGER, created=now
93
- ).model_dump(),
94
- )
95
- return
96
-
97
- log_config = self.LOG_MESSAGES[code]
98
- message = log_config['message'].format(*args) if args else log_config['message']
99
- log_level = level or log_config['level'] or Context.INFO
100
-
101
- now = datetime.now().isoformat()
102
- self.log(
103
- 'export_event',
104
- self.ExportEventLog(info=message, status=log_level, target_id=target_id, created=now).model_dump(),
105
- )
106
-
107
- def log_metrics(self, record: MetricsRecord, category: str):
108
- """Log export metrics.
109
-
110
- Args:
111
- record (MetricsRecord): The metrics record to log.
112
- category (str): The category of the metrics.
113
- """
114
- record = self.MetricsRecord.model_validate(record)
115
- self.set_metrics(value=record.model_dump(), category=category)
116
-
117
- def export_log_json_file(
118
- self,
119
- target_id: int,
120
- data_file_info: dict,
121
- status: ExportStatus = ExportStatus.STAND_BY,
122
- error: str | None = None,
123
- ):
124
- """Log export json data file."""
125
- self.log_file('export_data_file', target_id, data_file_info, status, error)
126
-
127
- def export_log_original_file(
128
- self,
129
- target_id: int,
130
- data_file_info: dict,
131
- status: ExportStatus = ExportStatus.STAND_BY,
132
- error: str | None = None,
133
- ):
134
- """Log export origin data file."""
135
- self.log_file('export_original_file', target_id, data_file_info, status, error)
136
-
137
-
138
- class ExportTargetHandler(ABC):
139
- """
140
- Abstract base class for handling export targets.
141
-
142
- This class defines the blueprint for export target handlers, requiring the implementation
143
- of methods to validate filters, retrieve results, and process collections of results.
144
- """
145
-
146
- @abstractmethod
147
- def validate_filter(self, value: dict, client: Any):
148
- """
149
- Validate filter query params to request original data from api.
150
-
151
- Args:
152
- value (dict): The filter criteria to validate.
153
- client (Any): The client used to validate the filter.
154
-
155
- Raises:
156
- PydanticCustomError: If the filter criteria are invalid.
157
-
158
- Returns:
159
- dict: The validated filter criteria.
160
- """
161
- pass
162
-
163
- @abstractmethod
164
- def get_results(self, client: Any, filters: dict):
165
- """
166
- Retrieve original data from target sources.
167
-
168
- Args:
169
- client (Any): The client used to retrieve the results.
170
- filters (dict): The filter criteria to apply.
171
-
172
- Returns:
173
- tuple: A tuple containing the results and the total count of results.
174
- """
175
- pass
176
-
177
- @abstractmethod
178
- def get_export_item(self, results):
179
- """
180
- Providing elements to build export data.
181
-
182
- Args:
183
- results (list): The results to process.
184
-
185
- Yields:
186
- generator: A generator that yields processed data items.
187
- """
188
- pass
189
-
190
-
191
- class AssignmentExportTargetHandler(ExportTargetHandler):
192
- def validate_filter(self, value: dict, client: Any):
193
- if 'project' not in value:
194
- raise PydanticCustomError('missing_field', _('Project is required for Assignment.'))
195
- try:
196
- client.list_assignments(params=value)
197
- except ClientError:
198
- raise PydanticCustomError('client_error', _('Unable to get Assignment.'))
199
- return value
200
-
201
- def get_results(self, client: Any, filters: dict):
202
- return client.list_assignments(params=filters, list_all=True)
203
-
204
- def get_export_item(self, results):
205
- for result in results:
206
- yield {
207
- 'data': result['data'],
208
- 'files': result['file'],
209
- 'id': result['id'],
210
- }
211
-
212
-
213
- class GroundTruthExportTargetHandler(ExportTargetHandler):
214
- def validate_filter(self, value: dict, client: Any):
215
- if 'ground_truth_dataset_version' not in value:
216
- raise PydanticCustomError('missing_field', _('Ground Truth dataset version is required.'))
217
- try:
218
- client.get_ground_truth_version(value['ground_truth_dataset_version'])
219
- except ClientError:
220
- raise PydanticCustomError('client_error', _('Unable to get Ground Truth dataset version.'))
221
- return value
222
-
223
- def get_results(self, client: Any, filters: dict):
224
- filters['ground_truth_dataset_versions'] = filters.pop('ground_truth_dataset_version')
225
- return client.list_ground_truth_events(params=filters, list_all=True)
226
-
227
- def get_export_item(self, results):
228
- for result in results:
229
- files_key = next(iter(result['data_unit']['files']))
230
- yield {
231
- 'data': result['data'],
232
- 'files': result['data_unit']['files'][files_key],
233
- 'id': result['id'],
234
- }
235
-
236
-
237
- class TaskExportTargetHandler(ExportTargetHandler):
238
- def validate_filter(self, value: dict, client: Any):
239
- if 'project' not in value:
240
- raise PydanticCustomError('missing_field', _('Project is required for Task.'))
241
- try:
242
- client.list_tasks(params=value)
243
- except ClientError:
244
- raise PydanticCustomError('client_error', _('Unable to get Task.'))
245
- return value
246
-
247
- def get_results(self, client: Any, filters: dict):
248
- filters['expand'] = ['data_unit', 'assignment', 'workshop']
249
- return client.list_tasks(params=filters, list_all=True)
250
-
251
- def get_export_item(self, results):
252
- for result in results:
253
- files_key = next(iter(result['data_unit']['files']))
254
- yield {
255
- 'data': result['data'],
256
- 'files': result['data_unit']['files'][files_key],
257
- 'id': result['id'],
258
- }
259
-
260
-
261
- class TargetHandlerFactory:
262
- @staticmethod
263
- def get_handler(target: str) -> ExportTargetHandler:
264
- if target == 'assignment':
265
- return AssignmentExportTargetHandler()
266
- elif target == 'ground_truth':
267
- return GroundTruthExportTargetHandler()
268
- elif target == 'task':
269
- return TaskExportTargetHandler()
270
- else:
271
- raise ValueError(f'Unknown target: {target}')
272
-
273
-
274
- class ExportParams(BaseModel):
275
- """
276
- Parameters for the export action.
277
-
278
- Attributes:
279
- name (str): The name of the action.
280
- description (str | None): The description of the action.
281
- storage (int): The storage ID to save the exported data.
282
- save_original_file (bool): Whether to save the original file.
283
- path (str): The path to save the exported data.
284
- target (str): The target source to export data from. (ex. ground_truth, assignment, task)
285
- filter (dict): The filter criteria to apply.
286
- extra_params (dict | None): Additional parameters for export customization.
287
- Example: {"include_metadata": True, "compression": "gzip"}
288
- """
289
-
290
- name: Annotated[str, AfterValidator(non_blank)]
291
- description: str | None = None
292
- storage: int
293
- save_original_file: bool = True
294
- path: str
295
- target: Literal['assignment', 'ground_truth', 'task']
296
- filter: dict
297
- extra_params: dict | None = None
298
-
299
- @field_validator('storage')
300
- @staticmethod
301
- def check_storage_exists(value, info):
302
- action = info.context['action']
303
- client = action.client
304
- try:
305
- client.get_storage(value)
306
- except ClientError:
307
- raise PydanticCustomError('client_error', _('Unable to get storage from Synapse backend.'))
308
- return value
309
-
310
- @field_validator('filter')
311
- @staticmethod
312
- def check_filter_by_target(value, info):
313
- action = info.context['action']
314
- client = action.client
315
- target = action.params['target']
316
- handler = TargetHandlerFactory.get_handler(target)
317
- return handler.validate_filter(value, client)
318
-
319
-
320
- @register_action
321
- class ExportAction(Action):
322
- name = 'export'
323
- category = PluginCategory.EXPORT
324
- method = RunMethod.JOB
325
- params_model = ExportParams
326
- run_class = ExportRun
327
- progress_categories = {
328
- 'dataset_conversion': {
329
- 'proportion': 100,
330
- }
331
- }
332
- metrics_categories = {
333
- 'data_file': {
334
- 'stand_by': 0,
335
- 'failed': 0,
336
- 'success': 0,
337
- },
338
- 'original_file': {
339
- 'stand_by': 0,
340
- 'failed': 0,
341
- 'success': 0,
342
- },
343
- }
344
-
345
- def get_filtered_results(self, filters, handler):
346
- """Get filtered target results."""
347
- try:
348
- result_list = handler.get_results(self.client, filters)
349
- results = result_list[0]
350
- count = result_list[1]
351
- except ClientError:
352
- raise PydanticCustomError('client_error', _('Unable to get Ground Truth dataset.'))
353
- return results, count
354
-
355
- def start(self):
356
- filters = {'expand': 'data', **self.params['filter']}
357
- target = self.params['target']
358
- handler = TargetHandlerFactory.get_handler(target)
359
-
360
- self.params['results'], self.params['count'] = self.get_filtered_results(filters, handler)
361
-
362
- # For the 'ground_truth' target, retrieve project information from the first result and add configuration
363
- if target == 'ground_truth':
364
- try:
365
- # Split generator into two using tee()
366
- peek_iter, main_iter = tee(self.params['results'])
367
- first_result = next(peek_iter) # Peek first value only
368
- project_pk = first_result['project']
369
- project_info = self.client.get_project(project_pk)
370
- self.params['project_id'] = project_pk
371
- self.params['configuration'] = project_info.get('configuration', {})
372
- self.params['results'] = main_iter # Keep original generator intact
373
- except (StopIteration, KeyError):
374
- self.params['configuration'] = {}
375
- # For the 'assignment' and 'task' targets, retrieve the project from the filter as before
376
- elif target in ['assignment', 'task'] and 'project' in self.params['filter']:
377
- project_pk = self.params['filter']['project']
378
- project_info = self.client.get_project(project_pk)
379
- self.params['configuration'] = project_info.get('configuration', {})
380
-
381
- export_items = handler.get_export_item(self.params['results'])
382
- storage = self.client.get_storage(self.params['storage'])
383
- pathlib_cwd = get_pathlib(storage, self.params['path'])
384
- exporter = self.entrypoint(self.run, export_items, pathlib_cwd, **self.params)
385
- return exporter.export()
@@ -1,7 +0,0 @@
1
- from enum import Enum
2
-
3
-
4
- class ExportStatus(str, Enum):
5
- SUCCESS = 'success'
6
- FAILED = 'failed'
7
- STAND_BY = 'stand_by'