synapse-sdk 1.0.0a30__py3-none-any.whl → 1.0.0a32__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.
- synapse_sdk/clients/backend/dataset.py +57 -5
- synapse_sdk/clients/base.py +20 -22
- synapse_sdk/plugins/categories/base.py +40 -0
- synapse_sdk/plugins/categories/export/actions/export.py +2 -5
- synapse_sdk/plugins/categories/export/templates/plugin/export.py +39 -29
- synapse_sdk/plugins/categories/neural_net/actions/train.py +1 -1
- synapse_sdk/plugins/categories/upload/actions/upload.py +292 -0
- synapse_sdk/plugins/categories/upload/templates/config.yaml +6 -0
- synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/upload/templates/plugin/upload.py +44 -0
- synapse_sdk/plugins/enums.py +3 -1
- synapse_sdk/plugins/models.py +16 -0
- synapse_sdk/utils/storage/__init__.py +11 -1
- {synapse_sdk-1.0.0a30.dist-info → synapse_sdk-1.0.0a32.dist-info}/METADATA +3 -2
- {synapse_sdk-1.0.0a30.dist-info → synapse_sdk-1.0.0a32.dist-info}/RECORD +21 -19
- {synapse_sdk-1.0.0a30.dist-info → synapse_sdk-1.0.0a32.dist-info}/WHEEL +1 -1
- synapse_sdk/plugins/categories/export/actions/utils.py +0 -5
- synapse_sdk/plugins/categories/import/actions/import.py +0 -10
- /synapse_sdk/plugins/categories/{import → upload}/__init__.py +0 -0
- /synapse_sdk/plugins/categories/{import → upload}/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a30.dist-info → synapse_sdk-1.0.0a32.dist-info}/entry_points.txt +0 -0
- {synapse_sdk-1.0.0a30.dist-info → synapse_sdk-1.0.0a32.dist-info/licenses}/LICENSE +0 -0
- {synapse_sdk-1.0.0a30.dist-info → synapse_sdk-1.0.0a32.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
from multiprocessing import Pool
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Dict, Optional
|
|
2
4
|
|
|
3
5
|
from tqdm import tqdm
|
|
4
6
|
|
|
@@ -11,21 +13,59 @@ class DatasetClientMixin(BaseClient):
|
|
|
11
13
|
path = 'datasets/'
|
|
12
14
|
return self._list(path)
|
|
13
15
|
|
|
14
|
-
def
|
|
16
|
+
def get_dataset(self, dataset_id):
|
|
17
|
+
"""Get dataset from synapse-backend.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
dataset_id: The dataset id to get.
|
|
21
|
+
"""
|
|
22
|
+
path = f'datasets/{dataset_id}/?expand=file_specifications'
|
|
23
|
+
return self._get(path)
|
|
24
|
+
|
|
25
|
+
def create_data_file(self, file_path: Path):
|
|
26
|
+
"""Create data file to synapse-backend.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
file_path: The file pathlib object to upload.
|
|
30
|
+
"""
|
|
15
31
|
path = 'data_files/'
|
|
16
32
|
return self._post(path, files={'file': file_path})
|
|
17
33
|
|
|
18
34
|
def create_data_units(self, data):
|
|
35
|
+
"""Create data units to synapse-backend.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
data: The data bindings to upload from create_data_file interface.
|
|
39
|
+
"""
|
|
19
40
|
path = 'data_units/'
|
|
20
41
|
return self._post(path, data=data)
|
|
21
42
|
|
|
22
|
-
def
|
|
43
|
+
def upload_dataset(
|
|
44
|
+
self,
|
|
45
|
+
dataset_id: int,
|
|
46
|
+
dataset: Dict,
|
|
47
|
+
project_id: Optional[int] = None,
|
|
48
|
+
batch_size: int = 1000,
|
|
49
|
+
process_pool: int = 10,
|
|
50
|
+
):
|
|
51
|
+
"""Upload dataset to synapse-backend.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
dataset_id: The dataset id to upload the data to.
|
|
55
|
+
dataset: The dataset to upload.
|
|
56
|
+
* structure:
|
|
57
|
+
- files: The files to upload. (key: file name, value: file pathlib object)
|
|
58
|
+
- meta: The meta data to upload.
|
|
59
|
+
project_id: The project id to upload the data to.
|
|
60
|
+
batch_size: The batch size to upload the data.
|
|
61
|
+
process_pool: The process pool to upload the data.
|
|
62
|
+
"""
|
|
23
63
|
# TODO validate dataset with schema
|
|
24
64
|
|
|
25
65
|
params = [(data, dataset_id) for data in dataset]
|
|
26
66
|
|
|
27
67
|
with Pool(processes=process_pool) as pool:
|
|
28
|
-
dataset = pool.starmap(self.
|
|
68
|
+
dataset = pool.starmap(self.upload_data_file, tqdm(params))
|
|
29
69
|
|
|
30
70
|
batches = get_batched_list(dataset, batch_size)
|
|
31
71
|
|
|
@@ -36,13 +76,25 @@ class DatasetClientMixin(BaseClient):
|
|
|
36
76
|
tasks_data = []
|
|
37
77
|
for data, data_unit in zip(batch, data_units):
|
|
38
78
|
task_data = {'project': project_id, 'data_unit': data_unit['id']}
|
|
39
|
-
# TODO:
|
|
79
|
+
# TODO: Additional logic needed here if task data storage is required during import.
|
|
40
80
|
|
|
41
81
|
tasks_data.append(task_data)
|
|
42
82
|
|
|
43
83
|
self.create_tasks(tasks_data)
|
|
44
84
|
|
|
45
|
-
def
|
|
85
|
+
def upload_data_file(self, data: Dict, dataset_id: int) -> Dict:
|
|
86
|
+
"""Upload files to synapse-backend.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
data: The data to upload.
|
|
90
|
+
* structure:
|
|
91
|
+
- files: The files to upload. (key: file name, value: file pathlib object)
|
|
92
|
+
- meta: The meta data to upload.
|
|
93
|
+
dataset_id: The dataset id to upload the data to.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Dict: The result of the upload.
|
|
97
|
+
"""
|
|
46
98
|
for name, path in data['files'].items():
|
|
47
99
|
data_file = self.create_data_file(path)
|
|
48
100
|
data['dataset'] = dataset_id
|
synapse_sdk/clients/base.py
CHANGED
|
@@ -40,37 +40,31 @@ class BaseClient:
|
|
|
40
40
|
headers = self._get_headers()
|
|
41
41
|
headers.update(kwargs.pop('headers', {}))
|
|
42
42
|
|
|
43
|
+
# List to store opened files to close after request
|
|
44
|
+
opened_files = []
|
|
45
|
+
|
|
43
46
|
if method in ['post', 'put', 'patch']:
|
|
44
47
|
# If files are included in the request, open them as binary files
|
|
45
48
|
if kwargs.get('files') is not None:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
kwargs['
|
|
58
|
-
opened_files.append(opened_file)
|
|
59
|
-
if 'data' in kwargs:
|
|
60
|
-
for name, value in kwargs['data'].items():
|
|
61
|
-
if isinstance(value, dict):
|
|
62
|
-
kwargs['data'][name] = json.dumps(value)
|
|
63
|
-
finally:
|
|
64
|
-
# Close all opened files
|
|
65
|
-
for opened_file in opened_files:
|
|
66
|
-
opened_file.close()
|
|
67
|
-
|
|
49
|
+
for name, file in kwargs['files'].items():
|
|
50
|
+
# Handle both string and Path object cases
|
|
51
|
+
if isinstance(file, str):
|
|
52
|
+
file = Path(file)
|
|
53
|
+
if isinstance(file, Path):
|
|
54
|
+
opened_file = file.open(mode='rb')
|
|
55
|
+
kwargs['files'][name] = (file.name, opened_file)
|
|
56
|
+
opened_files.append(opened_file)
|
|
57
|
+
if 'data' in kwargs:
|
|
58
|
+
for name, value in kwargs['data'].items():
|
|
59
|
+
if isinstance(value, dict):
|
|
60
|
+
kwargs['data'][name] = json.dumps(value)
|
|
68
61
|
else:
|
|
69
62
|
headers['Content-Type'] = 'application/json'
|
|
70
63
|
if 'data' in kwargs:
|
|
71
64
|
kwargs['data'] = json.dumps(kwargs['data'])
|
|
72
65
|
|
|
73
66
|
try:
|
|
67
|
+
# Send request
|
|
74
68
|
response = getattr(self.requests_session, method)(url, headers=headers, **kwargs)
|
|
75
69
|
if not response.ok:
|
|
76
70
|
raise ClientError(
|
|
@@ -79,6 +73,10 @@ class BaseClient:
|
|
|
79
73
|
except requests.ConnectionError:
|
|
80
74
|
raise ClientError(408, f'{self.name} is not responding')
|
|
81
75
|
|
|
76
|
+
# Close all opened files
|
|
77
|
+
for opened_file in opened_files:
|
|
78
|
+
opened_file.close()
|
|
79
|
+
|
|
82
80
|
return self._post_response(response)
|
|
83
81
|
|
|
84
82
|
def _post_response(self, response):
|
|
@@ -17,6 +17,30 @@ from synapse_sdk.utils.pydantic.errors import pydantic_to_drf_error
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class Action:
|
|
20
|
+
"""Base class for all plugin actions.
|
|
21
|
+
|
|
22
|
+
Attrs:
|
|
23
|
+
name (str): The name of the action.
|
|
24
|
+
category (PluginCategory): The category of the action.
|
|
25
|
+
method (RunMethod): The method to run of the action.
|
|
26
|
+
run_class (Run): The class to run the action.
|
|
27
|
+
params_model (BaseModel): The model to validate the params.
|
|
28
|
+
progress_categories (List[str]): The categories to update the progress.
|
|
29
|
+
params (Dict): The params to run the action.
|
|
30
|
+
plugin_config (Dict): The plugin config.
|
|
31
|
+
plugin_release (PluginRelease): The plugin release.
|
|
32
|
+
config (Dict): The action config.
|
|
33
|
+
requirements (List[str]): The requirements to install.
|
|
34
|
+
job_id (str): The job id.
|
|
35
|
+
direct (bool): The flag to run the action directly.
|
|
36
|
+
debug (bool): The flag to run the action in debug mode.
|
|
37
|
+
envs (Dict): The runtime envs.
|
|
38
|
+
run (Run): The run instance.
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
ActionError: If the action fails.
|
|
42
|
+
"""
|
|
43
|
+
|
|
20
44
|
# class 변수
|
|
21
45
|
name = None
|
|
22
46
|
category = None
|
|
@@ -159,11 +183,19 @@ class Action:
|
|
|
159
183
|
return getattr(self, f'start_by_{self.method.value}')()
|
|
160
184
|
|
|
161
185
|
def start(self):
|
|
186
|
+
"""Start the action.
|
|
187
|
+
|
|
188
|
+
TODO: Specify the return type of start method for overrided methods.
|
|
189
|
+
"""
|
|
162
190
|
if self.method == RunMethod.JOB:
|
|
163
191
|
return self.entrypoint(self.run, **self.params)
|
|
164
192
|
return self.entrypoint(**self.params)
|
|
165
193
|
|
|
166
194
|
def start_by_task(self):
|
|
195
|
+
"""Ray Task based execution.
|
|
196
|
+
|
|
197
|
+
* A task method that simply executes the entrypoint without job management functionality.
|
|
198
|
+
"""
|
|
167
199
|
import ray
|
|
168
200
|
from ray.exceptions import RayTaskError
|
|
169
201
|
|
|
@@ -195,6 +227,10 @@ class Action:
|
|
|
195
227
|
raise ActionError(e.cause)
|
|
196
228
|
|
|
197
229
|
def start_by_job(self):
|
|
230
|
+
"""Ray Job based execution.
|
|
231
|
+
|
|
232
|
+
* Executes the entrypoint with Ray job. Ray job manages the entrypoint execution and stores the results.
|
|
233
|
+
"""
|
|
198
234
|
main_options = []
|
|
199
235
|
options = ['run', '--direct']
|
|
200
236
|
arguments = [self.name, f'{json.dumps(json.dumps(self.params))}']
|
|
@@ -215,6 +251,10 @@ class Action:
|
|
|
215
251
|
)
|
|
216
252
|
|
|
217
253
|
def start_by_restapi(self):
|
|
254
|
+
"""Ray Serve based execution.
|
|
255
|
+
|
|
256
|
+
* This method executes a Fastapi endpoint defined within the Plugin.
|
|
257
|
+
"""
|
|
218
258
|
path = self.params.pop('path', '')
|
|
219
259
|
method = self.params.pop('method')
|
|
220
260
|
|
|
@@ -61,11 +61,8 @@ class ExportAction(Action):
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
def get_filtered_results(self):
|
|
64
|
-
"""Get filtered ground truth."""
|
|
65
|
-
|
|
66
|
-
self.params['filter']['ground_truth_dataset'] = self.client.get_ground_truth_version(
|
|
67
|
-
ground_truth_dataset_version
|
|
68
|
-
)['ground_truth_dataset']
|
|
64
|
+
"""Get filtered ground truth events."""
|
|
65
|
+
self.params['filter']['ground_truth_dataset_versions'] = self.params['ground_truth_dataset_version']
|
|
69
66
|
filters = {'expand': 'data', **self.params['filter']}
|
|
70
67
|
|
|
71
68
|
try:
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from pathlib import Path
|
|
2
3
|
|
|
3
4
|
import requests
|
|
4
5
|
|
|
5
|
-
from synapse_sdk.plugins.categories.export.actions.utils import get_original_file_path
|
|
6
|
-
|
|
7
6
|
|
|
8
7
|
def export(run, input_dataset, path_root, **params):
|
|
9
8
|
"""Executes the export task.
|
|
@@ -14,7 +13,7 @@ def export(run, input_dataset, path_root, **params):
|
|
|
14
13
|
- data (dict): dm_schema_data information.
|
|
15
14
|
- files (dict): File information. Includes file URL, original file path, metadata, etc.
|
|
16
15
|
- id (int): ground_truth ID
|
|
17
|
-
path_root :
|
|
16
|
+
path_root : pathlib object, the path to export
|
|
18
17
|
**params: Additional parameters
|
|
19
18
|
|
|
20
19
|
Returns:
|
|
@@ -24,10 +23,11 @@ def export(run, input_dataset, path_root, **params):
|
|
|
24
23
|
path_root.mkdir(parents=True, exist_ok=True)
|
|
25
24
|
run.log_message('Starting export process.')
|
|
26
25
|
|
|
27
|
-
# results
|
|
28
|
-
|
|
26
|
+
# results contains all information fetched through the list API.
|
|
27
|
+
# example:
|
|
28
|
+
# params.get('results', [])
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
save_original_file_flag = params.get('save_original_file')
|
|
31
31
|
errors_json_file_list = []
|
|
32
32
|
errors_original_file_list = []
|
|
33
33
|
|
|
@@ -39,21 +39,28 @@ def export(run, input_dataset, path_root, **params):
|
|
|
39
39
|
origin_files_output_path = path_root / 'origin_files'
|
|
40
40
|
origin_files_output_path.mkdir(parents=True, exist_ok=True)
|
|
41
41
|
|
|
42
|
-
total =
|
|
43
|
-
|
|
42
|
+
total = params['count']
|
|
43
|
+
# progress init
|
|
44
|
+
run.set_progress(0, total, category='dataset_conversion')
|
|
45
|
+
for no, input_data in enumerate(input_dataset, start=1):
|
|
44
46
|
run.set_progress(no, total, category='dataset_conversion')
|
|
47
|
+
if no == 1:
|
|
48
|
+
run.log_message('Converting dataset.')
|
|
45
49
|
preprocessed_data = before_convert(input_data)
|
|
46
50
|
converted_data = convert_data(preprocessed_data)
|
|
47
51
|
final_data = after_convert(converted_data)
|
|
48
52
|
|
|
49
53
|
# Call if original file extraction is needed
|
|
50
|
-
if
|
|
54
|
+
if save_original_file_flag:
|
|
55
|
+
if no == 1:
|
|
56
|
+
run.log_message('Saving original file.')
|
|
51
57
|
save_original_file(final_data, origin_files_output_path, errors_original_file_list)
|
|
52
58
|
|
|
53
59
|
# Extract data as JSON files
|
|
60
|
+
if no == 1:
|
|
61
|
+
run.log_message('Saving json file.')
|
|
54
62
|
save_as_json(final_data, json_output_path, errors_json_file_list)
|
|
55
63
|
|
|
56
|
-
run.log_message('Saving converted dataset.')
|
|
57
64
|
run.end_log()
|
|
58
65
|
|
|
59
66
|
# Save error list files
|
|
@@ -62,7 +69,7 @@ def export(run, input_dataset, path_root, **params):
|
|
|
62
69
|
with (path_root / 'error_file_list.json').open('w', encoding='utf-8') as f:
|
|
63
70
|
json.dump(export_error_file, f, indent=4, ensure_ascii=False)
|
|
64
71
|
|
|
65
|
-
return {'export_path': path_root}
|
|
72
|
+
return {'export_path': str(path_root)}
|
|
66
73
|
|
|
67
74
|
|
|
68
75
|
def convert_data(data):
|
|
@@ -80,19 +87,29 @@ def after_convert(data):
|
|
|
80
87
|
return data
|
|
81
88
|
|
|
82
89
|
|
|
83
|
-
def
|
|
84
|
-
"""
|
|
90
|
+
def get_original_file_pathlib(files):
|
|
91
|
+
"""Retrieve the original file path from the given file information.
|
|
85
92
|
|
|
86
93
|
Args:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
error_file_list (list): List of error files
|
|
94
|
+
files (dict): A dictionary containing file information, including file URL,
|
|
95
|
+
original file path, metadata, etc.
|
|
90
96
|
|
|
91
97
|
Returns:
|
|
92
|
-
|
|
98
|
+
pathlib.Path: The original file path extracted from the metadata.
|
|
99
|
+
"""
|
|
100
|
+
return Path(next(iter(files.values()))['meta']['path_original'])
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def save_original_file(result, base_path, error_file_list):
|
|
104
|
+
"""Saves the original file.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
result (dict): API response data containing file information.
|
|
108
|
+
base_path (Path): The directory where the file will be saved.
|
|
109
|
+
error_file_list (list): A list to store error files.
|
|
93
110
|
"""
|
|
94
111
|
file_url = next(iter(result['files'].values()))['url']
|
|
95
|
-
file_name =
|
|
112
|
+
file_name = get_original_file_pathlib(result['files']).name
|
|
96
113
|
response = requests.get(file_url)
|
|
97
114
|
try:
|
|
98
115
|
with (base_path / file_name).open('wb') as file:
|
|
@@ -100,27 +117,20 @@ def save_original_file(result, base_path, error_file_list):
|
|
|
100
117
|
except Exception as e:
|
|
101
118
|
error_file_list.append([file_name, str(e)])
|
|
102
119
|
|
|
103
|
-
return base_path
|
|
104
|
-
|
|
105
120
|
|
|
106
121
|
def save_as_json(result, base_path, error_file_list):
|
|
107
122
|
"""Saves the data as a JSON file.
|
|
108
123
|
|
|
109
124
|
Args:
|
|
110
|
-
result (dict):
|
|
111
|
-
base_path (Path):
|
|
112
|
-
error_file_list (list):
|
|
113
|
-
|
|
114
|
-
Returns:
|
|
115
|
-
base_path (str): Save path
|
|
125
|
+
result (dict): API response data containing file information.
|
|
126
|
+
base_path (Path): The directory where the file will be saved.
|
|
127
|
+
error_file_list (list): A list to store error files.
|
|
116
128
|
"""
|
|
117
129
|
# Default save file name: original file name
|
|
118
|
-
file_name =
|
|
130
|
+
file_name = get_original_file_pathlib(result['files']).stem
|
|
119
131
|
json_data = result['data']
|
|
120
132
|
try:
|
|
121
133
|
with (base_path / f'{file_name}.json').open('w', encoding='utf-8') as f:
|
|
122
134
|
json.dump(json_data, f, indent=4, ensure_ascii=False)
|
|
123
135
|
except Exception as e:
|
|
124
136
|
error_file_list.append([f'{file_name}.json', str(e)])
|
|
125
|
-
|
|
126
|
-
return base_path
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Annotated, Dict, List
|
|
3
|
+
|
|
4
|
+
from pydantic import AfterValidator, BaseModel, field_validator
|
|
5
|
+
from pydantic_core import PydanticCustomError
|
|
6
|
+
|
|
7
|
+
from synapse_sdk.clients.exceptions import ClientError
|
|
8
|
+
from synapse_sdk.clients.utils import get_batched_list
|
|
9
|
+
from synapse_sdk.i18n import gettext as _
|
|
10
|
+
from synapse_sdk.plugins.categories.base import Action
|
|
11
|
+
from synapse_sdk.plugins.categories.decorators import register_action
|
|
12
|
+
from synapse_sdk.plugins.enums import PluginCategory, RunMethod
|
|
13
|
+
from synapse_sdk.plugins.models import Run
|
|
14
|
+
from synapse_sdk.shared.enums import Context
|
|
15
|
+
from synapse_sdk.utils.pydantic.validators import non_blank
|
|
16
|
+
from synapse_sdk.utils.storage import get_pathlib
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class UploadRun(Run):
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class UploadParams(BaseModel):
|
|
24
|
+
"""Upload action parameters.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
name (str): The name of the action.
|
|
28
|
+
description (str | None): The description of the action.
|
|
29
|
+
checkpoint (int | None): The checkpoint of the action.
|
|
30
|
+
path (str): The path of the action.
|
|
31
|
+
storage (int): The storage of the action.
|
|
32
|
+
collection (int): The collection of the action.
|
|
33
|
+
project (int | None): The project of the action.
|
|
34
|
+
is_generate_tasks (bool): The flag to generate tasks.
|
|
35
|
+
is_generate_ground_truths (bool): The flag to generate ground truths
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
name: Annotated[str, AfterValidator(non_blank)]
|
|
39
|
+
description: str | None
|
|
40
|
+
path: str
|
|
41
|
+
storage: int
|
|
42
|
+
collection: int
|
|
43
|
+
project: int | None
|
|
44
|
+
is_generate_tasks: bool = False
|
|
45
|
+
is_generate_ground_truths: bool = False
|
|
46
|
+
|
|
47
|
+
@field_validator('storage', mode='before')
|
|
48
|
+
@classmethod
|
|
49
|
+
def check_storage_exists(cls, value: str, info) -> str:
|
|
50
|
+
"""Validate synapse-backend storage exists.
|
|
51
|
+
|
|
52
|
+
TODO: Need to define validation method naming convention.
|
|
53
|
+
TODO: Need to make validation method reusable.
|
|
54
|
+
"""
|
|
55
|
+
action = info.context['action']
|
|
56
|
+
client = action.client
|
|
57
|
+
try:
|
|
58
|
+
client.get_storage(value)
|
|
59
|
+
except ClientError:
|
|
60
|
+
raise PydanticCustomError('client_error', _('Error occurred while checking storage exists.'))
|
|
61
|
+
return value
|
|
62
|
+
|
|
63
|
+
@field_validator('collection', mode='before')
|
|
64
|
+
@classmethod
|
|
65
|
+
def check_collection_exists(cls, value: str, info) -> str:
|
|
66
|
+
"""Validate synapse-backend collection exists."""
|
|
67
|
+
action = info.context['action']
|
|
68
|
+
client = action.client
|
|
69
|
+
try:
|
|
70
|
+
client.get_dataset(value)
|
|
71
|
+
except ClientError:
|
|
72
|
+
raise PydanticCustomError('client_error', _('Error occurred while checking collection exists.'))
|
|
73
|
+
return value
|
|
74
|
+
|
|
75
|
+
@field_validator('project', mode='before')
|
|
76
|
+
@classmethod
|
|
77
|
+
def check_project_exists(cls, value: str, info) -> str:
|
|
78
|
+
"""Validate synapse-backend project exists."""
|
|
79
|
+
if not value:
|
|
80
|
+
return value
|
|
81
|
+
|
|
82
|
+
action = info.context['action']
|
|
83
|
+
client = action.client
|
|
84
|
+
try:
|
|
85
|
+
client.get_project(value)
|
|
86
|
+
except ClientError:
|
|
87
|
+
raise PydanticCustomError('client_error', _('Error occurred while checking project exists.'))
|
|
88
|
+
return value
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@register_action
|
|
92
|
+
class UploadAction(Action):
|
|
93
|
+
"""Upload action class.
|
|
94
|
+
|
|
95
|
+
Attrs:
|
|
96
|
+
name (str): The name of the action.
|
|
97
|
+
category (PluginCategory): The category of the action.
|
|
98
|
+
method (RunMethod): The method to run of the action.
|
|
99
|
+
|
|
100
|
+
Progress Categories:
|
|
101
|
+
analyze_collection: The progress category for the analyze collection process.
|
|
102
|
+
data_file_upload: The progress category for the upload process.
|
|
103
|
+
generate_data_units: The progress category for the generate data units process.
|
|
104
|
+
generate_tasks: The progress category for the generate tasks process.
|
|
105
|
+
generate_ground_truths: The progress category for the generate ground truths process.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
name = 'upload'
|
|
109
|
+
category = PluginCategory.UPLOAD
|
|
110
|
+
method = RunMethod.JOB
|
|
111
|
+
progress_categories = {
|
|
112
|
+
'analyze_collection': {
|
|
113
|
+
'proportion': 5,
|
|
114
|
+
},
|
|
115
|
+
'upload_data_files': {
|
|
116
|
+
'proportion': 35,
|
|
117
|
+
},
|
|
118
|
+
'generate_data_units': {
|
|
119
|
+
'proportion': 20,
|
|
120
|
+
},
|
|
121
|
+
'generate_tasks': {
|
|
122
|
+
'proportion': 20,
|
|
123
|
+
},
|
|
124
|
+
'generate_ground_truths': {
|
|
125
|
+
'proportion': 20,
|
|
126
|
+
},
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
def get_uploader(self, path):
|
|
130
|
+
"""Get uploader from entrypoint."""
|
|
131
|
+
return self.entrypoint(self.run, path)
|
|
132
|
+
|
|
133
|
+
def start(self) -> Dict:
|
|
134
|
+
"""Start upload process.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Dict: The result of the upload process.
|
|
138
|
+
"""
|
|
139
|
+
# Setup path object with path and storage.
|
|
140
|
+
storage = self.client.get_storage(self.params['storage'])
|
|
141
|
+
pathlib_cwd = get_pathlib(storage, self.params['path'])
|
|
142
|
+
|
|
143
|
+
# Initialize uploader.
|
|
144
|
+
uploader = self.get_uploader(pathlib_cwd)
|
|
145
|
+
|
|
146
|
+
# Analyze Collection file specifications to determine the data structure for upload.
|
|
147
|
+
self.run.set_progress(0, 1, category='analyze_collection')
|
|
148
|
+
file_specification_skeleton = self._analyze_collection()
|
|
149
|
+
self.run.set_progress(1, 1, category='analyze_collection')
|
|
150
|
+
|
|
151
|
+
# Setup result dict.
|
|
152
|
+
result = {}
|
|
153
|
+
|
|
154
|
+
# Organize data according to Collection file specification structure.
|
|
155
|
+
organized_files = uploader.handle_upload_files()
|
|
156
|
+
if not self._validate_organized_files(file_specification_skeleton, organized_files):
|
|
157
|
+
self.run.log_message('Validate organized files failed.')
|
|
158
|
+
return result
|
|
159
|
+
|
|
160
|
+
# Upload files to synapse-backend.
|
|
161
|
+
organized_files_count = len(organized_files)
|
|
162
|
+
if not organized_files_count:
|
|
163
|
+
self.run.log_message('Files not found on the path.', context=Context.WARNING.value)
|
|
164
|
+
return result
|
|
165
|
+
|
|
166
|
+
self.run.set_progress(0, organized_files_count, category='upload_data_files')
|
|
167
|
+
self.run.log_message('Uploading data files...')
|
|
168
|
+
result['uploaded_files'] = self._upload_files(organized_files)
|
|
169
|
+
self.run.set_progress(organized_files_count, organized_files_count, category='upload_data_files')
|
|
170
|
+
self.run.log_message('Upload data files completed.')
|
|
171
|
+
|
|
172
|
+
# Generate data units for the uploaded data.
|
|
173
|
+
upload_result_count = len(result['uploaded_files'])
|
|
174
|
+
if not upload_result_count:
|
|
175
|
+
self.run.log_message('No files were uploaded.', context=Context.WARNING.value)
|
|
176
|
+
return result
|
|
177
|
+
|
|
178
|
+
self.run.set_progress(0, upload_result_count, category='generate_data_units')
|
|
179
|
+
generated_data_units = self._generate_data_units(result['uploaded_files'])
|
|
180
|
+
result['generated_data_units'] = generated_data_units
|
|
181
|
+
self.run.set_progress(upload_result_count, upload_result_count, category='generate_data_units')
|
|
182
|
+
|
|
183
|
+
# Setup task with uploaded synapse-backend data units.
|
|
184
|
+
if not len(generated_data_units):
|
|
185
|
+
self.run.log_message('No data units were generated.', context=Context.WARNING.value)
|
|
186
|
+
return result
|
|
187
|
+
|
|
188
|
+
self.run.set_progress(0, 1, category='generate_tasks')
|
|
189
|
+
if self.config['options']['allow_generate_tasks'] and self.params['is_generate_tasks']:
|
|
190
|
+
self.run.log_message('Generating tasks with data files...')
|
|
191
|
+
self._generate_tasks(generated_data_units)
|
|
192
|
+
self.run.log_message('Generating tasks completed')
|
|
193
|
+
else:
|
|
194
|
+
self.run.log_message('Generating tasks process has passed.')
|
|
195
|
+
|
|
196
|
+
self.run.set_progress(1, 1, category='generate_tasks')
|
|
197
|
+
|
|
198
|
+
# Generate ground truths for the uploaded data.
|
|
199
|
+
# TODO: Need to add ground truths generation logic later.
|
|
200
|
+
self.run.set_progress(0, 1, category='generate_ground_truths')
|
|
201
|
+
if self.config['options']['allow_generate_ground_truths'] and self.params['is_generate_ground_truths']:
|
|
202
|
+
self.run.log_message('Generating ground truths...')
|
|
203
|
+
self._generate_ground_truths()
|
|
204
|
+
self.run.log_message('Generating ground truths completed')
|
|
205
|
+
else:
|
|
206
|
+
self.run.log_message('Generating ground truths process has passed.')
|
|
207
|
+
self.run.set_progress(1, 1, category='generate_ground_truths')
|
|
208
|
+
|
|
209
|
+
return result
|
|
210
|
+
|
|
211
|
+
def _analyze_collection(self) -> Dict:
|
|
212
|
+
"""Analyze Synapse Collection Specifications.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Dict: The file specifications of the collection.
|
|
216
|
+
"""
|
|
217
|
+
client = self.run.client
|
|
218
|
+
collection_id = self.params['collection']
|
|
219
|
+
collection = client.get_dataset(collection_id)
|
|
220
|
+
return collection['file_specifications']
|
|
221
|
+
|
|
222
|
+
def _validate_organized_files(self, file_specification_skeleton: Dict, organized_files: List) -> bool:
|
|
223
|
+
"""Validate organized files from Uploader."""
|
|
224
|
+
return True
|
|
225
|
+
|
|
226
|
+
def _upload_files(self, organized_files) -> List:
|
|
227
|
+
"""Upload files to synapse-backend.
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
Dict: The result of the upload.
|
|
231
|
+
"""
|
|
232
|
+
client = self.run.client
|
|
233
|
+
collection_id = self.params['collection']
|
|
234
|
+
upload_result = []
|
|
235
|
+
organized_files_count = len(organized_files)
|
|
236
|
+
current_progress = 0
|
|
237
|
+
for organized_file in organized_files:
|
|
238
|
+
upload_result.append(client.upload_data_file(organized_file, collection_id))
|
|
239
|
+
self.run.set_progress(current_progress, organized_files_count, category='upload_data_files')
|
|
240
|
+
current_progress += 1
|
|
241
|
+
return upload_result
|
|
242
|
+
|
|
243
|
+
def _generate_data_units(self, uploaded_files: List) -> List:
|
|
244
|
+
"""Generate data units for the uploaded data.
|
|
245
|
+
|
|
246
|
+
TODO: make batch size configurable.
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
Dict: The result of the generate data units process.
|
|
250
|
+
"""
|
|
251
|
+
client = self.run.client
|
|
252
|
+
|
|
253
|
+
generation_result = []
|
|
254
|
+
current_progress = 0
|
|
255
|
+
batches = get_batched_list(uploaded_files, 100)
|
|
256
|
+
batches_count = len(batches)
|
|
257
|
+
for batch in batches:
|
|
258
|
+
generation_result.append(client.create_data_units(batch))
|
|
259
|
+
self.run.set_progress(current_progress, batches_count, category='generate_data_units')
|
|
260
|
+
current_progress += 1
|
|
261
|
+
return generation_result
|
|
262
|
+
|
|
263
|
+
def _generate_tasks(self, generated_data_units: List):
|
|
264
|
+
"""Setup task with uploaded synapse-backend data units.
|
|
265
|
+
|
|
266
|
+
TODO: make batch size configurable.
|
|
267
|
+
"""
|
|
268
|
+
|
|
269
|
+
# Prepare batches for processing
|
|
270
|
+
client = self.run.client
|
|
271
|
+
project_id = self.params['project']
|
|
272
|
+
current_progress = 0
|
|
273
|
+
|
|
274
|
+
# Generate tasks
|
|
275
|
+
generated_data_units_count = len(generated_data_units)
|
|
276
|
+
for data_units in generated_data_units:
|
|
277
|
+
tasks_data = []
|
|
278
|
+
for data_unit in data_units:
|
|
279
|
+
task_data = {'project': project_id, 'data_unit': data_unit['id']}
|
|
280
|
+
tasks_data.append(task_data)
|
|
281
|
+
|
|
282
|
+
if tasks_data:
|
|
283
|
+
client.create_tasks(tasks_data)
|
|
284
|
+
|
|
285
|
+
self.run.set_progress(current_progress, generated_data_units_count, category='generate_tasks')
|
|
286
|
+
current_progress += 1
|
|
287
|
+
|
|
288
|
+
def _generate_ground_truths(self):
|
|
289
|
+
"""Generate ground truths for the uploaded data.
|
|
290
|
+
|
|
291
|
+
TODO: Need to add ground truths generation logic later.
|
|
292
|
+
"""
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Uploader:
|
|
6
|
+
"""Plugin upload action class.
|
|
7
|
+
|
|
8
|
+
* Organize, upload, setup task, generate ground truths for the uploaded data.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, run, path: Path, *args, **kwargs):
|
|
12
|
+
"""Initialize the plugin upload action class.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
run: Plugin run object.
|
|
16
|
+
path: pathlib object by upload target destination path.
|
|
17
|
+
"""
|
|
18
|
+
self.run = run
|
|
19
|
+
self.path = path
|
|
20
|
+
|
|
21
|
+
def handle_upload_files(self) -> List:
|
|
22
|
+
"""Handle upload files.
|
|
23
|
+
|
|
24
|
+
* Organize data according to collection file specification structure.
|
|
25
|
+
* Structure files according to the file specification of the target collection.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
List: List of dictionaries containing 'files' and 'meta'.
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
[
|
|
32
|
+
{
|
|
33
|
+
"files": {
|
|
34
|
+
'image_1': image_1_pathlib_object,
|
|
35
|
+
'image_2': image_2_pathlib_object,
|
|
36
|
+
'meta_1': meta_1_pathlib_object,
|
|
37
|
+
},
|
|
38
|
+
"meta": {
|
|
39
|
+
"key": "value"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
"""
|
|
44
|
+
return []
|
synapse_sdk/plugins/enums.py
CHANGED
|
@@ -2,6 +2,8 @@ from enum import Enum
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class RunMethod(Enum):
|
|
5
|
+
"""Plugin Execution Methods."""
|
|
6
|
+
|
|
5
7
|
JOB = 'job'
|
|
6
8
|
TASK = 'task'
|
|
7
9
|
RESTAPI = 'restapi'
|
|
@@ -10,7 +12,7 @@ class RunMethod(Enum):
|
|
|
10
12
|
class PluginCategory(Enum):
|
|
11
13
|
NEURAL_NET = 'neural_net'
|
|
12
14
|
EXPORT = 'export'
|
|
13
|
-
|
|
15
|
+
UPLOAD = 'upload'
|
|
14
16
|
SMART_TOOL = 'smart_tool'
|
|
15
17
|
POST_ANNOTATION = 'post_annotation'
|
|
16
18
|
PRE_ANNOTATION = 'pre_annotation'
|
synapse_sdk/plugins/models.py
CHANGED
|
@@ -87,6 +87,15 @@ class PluginRelease:
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
class Run:
|
|
90
|
+
"""Run class for manage plugin run istance.
|
|
91
|
+
|
|
92
|
+
Attrs:
|
|
93
|
+
job_id: plugin run job id
|
|
94
|
+
context: plugin run context
|
|
95
|
+
client: backend client for communicate with backend
|
|
96
|
+
logger: logger for log plugin run events
|
|
97
|
+
"""
|
|
98
|
+
|
|
90
99
|
logger = None
|
|
91
100
|
job_id = None
|
|
92
101
|
context = None
|
|
@@ -111,6 +120,13 @@ class Run:
|
|
|
111
120
|
self.logger = ConsoleLogger(**kwargs)
|
|
112
121
|
|
|
113
122
|
def set_progress(self, current, total, category=''):
|
|
123
|
+
"""Set progress for plugin run.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
current: current progress value
|
|
127
|
+
total: total progress value
|
|
128
|
+
category: progress category
|
|
129
|
+
"""
|
|
114
130
|
self.logger.set_progress(current, total, category)
|
|
115
131
|
|
|
116
132
|
def log(self, event, data, file=None):
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from pathlib import Path
|
|
1
2
|
from urllib.parse import urlparse
|
|
2
3
|
|
|
3
4
|
from synapse_sdk.i18n import gettext as _
|
|
@@ -15,6 +16,15 @@ def get_storage(connection_param: str | dict):
|
|
|
15
16
|
return STORAGE_PROVIDERS[storage_scheme](connection_param)
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
def get_pathlib(storage_config, path_root):
|
|
19
|
+
def get_pathlib(storage_config: str | dict, path_root: str) -> Path:
|
|
20
|
+
"""Get pathlib object with synapse-backend storage config.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
storage_config (str | dict): The storage config by synapse-backend storage api.
|
|
24
|
+
path_root (str): The path root.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
pathlib.Path: The pathlib object.
|
|
28
|
+
"""
|
|
19
29
|
storage_class = get_storage(storage_config)
|
|
20
30
|
return storage_class.get_pathlib(path_root)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: synapse-sdk
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.0a32
|
|
4
4
|
Summary: synapse sdk
|
|
5
5
|
Author-email: datamaker <developer@datamaker.io>
|
|
6
6
|
License: MIT
|
|
@@ -21,6 +21,7 @@ Requires-Dist: universal-pathlib
|
|
|
21
21
|
Requires-Dist: fsspec[gcs,s3,sftp]
|
|
22
22
|
Provides-Extra: all
|
|
23
23
|
Requires-Dist: ray[all]; extra == "all"
|
|
24
|
+
Dynamic: license-file
|
|
24
25
|
|
|
25
26
|
This is the SDK to develop synapse plugins
|
|
26
27
|
|
|
@@ -21,7 +21,7 @@ synapse_sdk/cli/plugin/create.py,sha256=HpYTpohV1NbSrULaVUlc4jWLWznPrx7glgydTM3s
|
|
|
21
21
|
synapse_sdk/cli/plugin/publish.py,sha256=sIl1wiuSC3lAUpE3rOF4UDKDy2G5EVLlelMjk2aT05g,1221
|
|
22
22
|
synapse_sdk/cli/plugin/run.py,sha256=xz5LRm3zh8Y9DMjw5FFRFVRWSCWtYfZJskfCmrPikaQ,2598
|
|
23
23
|
synapse_sdk/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
-
synapse_sdk/clients/base.py,sha256=
|
|
24
|
+
synapse_sdk/clients/base.py,sha256=m3zEX1wv_sSxa-jBCnE-9Q5-f71o1TdODkWHRE9Vo-E,4403
|
|
25
25
|
synapse_sdk/clients/exceptions.py,sha256=ylv7x10eOp4aA3a48jwonnvqvkiYwzJYXjkVkRTAjwk,220
|
|
26
26
|
synapse_sdk/clients/utils.py,sha256=8pPJTdzHiRPSbZMoQYHAgR2BAMO6u_R_jMV6a2p34iQ,392
|
|
27
27
|
synapse_sdk/clients/agent/__init__.py,sha256=Pz8_iTbIbnb7ywGJ3feqoZVmO2I3mEbwpWsISIxh0BU,1968
|
|
@@ -31,20 +31,20 @@ synapse_sdk/clients/agent/service.py,sha256=s7KuPK_DB1nr2VHrigttV1WyFonaGHNrPvU8
|
|
|
31
31
|
synapse_sdk/clients/backend/__init__.py,sha256=aozhPhvRTPHz1P90wxEay07B-Ct4vj_yTw5H9_PJEBE,1105
|
|
32
32
|
synapse_sdk/clients/backend/annotation.py,sha256=eZc5EidgR_RfMGwvv1r1_mLkPdRd8e52c4zuuMjMX34,979
|
|
33
33
|
synapse_sdk/clients/backend/core.py,sha256=5XAOdo6JZ0drfk-FMPJ96SeTd9oja-VnTwzGXdvK7Bg,1027
|
|
34
|
-
synapse_sdk/clients/backend/dataset.py,sha256=
|
|
34
|
+
synapse_sdk/clients/backend/dataset.py,sha256=11R5LuTva9jgXatxQAlKy7UEJmwIWzTsLVdFf3MZ9F8,3400
|
|
35
35
|
synapse_sdk/clients/backend/integration.py,sha256=MCfeChpLySqlVRc1aZxCfDpQiRH--pfevkCdJDCNZEQ,2506
|
|
36
36
|
synapse_sdk/clients/backend/ml.py,sha256=JoPH9Ly2E3HJ7S5mdGLtcGq7ruQVVrYfWArogwZLlms,1193
|
|
37
37
|
synapse_sdk/clients/ray/__init__.py,sha256=9ZSPXVVxlJ8Wp8ku7l021ENtPjVrGgQDgqifkkVAXgM,187
|
|
38
38
|
synapse_sdk/clients/ray/core.py,sha256=a4wyCocAma2HAm-BHlbZnoVbpfdR-Aad2FM0z6vPFvw,731
|
|
39
39
|
synapse_sdk/clients/ray/serve.py,sha256=rbCpXZYWf0oP8XJ9faa9QFNPYU7h8dltIG8xn9ZconY,907
|
|
40
40
|
synapse_sdk/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
-
synapse_sdk/plugins/enums.py,sha256=
|
|
41
|
+
synapse_sdk/plugins/enums.py,sha256=ibixwqA3sCNSriG1jAtL54JQc_Zwo3MufwYUqGhVncc,523
|
|
42
42
|
synapse_sdk/plugins/exceptions.py,sha256=Qs7qODp_RRLO9y2otU2T4ryj5LFwIZODvSIXkAh91u0,691
|
|
43
|
-
synapse_sdk/plugins/models.py,sha256=
|
|
43
|
+
synapse_sdk/plugins/models.py,sha256=njTQIT-c2d7TsqAN__q1aoYm8hLEPC7ludTj665iN-4,4148
|
|
44
44
|
synapse_sdk/plugins/upload.py,sha256=VJOotYMayylOH0lNoAGeGHRkLdhP7jnC_A0rFQMvQpQ,3228
|
|
45
45
|
synapse_sdk/plugins/utils.py,sha256=4_K6jIl0WrsXOEhFp94faMOriSsddOhIiaXcawYYUUA,3300
|
|
46
46
|
synapse_sdk/plugins/categories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
|
-
synapse_sdk/plugins/categories/base.py,sha256=
|
|
47
|
+
synapse_sdk/plugins/categories/base.py,sha256=cfk7mgidCBnldZ8nCo_Nq_qzP9C1LJYgSXWtYT6hJDw,10046
|
|
48
48
|
synapse_sdk/plugins/categories/decorators.py,sha256=Gw6T-UHwpCKrSt596X-g2sZbY_Z1zbbogowClj7Pr5Q,518
|
|
49
49
|
synapse_sdk/plugins/categories/registry.py,sha256=KdQR8SUlLT-3kgYzDNWawS1uJnAhrcw2j4zFaTpilRs,636
|
|
50
50
|
synapse_sdk/plugins/categories/templates.py,sha256=FF5FerhkZMeW1YcKLY5cylC0SkWSYdJODA_Qcm4OGYQ,887
|
|
@@ -56,20 +56,16 @@ synapse_sdk/plugins/categories/data_validation/templates/plugin/__init__.py,sha2
|
|
|
56
56
|
synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py,sha256=90I5boUpEXvO3mEuKKBs528ls2A4h8Iw4ReOID2h00Y,139
|
|
57
57
|
synapse_sdk/plugins/categories/export/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
58
|
synapse_sdk/plugins/categories/export/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
|
-
synapse_sdk/plugins/categories/export/actions/export.py,sha256=
|
|
60
|
-
synapse_sdk/plugins/categories/export/actions/utils.py,sha256=ixilT_VtgwtbX9kbBTrIybbAyW1kPLhNEkOHABKmZ88,131
|
|
59
|
+
synapse_sdk/plugins/categories/export/actions/export.py,sha256=45hnvM3myFgRJyGpC_jpDu_VaDC-iaNCqy4DcH24eDU,2926
|
|
61
60
|
synapse_sdk/plugins/categories/export/templates/config.yaml,sha256=N7YmnFROb3s3M35SA9nmabyzoSb5O2t2TRPicwFNN2o,56
|
|
62
61
|
synapse_sdk/plugins/categories/export/templates/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
|
-
synapse_sdk/plugins/categories/export/templates/plugin/export.py,sha256=
|
|
64
|
-
synapse_sdk/plugins/categories/import/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
65
|
-
synapse_sdk/plugins/categories/import/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
66
|
-
synapse_sdk/plugins/categories/import/actions/import.py,sha256=URn6TOp081odMT5D4NlZ2XEcyKelJx8fxzdoKSkXSAI,320
|
|
62
|
+
synapse_sdk/plugins/categories/export/templates/plugin/export.py,sha256=cSUhgY5FDqMWVj4XlrOfzDN8q-NxOAvB3BTMXdqd-Eg,4604
|
|
67
63
|
synapse_sdk/plugins/categories/neural_net/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
64
|
synapse_sdk/plugins/categories/neural_net/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
65
|
synapse_sdk/plugins/categories/neural_net/actions/deployment.py,sha256=Wmi7in_Mgizt1d5XcDR080h1CIMWKh2_mjub9N380qA,1917
|
|
70
66
|
synapse_sdk/plugins/categories/neural_net/actions/inference.py,sha256=0a655ELqNVjPFZTJDiw4EUdcMCPGveUEKyoYqpwMFBU,1019
|
|
71
67
|
synapse_sdk/plugins/categories/neural_net/actions/test.py,sha256=JY25eg-Fo6WbgtMkGoo_qNqoaZkp3AQNEypJmeGzEog,320
|
|
72
|
-
synapse_sdk/plugins/categories/neural_net/actions/train.py,sha256=
|
|
68
|
+
synapse_sdk/plugins/categories/neural_net/actions/train.py,sha256=kve6iTCg2kUeavMQTR2JFuoYDu-QWZFFlB58ZICQtdM,5406
|
|
73
69
|
synapse_sdk/plugins/categories/neural_net/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
70
|
synapse_sdk/plugins/categories/neural_net/base/inference.py,sha256=R5DASI6-5vzsjDOYxqeGGMBjnav5qHF4hNJT8zNUR3I,1097
|
|
75
71
|
synapse_sdk/plugins/categories/neural_net/templates/config.yaml,sha256=vSTHgKzi7sHzsuUvhOT001hzR6JBpPCue5nECmruEnI,433
|
|
@@ -95,6 +91,12 @@ synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py,sha256=fHiqA8ntm
|
|
|
95
91
|
synapse_sdk/plugins/categories/smart_tool/templates/config.yaml,sha256=7bvb4M1PLaoTOVDYF05L7yb8ix4rZOrAnEuZ-thMsyo,206
|
|
96
92
|
synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
97
93
|
synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py,sha256=eevNg0nOcYFR4z_L_R-sCvVOYoLWSAH1jwDkAf3YCjY,320
|
|
94
|
+
synapse_sdk/plugins/categories/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
95
|
+
synapse_sdk/plugins/categories/upload/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
96
|
+
synapse_sdk/plugins/categories/upload/actions/upload.py,sha256=V7gArcj7FZO8AT_ihUGodrc_7q49Q7j9BKc9DvoYOYQ,11178
|
|
97
|
+
synapse_sdk/plugins/categories/upload/templates/config.yaml,sha256=0PhB2uD-9ufavZs7EiF6xj4aBgZuif9mFFGGfzG7HuY,147
|
|
98
|
+
synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
99
|
+
synapse_sdk/plugins/categories/upload/templates/plugin/upload.py,sha256=dnK8gy33GjG5ettayawDJv1gM3xCm1K6lM-PfeeTjQw,1163
|
|
98
100
|
synapse_sdk/plugins/templates/cookiecutter.json,sha256=NxOWk9A_v1pO0Ny4IYT9Cj5iiJ16--cIQrGC67QdR0I,396
|
|
99
101
|
synapse_sdk/plugins/templates/hooks/post_gen_project.py,sha256=jqlYkY1O2TxIR-Vh3gnwILYy8k-D39Xx66d2KNQVMCs,147
|
|
100
102
|
synapse_sdk/plugins/templates/hooks/pre_prompt.py,sha256=aOAMM623s0sKFGjTZaotAOYFvsNMxeii4tPyhOAFKVE,539
|
|
@@ -117,15 +119,15 @@ synapse_sdk/utils/pydantic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
|
117
119
|
synapse_sdk/utils/pydantic/config.py,sha256=1vYOcUI35GslfD1rrqhFkNXXJOXt4IDqOPSx9VWGfNE,123
|
|
118
120
|
synapse_sdk/utils/pydantic/errors.py,sha256=0v0T12eQBr1KrFiEOBu6KMaPK4aPEGEC6etPJGoR5b4,1061
|
|
119
121
|
synapse_sdk/utils/pydantic/validators.py,sha256=G47P8ObPhsePmd_QZDK8EdPnik2CbaYzr_N4Z6En8dc,193
|
|
120
|
-
synapse_sdk/utils/storage/__init__.py,sha256=
|
|
122
|
+
synapse_sdk/utils/storage/__init__.py,sha256=AOPEo1_4Tssr3X0_pu5cbmJP_V5ywx9qSocIzZTc2kM,1005
|
|
121
123
|
synapse_sdk/utils/storage/registry.py,sha256=WaSN9SJR7s9sZgmTVl5k4mLFz-9R6X4ii82wefxs95A,335
|
|
122
124
|
synapse_sdk/utils/storage/providers/__init__.py,sha256=NM9yRIWcPkH53DeNHgIhH9zaDFK8SJv0KptP1Afulyw,1125
|
|
123
125
|
synapse_sdk/utils/storage/providers/gcp.py,sha256=i2BQCu1Kej1If9SuNr2_lEyTcr5M_ncGITZrL0u5wEA,363
|
|
124
126
|
synapse_sdk/utils/storage/providers/s3.py,sha256=r94aUGVNf8yxihU0lN62yaXdxSS7P783_sfD-hCiK40,1191
|
|
125
127
|
synapse_sdk/utils/storage/providers/sftp.py,sha256=TUQXkKJf0-fh8NhGC_1zzqI4autFNHZVCqngwkQ1aD4,523
|
|
126
|
-
synapse_sdk-1.0.
|
|
127
|
-
synapse_sdk-1.0.
|
|
128
|
-
synapse_sdk-1.0.
|
|
129
|
-
synapse_sdk-1.0.
|
|
130
|
-
synapse_sdk-1.0.
|
|
131
|
-
synapse_sdk-1.0.
|
|
128
|
+
synapse_sdk-1.0.0a32.dist-info/licenses/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
|
|
129
|
+
synapse_sdk-1.0.0a32.dist-info/METADATA,sha256=jJsMUwX1BNln7bpCx7CGxkQQuE6UCCvSk4P2i9as7x4,1160
|
|
130
|
+
synapse_sdk-1.0.0a32.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
|
|
131
|
+
synapse_sdk-1.0.0a32.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
|
|
132
|
+
synapse_sdk-1.0.0a32.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
|
|
133
|
+
synapse_sdk-1.0.0a32.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
from synapse_sdk.plugins.categories.base import Action
|
|
2
|
-
from synapse_sdk.plugins.categories.decorators import register_action
|
|
3
|
-
from synapse_sdk.plugins.enums import PluginCategory, RunMethod
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@register_action
|
|
7
|
-
class ImportAction(Action):
|
|
8
|
-
name = 'import'
|
|
9
|
-
category = PluginCategory.IMPORT
|
|
10
|
-
method = RunMethod.JOB
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|