synapse-sdk 1.0.0a9__py3-none-any.whl → 1.0.0a10__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 (35) hide show
  1. synapse_sdk/clients/agent/__init__.py +30 -2
  2. synapse_sdk/clients/agent/ray.py +54 -0
  3. synapse_sdk/clients/agent/service.py +0 -39
  4. synapse_sdk/clients/backend/integration.py +4 -0
  5. synapse_sdk/clients/backend/ml.py +4 -0
  6. synapse_sdk/clients/base.py +3 -0
  7. synapse_sdk/clients/ray/__init__.py +6 -0
  8. synapse_sdk/clients/ray/core.py +22 -0
  9. synapse_sdk/clients/ray/serve.py +20 -0
  10. synapse_sdk/i18n.py +35 -0
  11. synapse_sdk/locale/en/LC_MESSAGES/messages.po +39 -0
  12. synapse_sdk/locale/ko/LC_MESSAGES/messages.po +34 -0
  13. synapse_sdk/loggers.py +3 -3
  14. synapse_sdk/plugins/categories/base.py +38 -9
  15. synapse_sdk/plugins/categories/neural_net/actions/deployment.py +21 -0
  16. synapse_sdk/plugins/categories/neural_net/actions/inference.py +8 -0
  17. synapse_sdk/plugins/categories/neural_net/actions/train.py +7 -6
  18. synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py +18 -3
  19. synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +1 -0
  20. synapse_sdk/plugins/cli/__init__.py +3 -1
  21. synapse_sdk/plugins/cli/publish.py +2 -1
  22. synapse_sdk/plugins/exceptions.py +18 -2
  23. synapse_sdk/plugins/models.py +26 -7
  24. synapse_sdk/plugins/upload.py +2 -1
  25. synapse_sdk/shared/__init__.py +0 -0
  26. synapse_sdk/shared/enums.py +8 -0
  27. synapse_sdk/utils/debug.py +4 -1
  28. synapse_sdk/utils/file.py +2 -0
  29. synapse_sdk-1.0.0a10.dist-info/METADATA +43 -0
  30. {synapse_sdk-1.0.0a9.dist-info → synapse_sdk-1.0.0a10.dist-info}/RECORD +34 -25
  31. synapse_sdk-1.0.0a9.dist-info/METADATA +0 -22
  32. {synapse_sdk-1.0.0a9.dist-info → synapse_sdk-1.0.0a10.dist-info}/LICENSE +0 -0
  33. {synapse_sdk-1.0.0a9.dist-info → synapse_sdk-1.0.0a10.dist-info}/WHEEL +0 -0
  34. {synapse_sdk-1.0.0a9.dist-info → synapse_sdk-1.0.0a10.dist-info}/entry_points.txt +0 -0
  35. {synapse_sdk-1.0.0a9.dist-info → synapse_sdk-1.0.0a10.dist-info}/top_level.txt +0 -0
@@ -1,18 +1,22 @@
1
1
  from synapse_sdk.clients.agent.core import CoreClientMixin
2
+ from synapse_sdk.clients.agent.ray import RayClientMixin
2
3
  from synapse_sdk.clients.agent.service import ServiceClientMixin
4
+ from synapse_sdk.clients.exceptions import ClientError
3
5
 
4
6
 
5
- class AgentClient(CoreClientMixin, ServiceClientMixin):
7
+ class AgentClient(CoreClientMixin, RayClientMixin, ServiceClientMixin):
6
8
  name = 'Agent'
7
9
  agent_token = None
8
10
  user_token = None
9
11
  tenant = None
12
+ long_poll_handler = None
10
13
 
11
- def __init__(self, base_url, agent_token, user_token=None, tenant=None):
14
+ def __init__(self, base_url, agent_token, user_token=None, tenant=None, long_poll_handler=None):
12
15
  super().__init__(base_url)
13
16
  self.agent_token = agent_token
14
17
  self.user_token = user_token
15
18
  self.tenant = tenant
19
+ self.long_poll_handler = long_poll_handler
16
20
 
17
21
  def _get_headers(self):
18
22
  headers = {'Authorization': self.agent_token}
@@ -21,3 +25,27 @@ class AgentClient(CoreClientMixin, ServiceClientMixin):
21
25
  if self.tenant:
22
26
  headers['SYNAPSE-Tenant'] = f'Token {self.tenant}'
23
27
  return headers
28
+
29
+ def _request(self, method, path, **kwargs):
30
+ if self.long_poll_handler:
31
+ return self._request_long_poll(method, path, **kwargs)
32
+ return super()._request(method, path, **kwargs)
33
+
34
+ def _request_long_poll(self, method, path, **kwargs):
35
+ headers = self._get_headers()
36
+
37
+ if kwargs.get('files'):
38
+ raise ClientError(400, 'file is not allowed when long polling')
39
+
40
+ headers['Content-Type'] = 'application/json'
41
+
42
+ request_id = self.long_poll_handler.set_request({'method': method, 'path': path, 'headers': headers, **kwargs})
43
+ try:
44
+ response = self.long_poll_handler.get_response(request_id)
45
+ except TimeoutError:
46
+ raise ClientError(408, f'{self.name} is not responding')
47
+
48
+ if 400 <= response['status'] < 600:
49
+ raise ClientError(response['status'], response.json() if response['status'] == 400 else response['reason'])
50
+
51
+ return response['data']
@@ -0,0 +1,54 @@
1
+ from synapse_sdk.clients.base import BaseClient
2
+ from synapse_sdk.clients.exceptions import ClientError
3
+
4
+
5
+ class RayClientMixin(BaseClient):
6
+ def get_job(self, pk):
7
+ path = f'jobs/{pk}/'
8
+ return self._get(path)
9
+
10
+ def list_jobs(self):
11
+ path = 'jobs/'
12
+ return self._get(path)
13
+
14
+ def list_job_logs(self, pk):
15
+ path = f'jobs/{pk}/logs/'
16
+ return self._get(path)
17
+
18
+ def tail_job_logs(self, pk):
19
+ if self.long_poll_handler:
20
+ raise ClientError(400, '"tail_job_logs" does not support long polling')
21
+
22
+ path = f'jobs/{pk}/tail_logs/'
23
+
24
+ url = self._get_url(path)
25
+ headers = self._get_headers()
26
+
27
+ response = self.requests_session.get(url, headers=headers, stream=True)
28
+ for line in response.iter_lines(decode_unicode=True):
29
+ if line:
30
+ yield f'{line}\n'
31
+
32
+ def get_node(self, pk):
33
+ path = f'nodes/{pk}/'
34
+ return self._get(path)
35
+
36
+ def list_nodes(self):
37
+ path = 'nodes/'
38
+ return self._get(path)
39
+
40
+ def get_task(self, pk):
41
+ path = f'tasks/{pk}/'
42
+ return self._get(path)
43
+
44
+ def list_tasks(self):
45
+ path = 'tasks/'
46
+ return self._get(path)
47
+
48
+ def get_serve_application(self, pk):
49
+ path = f'serve_application/{pk}/'
50
+ return self._get(path)
51
+
52
+ def list_serve_applications(self):
53
+ path = 'serve_applications/'
54
+ return self._get(path)
@@ -13,42 +13,3 @@ class ServiceClientMixin(BaseClient):
13
13
  def create_plugin_release(self, data):
14
14
  path = 'plugin_releases/'
15
15
  return self._post(path, data=data)
16
-
17
- def get_job(self, pk):
18
- path = f'jobs/{pk}/'
19
- return self._get(path)
20
-
21
- def list_jobs(self):
22
- path = 'jobs/'
23
- return self._get(path)
24
-
25
- def list_job_logs(self, pk):
26
- path = f'jobs/{pk}/logs/'
27
- return self._get(path)
28
-
29
- def tail_job_logs(self, pk):
30
- path = f'jobs/{pk}/tail_logs/'
31
-
32
- url = self._get_url(path)
33
- headers = self._get_headers()
34
-
35
- response = self.requests_session.get(url, headers=headers, stream=True)
36
- for line in response.iter_lines(decode_unicode=True):
37
- if line:
38
- yield f'{line}\n'
39
-
40
- def get_node(self, pk):
41
- path = f'nodes/{pk}/'
42
- return self._get(path)
43
-
44
- def list_nodes(self):
45
- path = 'nodes/'
46
- return self._get(path)
47
-
48
- def get_task(self, pk):
49
- path = f'tasks/{pk}/'
50
- return self._get(path)
51
-
52
- def list_tasks(self):
53
- path = 'tasks/'
54
- return self._get(path)
@@ -31,6 +31,10 @@ class IntegrationClientMixin(BaseClient):
31
31
  files = {'file': data.pop('file')}
32
32
  return self._post(path, data=data, files=files)
33
33
 
34
+ def get_job(self, pk, params=None):
35
+ path = f'jobs/{pk}/'
36
+ return self._get(path, params=params)
37
+
34
38
  def list_jobs(self, params=None):
35
39
  path = 'jobs/'
36
40
  return self._get(path, params=params)
@@ -19,6 +19,10 @@ class MLClientMixin(BaseClient):
19
19
  files = {'file': data.pop('file')}
20
20
  return self._post(path, data=data, files=files)
21
21
 
22
+ def create_serve_application(self, data):
23
+ path = 'serve_applications/'
24
+ return self._post(path, data=data)
25
+
22
26
  def list_ground_truth_events(self, params=None, url_conversion=None, list_all=False):
23
27
  path = 'ground_truth_events/'
24
28
  url_conversion = get_default_url_conversion(url_conversion, files_fields=['files'])
@@ -50,6 +50,9 @@ class BaseClient:
50
50
  except requests.ConnectionError:
51
51
  raise ClientError(408, f'{self.name} is not responding')
52
52
 
53
+ return self._post_response(response)
54
+
55
+ def _post_response(self, response):
53
56
  try:
54
57
  return response.json()
55
58
  except ValueError:
@@ -0,0 +1,6 @@
1
+ from synapse_sdk.clients.ray.core import CoreClientMixin
2
+ from synapse_sdk.clients.ray.serve import ServeClientMixin
3
+
4
+
5
+ class RayClient(ServeClientMixin, CoreClientMixin):
6
+ name = 'Ray'
@@ -0,0 +1,22 @@
1
+ from synapse_sdk.clients.base import BaseClient
2
+ from synapse_sdk.clients.exceptions import ClientError
3
+
4
+
5
+ class CoreClientMixin(BaseClient):
6
+ def list_nodes(self, params=None):
7
+ path = 'nodes'
8
+ response = self._get(path, params=params)
9
+ if not response['result']:
10
+ raise ClientError(200, response['msg'])
11
+ return response['data']['summary']
12
+
13
+ def get_node(self, pk, params=None):
14
+ path = f'nodes/{pk}'
15
+ response = self._get(path, params=params)['detail']
16
+
17
+ if not response['result']:
18
+ raise ClientError(200, response['msg'])
19
+
20
+ if 'agent' not in response['data']:
21
+ raise ClientError(404, 'Node Not Found')
22
+ return response['data']
@@ -0,0 +1,20 @@
1
+ from synapse_sdk.clients.base import BaseClient
2
+ from synapse_sdk.clients.exceptions import ClientError
3
+
4
+
5
+ class ServeClientMixin(BaseClient):
6
+ def list_serve_applications(self, params=None):
7
+ path = 'api/serve/applications/'
8
+ response = self._get(path, params=params)
9
+ for key, item in response['applications'].items():
10
+ response['applications'][key]['deployments'] = list(item['deployments'].values())
11
+ return list(response['applications'].values())
12
+
13
+ def get_serve_application(self, pk, params=None):
14
+ path = 'api/serve/applications/'
15
+ response = self._get(path, params=params)
16
+ try:
17
+ response['applications'][pk]['deployments'] = list(response['applications'][pk]['deployments'].values())
18
+ return response['applications'][pk]
19
+ except KeyError:
20
+ raise ClientError(404, 'Serve Application Not Found')
synapse_sdk/i18n.py ADDED
@@ -0,0 +1,35 @@
1
+ import gettext as _gettext
2
+ import locale
3
+ from pathlib import Path
4
+
5
+ ASSIGNED_LOCALE = None
6
+
7
+
8
+ def set_language(language):
9
+ ASSIGNED_LOCALE = language # noqa: F841
10
+
11
+
12
+ def get_locale():
13
+ if ASSIGNED_LOCALE is not None:
14
+ return ASSIGNED_LOCALE
15
+
16
+ system_locale, encoding = locale.getlocale()
17
+
18
+ if system_locale is None:
19
+ system_locale = 'en'
20
+
21
+ return system_locale
22
+
23
+
24
+ language = get_locale().split('_')[0]
25
+
26
+ PACKAGE_DIR = Path(__file__).parent
27
+ LOCALE_DIR = PACKAGE_DIR / 'locale'
28
+
29
+ translation = _gettext.translation('messages', localedir=LOCALE_DIR, languages=[language], fallback=True)
30
+ translation.install()
31
+
32
+ gettext = translation.gettext
33
+ ngettext = translation.ngettext
34
+ pgettext = translation.pgettext
35
+ npgettext = translation.npgettext
@@ -0,0 +1,39 @@
1
+ # English translations for PACKAGE package.
2
+ # Copyright (C) 2024 THE PACKAGE'S COPYRIGHT HOLDER
3
+ # This file is distributed under the same license as the PACKAGE package.
4
+ # <developer@datamaker.io>, 2024.
5
+ #
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: PACKAGE VERSION\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2024-11-27 16:15+0900\n"
11
+ "PO-Revision-Date: 2024-11-27 16:17+0900\n"
12
+ "Last-Translator: <developer@datamaker.io>\n"
13
+ "Language-Team: English\n"
14
+ "Language: en\n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
+
20
+ #: synapse_sdk/utils/debug.py:5
21
+ msgid "hello world from sdk"
22
+ msgstr "hello world from sdk"
23
+
24
+ #: synapse_sdk/plugins/cli/publish.py:34
25
+ #, python-brace-format
26
+ msgid ""
27
+ "Successfully published \"{plugin_release.name}\" ({plugin_release.code}) to "
28
+ "synapse backend!"
29
+ msgstr ""
30
+ "Successfully published \"{plugin_release.name}\" ({plugin_release.code}) to "
31
+ "synapse backend!"
32
+
33
+ #: synapse_sdk/plugins/cli/__init__.py:15
34
+ msgid "Debug mode is \"on\""
35
+ msgstr "Debug mode is \"on\""
36
+
37
+ #: synapse_sdk/plugins/upload.py:62
38
+ msgid "Building {Path(source_path).name}..."
39
+ msgstr "Building {Path(source_path).name}..."
@@ -0,0 +1,34 @@
1
+ # Korean translations for PACKAGE package.
2
+ # Copyright (C) 2024 THE PACKAGE'S COPYRIGHT HOLDER
3
+ # This file is distributed under the same license as the PACKAGE package.
4
+ # <developer@datamaker.io>, 2024.
5
+ #
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: PACKAGE VERSION\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2024-11-27 17:16+0900\n"
11
+ "PO-Revision-Date: 2024-11-27 17:16+0900\n"
12
+ "Last-Translator: <developer@datamaker.io>\n"
13
+ "Language-Team: Korean <translation-team-ko@googlegroups.com>\n"
14
+ "Language: ko\n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=1; plural=0;\n"
19
+
20
+ #: synapse_sdk/utils/debug.py:5
21
+ msgid "hello world from sdk"
22
+ msgstr ""
23
+
24
+ #: synapse_sdk/plugins/cli/publish.py:34
25
+ msgid "Successfully published \"{}\" ({}) to synapse backend!"
26
+ msgstr "Synapse 백엔드에 \"{}\" ({})를 성공적으로 등록되었습니다!"
27
+
28
+ #: synapse_sdk/plugins/cli/__init__.py:17
29
+ msgid "Debug mode is \"on\""
30
+ msgstr "디버그 모드가 \"켜짐\" 상태입니다"
31
+
32
+ #: synapse_sdk/plugins/upload.py:63
33
+ msgid "Building {}..."
34
+ msgstr "{} 빌드 중..."
synapse_sdk/loggers.py CHANGED
@@ -99,11 +99,11 @@ class BackendLogger(BaseLogger):
99
99
  except ClientError:
100
100
  pass
101
101
 
102
- def log(self, action, data):
103
- print(action, data)
102
+ def log(self, event, data):
103
+ print(event, data)
104
104
 
105
105
  log = {
106
- 'action': action,
106
+ 'event': event,
107
107
  'data': data,
108
108
  'datetime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'),
109
109
  'job': self.job_id,
@@ -8,9 +8,11 @@ import ray
8
8
  import requests
9
9
  from pydantic import ValidationError
10
10
  from ray.dashboard.modules.job.sdk import JobSubmissionClient
11
+ from ray.exceptions import RayTaskError
11
12
 
13
+ from synapse_sdk.clients.ray import RayClient
12
14
  from synapse_sdk.plugins.enums import RunMethod
13
- from synapse_sdk.plugins.exceptions import ActionValidationError
15
+ from synapse_sdk.plugins.exceptions import ActionError
14
16
  from synapse_sdk.plugins.models import PluginRelease, Run
15
17
  from synapse_sdk.plugins.upload import archive_and_upload, build_and_upload, download_and_upload
16
18
  from synapse_sdk.utils.module_loading import import_string
@@ -38,6 +40,7 @@ class Action:
38
40
  run = None
39
41
 
40
42
  default_envs = [
43
+ 'RAY_ADDRESS',
41
44
  'RAY_DASHBOARD_URL',
42
45
  'RAY_SERVE_ADDRESS',
43
46
  'SYNAPSE_PLUGIN_STORAGE',
@@ -56,7 +59,7 @@ class Action:
56
59
  self.job_id = job_id
57
60
  self.direct = direct
58
61
  self.debug = debug
59
- self.envs = {**envs, **self.get_default_envs()} if envs else self.get_default_envs()
62
+ self.envs = {**self.get_default_envs(), **envs} if envs else self.get_default_envs()
60
63
  self.run = self.get_run()
61
64
 
62
65
  @cached_property
@@ -71,6 +74,10 @@ class Action:
71
74
  def client(self):
72
75
  return self.run.client
73
76
 
77
+ @property
78
+ def ray_client(self):
79
+ return RayClient(self.envs['RAY_DASHBOARD_URL'])
80
+
74
81
  @property
75
82
  def plugin_url(self):
76
83
  if self.debug:
@@ -131,10 +138,14 @@ class Action:
131
138
  try:
132
139
  self.params_model.model_validate(self.params, context={'action': self})
133
140
  except ValidationError as e:
134
- raise ActionValidationError({'params': pydantic_to_drf_error(e)})
141
+ raise ActionError({'params': pydantic_to_drf_error(e)})
135
142
 
136
143
  def run_action(self):
137
144
  self.validate_params()
145
+
146
+ if not ray.is_initialized():
147
+ ray.init(address=self.envs['RAY_ADDRESS'], ignore_reinit_error=True)
148
+
138
149
  if self.direct:
139
150
  if self.method == RunMethod.RESTAPI:
140
151
  return self.start_by_restapi()
@@ -171,7 +182,11 @@ class Action:
171
182
  kwargs[param.name] = getattr(self, param.name)
172
183
 
173
184
  kwargs['direct'] = True
174
- return ray.get(run_task.remote(self.category.value, self.name, *args, **kwargs))
185
+ try:
186
+ return ray.get(run_task.remote(self.category.value, self.name, *args, **kwargs))
187
+ except RayTaskError as e:
188
+ error = e.as_instanceof_cause()
189
+ raise ActionError(error.cause)
175
190
 
176
191
  def start_by_job(self):
177
192
  main_options = []
@@ -186,7 +201,7 @@ class Action:
186
201
 
187
202
  cmd = ' '.join(main_options + options + arguments)
188
203
 
189
- client = JobSubmissionClient(address=self.envs.get('RAY_DASHBOARD_URL'))
204
+ client = self.get_job_client()
190
205
  return client.submit_job(
191
206
  submission_id=self.job_id,
192
207
  entrypoint=f'python main.py {cmd}',
@@ -198,10 +213,24 @@ class Action:
198
213
  method = self.params.pop('method')
199
214
 
200
215
  url = self.plugin_release.get_serve_url(self.envs['RAY_SERVE_ADDRESS'], path)
201
- response = getattr(requests, method)(url, **self.params)
202
- # TODO ok response가 아닌 경우 대응하기
203
- return response.json()
216
+ try:
217
+ response = getattr(requests, method)(url, **self.params)
218
+ try:
219
+ response_body = response.json()
220
+ except ValueError:
221
+ response_body = response.text
222
+ if response.ok:
223
+ return response_body
224
+ else:
225
+ raise ActionError({'status': response.status_code, 'reason': response.reason, 'message': response_body})
226
+ except requests.ConnectionError:
227
+ raise ActionError('Unable to connect to serve application')
204
228
 
205
229
  def post_action_by_job(self, result):
206
230
  if self.client:
207
- self.client.update_job(self.job_id, data={'result': result})
231
+ job_client = self.get_job_client()
232
+ logs = job_client.get_job_logs(self.job_id).split('\n')
233
+ self.client.update_job(self.job_id, data={'result': result or {}, 'console_logs': logs})
234
+
235
+ def get_job_client(self):
236
+ return JobSubmissionClient(address=self.envs.get('RAY_DASHBOARD_URL'))
@@ -1,5 +1,6 @@
1
1
  from ray import serve
2
2
 
3
+ from synapse_sdk.clients.exceptions import ClientError
3
4
  from synapse_sdk.plugins.categories.base import Action
4
5
  from synapse_sdk.plugins.categories.decorators import register_action
5
6
  from synapse_sdk.plugins.enums import PluginCategory, RunMethod
@@ -22,3 +23,23 @@ class DeploymentAction(Action):
22
23
  serve.delete(self.plugin_release.code)
23
24
  # TODO add run object
24
25
  serve.run(deployment.bind(), name=self.plugin_release.code, route_prefix=f'/{self.plugin_release.checksum}')
26
+
27
+ # 백엔드에 ServeApplication 추가
28
+ serve_application = self.create_serve_application()
29
+ return {'serve_application': serve_application['id'] if serve_application else None}
30
+
31
+ def create_serve_application(self):
32
+ if self.client:
33
+ try:
34
+ job = self.client.get_job(self.job_id)
35
+ serve_application = self.ray_client.get_serve_application(self.plugin_release.code)
36
+ return self.client.create_serve_application({
37
+ 'plugin': self.plugin_release.plugin,
38
+ 'version': self.plugin_release.version,
39
+ 'agent': job['agent'],
40
+ 'status': serve_application['status'],
41
+ 'data': serve_application,
42
+ })
43
+ except ClientError:
44
+ pass
45
+ return None
@@ -8,3 +8,11 @@ class InferenceAction(Action):
8
8
  name = 'inference'
9
9
  category = PluginCategory.NEURAL_NET
10
10
  method = RunMethod.RESTAPI
11
+
12
+ def __init__(self, *args, **kwargs):
13
+ super().__init__(*args, **kwargs)
14
+ headers = {'serve_multiplexed_model_id': str(self.params.pop('model'))}
15
+ if 'headers' in self.params:
16
+ self.params['headers'].update(headers)
17
+ else:
18
+ self.params['headers'] = headers
@@ -17,8 +17,8 @@ from synapse_sdk.utils.pydantic.validators import non_blank
17
17
 
18
18
 
19
19
  class TrainRun(Run):
20
- def log_metric(self, x, i, **kwargs):
21
- self.log(x, {x: i, **kwargs})
20
+ def log_metric(self, key, value, **metrics):
21
+ self.log('metric', {'key': key, 'value': value, 'metrics': metrics})
22
22
 
23
23
 
24
24
  class Hyperparameter(BaseModel):
@@ -80,22 +80,22 @@ class TrainAction(Action):
80
80
  hyperparameter = self.params['hyperparameter']
81
81
 
82
82
  # download dataset
83
- self.run.log_event('Preparing dataset for training.')
83
+ self.run.log_message('Preparing dataset for training.')
84
84
  input_dataset = self.get_dataset()
85
85
 
86
86
  # train dataset
87
- self.run.log_event('Starting model training.')
87
+ self.run.log_message('Starting model training.')
88
88
 
89
89
  result = self.entrypoint(self.run, input_dataset, hyperparameter)
90
90
 
91
91
  # upload model_data
92
- self.run.log_event('Registering model data.')
92
+ self.run.log_message('Registering model data.')
93
93
  self.run.set_progress(0, 1, category='model_upload')
94
94
  model = self.create_model(result)
95
95
  self.run.set_progress(1, 1, category='model_upload')
96
96
 
97
97
  self.run.end_log()
98
- return {'model_id': model['id']}
98
+ return {'model_id': model['id'] if model else None}
99
99
 
100
100
  def get_dataset(self):
101
101
  client = self.run.client
@@ -123,6 +123,7 @@ class TrainAction(Action):
123
123
  def create_model(self, path):
124
124
  if not self.client:
125
125
  print(path)
126
+ return None
126
127
 
127
128
  params = copy.deepcopy(self.params)
128
129
  configuration_fields = ['hyperparameter']
@@ -1,11 +1,13 @@
1
1
  from synapse_sdk.plugins.categories.base import Action
2
2
  from synapse_sdk.plugins.categories.decorators import register_action
3
3
  from synapse_sdk.plugins.enums import PluginCategory, RunMethod
4
+ from synapse_sdk.plugins.exceptions import ActionError
5
+ from synapse_sdk.plugins.utils import get_action
4
6
 
5
7
 
6
8
  @register_action
7
9
  class AutoLabelAction(Action):
8
- name = 'label'
10
+ name = 'auto_label'
9
11
  category = PluginCategory.SMART_TOOL
10
12
  method = RunMethod.TASK
11
13
 
@@ -13,10 +15,23 @@ class AutoLabelAction(Action):
13
15
  return self.entrypoint(**self.params)
14
16
 
15
17
  def run_model(self, input_data):
16
- return {}
18
+ try:
19
+ action = get_action(
20
+ 'inference',
21
+ input_data,
22
+ config={
23
+ 'category': 'neural_net',
24
+ 'code': self.params['plugin'],
25
+ 'version': self.params['version'],
26
+ 'actions': {'inference': {'method': input_data['method']}},
27
+ },
28
+ )
29
+ return action.run_action()
30
+ except ActionError as e:
31
+ raise Exception(e.errors)
17
32
 
18
33
  def start(self):
19
34
  auto_label = self.get_auto_label()
20
- input_data = auto_label.handle_input(self.params['input_data'])
35
+ input_data = auto_label.handle_input(self.params)
21
36
  output_data = self.run_model(input_data)
22
37
  return auto_label.handle_output(output_data)
@@ -1,3 +1,4 @@
1
+ smart_tool: interactive_segmentation
1
2
  actions:
2
3
  auto_label:
3
4
  category: interactive_segmentation
@@ -1,5 +1,7 @@
1
1
  import click
2
2
 
3
+ from synapse_sdk.i18n import gettext as _
4
+
3
5
  from .publish import publish
4
6
  from .run import run
5
7
 
@@ -12,7 +14,7 @@ def cli(ctx, debug):
12
14
  ctx.obj['DEBUG'] = debug
13
15
 
14
16
  if debug:
15
- click.echo('Debug mode is "on"')
17
+ click.echo(_('Debug mode is "on"'))
16
18
 
17
19
 
18
20
  cli.add_command(run)
@@ -4,6 +4,7 @@ from pathlib import Path
4
4
  import click
5
5
 
6
6
  from synapse_sdk.clients.backend import BackendClient
7
+ from synapse_sdk.i18n import gettext as _
7
8
  from synapse_sdk.plugins.models import PluginRelease
8
9
  from synapse_sdk.plugins.upload import archive
9
10
 
@@ -30,7 +31,7 @@ def publish(ctx, host, user_token, tenant, debug_modules):
30
31
  client = BackendClient(host, user_token, tenant=tenant)
31
32
  client.create_plugin_release(data)
32
33
  click.secho(
33
- f'Successfully published "{plugin_release.name}" ({plugin_release.code}) to synapse backend!',
34
+ _('Successfully published "{}" ({}) to synapse backend!').format(plugin_release.name, plugin_release.code),
34
35
  fg='green',
35
36
  bold=True,
36
37
  )
@@ -1,6 +1,22 @@
1
- class ActionValidationError(Exception):
1
+ class ActionError(Exception):
2
2
  errors = None
3
3
 
4
4
  def __init__(self, errors, *args):
5
- self.errors = errors
5
+ if isinstance(errors, (str, dict)):
6
+ self.errors = errors
7
+ elif isinstance(errors, Exception) and len(errors.args) == 1:
8
+ self.errors = ActionError(errors.args[0]).errors
9
+ else:
10
+ self.errors = str(errors)
6
11
  super().__init__(errors, *args)
12
+
13
+ def as_drf_error(self, data=None):
14
+ if data is None:
15
+ data = self.errors
16
+
17
+ if isinstance(data, list):
18
+ return data
19
+ elif isinstance(data, dict):
20
+ return {key: self.as_drf_error(value) for key, value in data.items()}
21
+
22
+ return [str(data)]
@@ -2,9 +2,14 @@ import os
2
2
  from functools import cached_property
3
3
  from typing import Any, Dict
4
4
 
5
+ import ray
6
+ from ray.util.scheduling_strategies import NodeAffinitySchedulingStrategy
7
+ from ray.util.state import list_nodes
8
+
5
9
  from synapse_sdk.clients.backend import BackendClient
6
10
  from synapse_sdk.loggers import BackendLogger, ConsoleLogger
7
11
  from synapse_sdk.plugins.utils import read_plugin_config
12
+ from synapse_sdk.shared.enums import Context
8
13
  from synapse_sdk.utils.storage import get_storage
9
14
  from synapse_sdk.utils.string import hash_text
10
15
 
@@ -49,8 +54,22 @@ class PluginRelease:
49
54
  return list(self.config['actions'].keys())
50
55
 
51
56
  def setup_runtime_env(self):
52
- # TODO ray에 해당 plugin release runtime env 캐싱
53
- pass
57
+ @ray.remote
58
+ def warm_up():
59
+ pass
60
+
61
+ nodes = list_nodes(address=self.envs['RAY_DASHBOARD_URL'])
62
+ node_ids = [n['node_id'] for n in nodes]
63
+ for node_id in node_ids:
64
+ strategy = NodeAffinitySchedulingStrategy(node_id=node_id, soft=False)
65
+
66
+ warm_up.options(
67
+ runtime_env={
68
+ 'pip': ['-r ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}/requirements.txt'],
69
+ 'working_dir': self.get_url(self.envs['SYNAPSE_PLUGIN_STORAGE']),
70
+ },
71
+ scheduling_strategy=strategy,
72
+ ).remote()
54
73
 
55
74
  def get_action_config(self, action):
56
75
  return self.config['actions'][action]
@@ -92,11 +111,11 @@ class Run:
92
111
  def set_progress(self, current, total, category=''):
93
112
  self.logger.set_progress(current, total, category)
94
113
 
95
- def log(self, action, data):
96
- self.logger.log(action, data)
114
+ def log(self, event, data):
115
+ self.logger.log(event, data)
97
116
 
98
- def log_event(self, message):
99
- self.logger.log('event', {'content': message})
117
+ def log_message(self, message, context=Context.INFO.value):
118
+ self.logger.log('message', {'context': context, 'content': message})
100
119
 
101
120
  def end_log(self):
102
- self.log_event('Plugin run is complete.')
121
+ self.log_message('Plugin run is complete.')
@@ -2,6 +2,7 @@ import subprocess
2
2
  import tempfile
3
3
  from pathlib import Path
4
4
 
5
+ from synapse_sdk.i18n import gettext as _
5
6
  from synapse_sdk.utils.file import calculate_checksum, download_file
6
7
  from synapse_sdk.utils.storage import get_storage
7
8
 
@@ -59,7 +60,7 @@ def build_and_upload(source_path, url, virtualenv_path='.venv'):
59
60
  for file_path in dist_path.glob('*.whl'):
60
61
  file_path.unlink()
61
62
 
62
- print(f'Building {Path(source_path).name}...')
63
+ print(_('Building {}...').format(Path(source_path).name))
63
64
  subprocess.run(
64
65
  f'{virtualenv_path}/bin/python -m build --wheel',
65
66
  cwd=source_path,
File without changes
@@ -0,0 +1,8 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Context(str, Enum):
5
+ INFO = 'info'
6
+ SUCCESS = 'success'
7
+ WARNING = 'warning'
8
+ DANGER = 'danger'
@@ -1,2 +1,5 @@
1
+ from synapse_sdk.i18n import gettext as _
2
+
3
+
1
4
  def get_message():
2
- return 'hello world from sdk'
5
+ return _('hello world from sdk')
synapse_sdk/utils/file.py CHANGED
@@ -4,6 +4,7 @@ import operator
4
4
  import zipfile
5
5
  from functools import reduce
6
6
  from pathlib import Path
7
+ from urllib.parse import urlparse
7
8
 
8
9
  import requests
9
10
  import yaml
@@ -15,6 +16,7 @@ def download_file(url, path_download, name=None, coerce=None):
15
16
  else:
16
17
  name = Path(url).name
17
18
 
19
+ name = urlparse(name).path
18
20
  path = Path(path_download) / name
19
21
  if not path.is_file():
20
22
  r = requests.get(url, allow_redirects=True)
@@ -0,0 +1,43 @@
1
+ Metadata-Version: 2.1
2
+ Name: synapse-sdk
3
+ Version: 1.0.0a10
4
+ Summary: synapse sdk
5
+ Author-email: datamaker <developer@datamaker.io>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Requires-Python: >=3.11
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: boto3
12
+ Requires-Dist: click
13
+ Requires-Dist: cookiecutter
14
+ Requires-Dist: requests
15
+ Requires-Dist: tqdm
16
+ Requires-Dist: python-dotenv
17
+ Requires-Dist: pyyaml
18
+ Requires-Dist: pydantic
19
+ Provides-Extra: all
20
+ Requires-Dist: ray[all]; extra == "all"
21
+
22
+ This is the SDK to develop synapse plugins
23
+
24
+
25
+ ## Internationalization
26
+
27
+ ### Find Messages
28
+ ```bash
29
+ $ find . -name "*.py" | xargs xgettext -o messages.pot
30
+ ```
31
+
32
+ ### Make Messages
33
+ ```bash
34
+ $ msginit -l ko -i messages.pot -o synapse_sdk/locale/ko/LC_MESSAGES/messages.po
35
+ $ msginit -l en -i messages.pot -o synapse_sdk/locale/en/LC_MESSAGES/messages.po
36
+ ```
37
+
38
+ ### Compile Messages
39
+
40
+ ```bash
41
+ $ msgfmt synapse_sdk/locale/ko/LC_MESSAGES/messages.po -o synapse_sdk/locale/ko/LC_MESSAGES/messages.mo
42
+ $ msgfmt synapse_sdk/locale/en/LC_MESSAGES/messages.po -o synapse_sdk/locale/en/LC_MESSAGES/messages.mo
43
+ ```
@@ -1,27 +1,34 @@
1
1
  synapse_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- synapse_sdk/loggers.py,sha256=avoceBBu9VuSNS_CC3M5X8rWmAlk5xCTYEAVqxAXzBM,4008
2
+ synapse_sdk/i18n.py,sha256=OZKL3sArRhusT0Z_3TWJ3KvuSHLWmrFllVshZFaSKxw,759
3
+ synapse_sdk/loggers.py,sha256=RsDDOiOeUCih1XOkWQJseYdYCX_wt50AZJRe6aPf96Q,4004
3
4
  synapse_sdk/cli/__init__.py,sha256=WmYGW1qZEXXIGJe3SGr8QjOStY4svuZKK1Lp_aPvtPs,140
4
5
  synapse_sdk/cli/create_plugin.py,sha256=egbW_92WwxfHz50Gy4znX5Bf5fxDdQj3GFyd0l3Y3SY,228
5
6
  synapse_sdk/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- synapse_sdk/clients/base.py,sha256=vVt6Qi3R3lVnzCTD0WMRDYw99u2d1SMAqDXgkcvq4VM,3146
7
+ synapse_sdk/clients/base.py,sha256=BPQjM-5Uq-u1wksPnIXaFAzKjNXtcKT4s6-WgxYWs80,3232
7
8
  synapse_sdk/clients/exceptions.py,sha256=ylv7x10eOp4aA3a48jwonnvqvkiYwzJYXjkVkRTAjwk,220
8
9
  synapse_sdk/clients/utils.py,sha256=8pPJTdzHiRPSbZMoQYHAgR2BAMO6u_R_jMV6a2p34iQ,392
9
- synapse_sdk/clients/agent/__init__.py,sha256=k5cGnN-dUAYYfeQDiRW4XEFWUgwSH9mwJFcvjzgwpOc,768
10
+ synapse_sdk/clients/agent/__init__.py,sha256=Pz8_iTbIbnb7ywGJ3feqoZVmO2I3mEbwpWsISIxh0BU,1968
10
11
  synapse_sdk/clients/agent/core.py,sha256=YicfkO0YvjDDOt1jNWoZ0mokrh8xxKibBL4qF5yOjKs,169
11
- synapse_sdk/clients/agent/service.py,sha256=NnRu0XPVRqry6PWN_8-3iuzdXx20zO1lPXw-yVWQbdg,1433
12
+ synapse_sdk/clients/agent/ray.py,sha256=eQydp2ar0XDlzaY82XbS9TvGPOn_c9c7t7pig48P14g,1436
13
+ synapse_sdk/clients/agent/service.py,sha256=s7KuPK_DB1nr2VHrigttV1WyFonaGHNrPvU8loRxHcE,478
12
14
  synapse_sdk/clients/backend/__init__.py,sha256=SVC7kDO_z_4YqpLDR-O_RrrxJFkWmMhJC8Hl_Mc5Sz4,830
13
15
  synapse_sdk/clients/backend/annotation.py,sha256=eZc5EidgR_RfMGwvv1r1_mLkPdRd8e52c4zuuMjMX34,979
14
16
  synapse_sdk/clients/backend/dataset.py,sha256=X8R71vff1gLytlEaOnKhBWjVQaZcIG_WYy32new4Vq0,1737
15
- synapse_sdk/clients/backend/integration.py,sha256=Z0Vvhp4NsbP4W9esTH_0SDrPkzHy84t1joSinvtjWgI,1744
16
- synapse_sdk/clients/backend/ml.py,sha256=SwA4_noRCZ1dVIzyXfrs2zHuRlQZdZt17o1We5QOxl8,1053
17
+ synapse_sdk/clients/backend/integration.py,sha256=0NNwbkGMYrfz5Baq8s_FfZ6U4uXs0AfTl78YuW6Samo,1860
18
+ synapse_sdk/clients/backend/ml.py,sha256=rBF_iWRpGPbwP9obblqayYgAAMvGkERposBlOgoRXP8,1180
19
+ synapse_sdk/clients/ray/__init__.py,sha256=9ZSPXVVxlJ8Wp8ku7l021ENtPjVrGgQDgqifkkVAXgM,187
20
+ synapse_sdk/clients/ray/core.py,sha256=a4wyCocAma2HAm-BHlbZnoVbpfdR-Aad2FM0z6vPFvw,731
21
+ synapse_sdk/clients/ray/serve.py,sha256=rbCpXZYWf0oP8XJ9faa9QFNPYU7h8dltIG8xn9ZconY,907
22
+ synapse_sdk/locale/en/LC_MESSAGES/messages.po,sha256=r2a1qgUTRPHHUQ5VVitwkVxP7SFyScjSmEp9Ej39elY,1224
23
+ synapse_sdk/locale/ko/LC_MESSAGES/messages.po,sha256=43hgIhC8m8MNtjes8tP9K92_8tkjvnZxxhOmfgdrCn8,1127
17
24
  synapse_sdk/plugins/__init__.py,sha256=9vsbYhxah4_ofTaG0x0qLFID_raHNkO57Y8A31Ws-lU,222
18
25
  synapse_sdk/plugins/enums.py,sha256=s59P6Oz2WAK9IX-kLVhNOvNKYJifKlWBhPpZbc9-ttE,486
19
- synapse_sdk/plugins/exceptions.py,sha256=RFRz2SIHc4WmTd7sKZOMrQtD5nm4ldtb8CzG9VG65OE,167
20
- synapse_sdk/plugins/models.py,sha256=pzzJl9zKL8v2XjBQC0UR-W9rG4Vyp95DzJ9MMG2W5L0,2835
21
- synapse_sdk/plugins/upload.py,sha256=SSCHUR4HJ_mdLN7mUkk5UlXmL9028SKP6tpBS2rpf0A,3175
26
+ synapse_sdk/plugins/exceptions.py,sha256=Qs7qODp_RRLO9y2otU2T4ryj5LFwIZODvSIXkAh91u0,691
27
+ synapse_sdk/plugins/models.py,sha256=TGlOO_s6b2O1ed8KOvpGCRxyq2Ae9UHxbnwx_OJejTw,3597
28
+ synapse_sdk/plugins/upload.py,sha256=VJOotYMayylOH0lNoAGeGHRkLdhP7jnC_A0rFQMvQpQ,3228
22
29
  synapse_sdk/plugins/utils.py,sha256=n3s-zFnj4hrGWFtaBTJFbaupI8qUQL6S8_5YcbxOmeY,1482
23
30
  synapse_sdk/plugins/categories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- synapse_sdk/plugins/categories/base.py,sha256=8WhcLa406V3rR31byhueQssRKeJsoO-kFWGzpre7O20,7062
31
+ synapse_sdk/plugins/categories/base.py,sha256=MkGrkUIJlYwVO9QLjQNpm2vtGjtt11NypqNfpdSuScI,8106
25
32
  synapse_sdk/plugins/categories/decorators.py,sha256=Gw6T-UHwpCKrSt596X-g2sZbY_Z1zbbogowClj7Pr5Q,518
26
33
  synapse_sdk/plugins/categories/registry.py,sha256=KdQR8SUlLT-3kgYzDNWawS1uJnAhrcw2j4zFaTpilRs,636
27
34
  synapse_sdk/plugins/categories/templates.py,sha256=FF5FerhkZMeW1YcKLY5cylC0SkWSYdJODA_Qcm4OGYQ,887
@@ -39,10 +46,10 @@ synapse_sdk/plugins/categories/import/actions/__init__.py,sha256=47DEQpj8HBSa-_T
39
46
  synapse_sdk/plugins/categories/import/actions/import.py,sha256=URn6TOp081odMT5D4NlZ2XEcyKelJx8fxzdoKSkXSAI,320
40
47
  synapse_sdk/plugins/categories/neural_net/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
48
  synapse_sdk/plugins/categories/neural_net/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
- synapse_sdk/plugins/categories/neural_net/actions/deployment.py,sha256=U44sv_5UN2awfkbpyYPH9zOTEBhYn0FfcZwV7ywi-cA,827
43
- synapse_sdk/plugins/categories/neural_net/actions/inference.py,sha256=qavUxayUDgN5E5Ht0x3cqWF0uPNkwUiZlCmfo574xHE,334
49
+ synapse_sdk/plugins/categories/neural_net/actions/deployment.py,sha256=ASRY0-ijdNZl9zTslszIBoaKpn0q_MITcUSoGWoc25c,1741
50
+ synapse_sdk/plugins/categories/neural_net/actions/inference.py,sha256=i18bDDjkuF9V8nxxW-T_umNIOD-Jnq_MMjIjZc6W8n8,645
44
51
  synapse_sdk/plugins/categories/neural_net/actions/test.py,sha256=JY25eg-Fo6WbgtMkGoo_qNqoaZkp3AQNEypJmeGzEog,320
45
- synapse_sdk/plugins/categories/neural_net/actions/train.py,sha256=pE0RTruXqX1Jdp4iWDpsRH80V7TnvMnZnAlLOYkRusA,4463
52
+ synapse_sdk/plugins/categories/neural_net/actions/train.py,sha256=TPtCAfovmFyzCYRbiRtlrov9AjE6XPQLDB94W0M1OuU,4558
46
53
  synapse_sdk/plugins/categories/neural_net/templates/config.yaml,sha256=pvJFh_NHGZHHFfqrvZm6fHO5lsS7CudaIGboP6wbtY8,252
47
54
  synapse_sdk/plugins/categories/neural_net/templates/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
55
  synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py,sha256=glYYdRybG3vRe48bYIxvue7bCFGPlEZmYWRoyBsLdZw,123
@@ -62,12 +69,12 @@ synapse_sdk/plugins/categories/pre_annotation/templates/plugin/__init__.py,sha25
62
69
  synapse_sdk/plugins/categories/pre_annotation/templates/plugin/pre_annotation.py,sha256=HBHxHuv2gMBzDB2alFfrzI_SZ1Ztk6mo7eFbR5GqHKw,106
63
70
  synapse_sdk/plugins/categories/smart_tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
71
  synapse_sdk/plugins/categories/smart_tool/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
- synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py,sha256=MZKpLsCGzO1FJsE32D7O3gC2rrTpYZKP1x0oE-Uu8Mc,699
66
- synapse_sdk/plugins/categories/smart_tool/templates/config.yaml,sha256=lTixdat8b3LZi_JeiUZfAN5oM5iFnqLD5M-xR_xF7M4,145
72
+ synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py,sha256=fHiqA8ntmzjs2GMVMuByR7Clh2zhLie8OPF9B8OmwxM,1279
73
+ synapse_sdk/plugins/categories/smart_tool/templates/config.yaml,sha256=3jxW8daipL2voo1cAeg8cEu-JFcOvhEa4VT2OvDI4JA,182
67
74
  synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
75
  synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py,sha256=eevNg0nOcYFR4z_L_R-sCvVOYoLWSAH1jwDkAf3YCjY,320
69
- synapse_sdk/plugins/cli/__init__.py,sha256=8ogaOhN-RbDNYHqziW8nLsNUxKkZwGkHBdKxTahcm3U,334
70
- synapse_sdk/plugins/cli/publish.py,sha256=ecX5vne2MuULon7JvH6NfiNcn7ccdv2SZUd9TakQzCI,1145
76
+ synapse_sdk/plugins/cli/__init__.py,sha256=LPtUO0jqkhKq6xR1grpse7da2R6OoT_BeDyCNyUY0T4,380
77
+ synapse_sdk/plugins/cli/publish.py,sha256=aJ7eWdw_c0stIoBY4jWRpeGP0h5qUJWTFUHD6jNs6aM,1200
71
78
  synapse_sdk/plugins/cli/run.py,sha256=lw1KbsL-xTGllF4NtD2cq-Rh6HMbhi-sO862_Ds-sUo,2330
72
79
  synapse_sdk/plugins/templates/cookiecutter.json,sha256=NxOWk9A_v1pO0Ny4IYT9Cj5iiJ16--cIQrGC67QdR0I,396
73
80
  synapse_sdk/plugins/templates/hooks/post_gen_project.py,sha256=jqlYkY1O2TxIR-Vh3gnwILYy8k-D39Xx66d2KNQVMCs,147
@@ -82,9 +89,11 @@ synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/main.p
82
89
  synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/pyproject.toml,sha256=Usgd80tHZAD1Ug5MAjPfETUZxtKKgZW-xovFEAEbQDo,317
83
90
  synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt,sha256=F5UwinpTLQFfyakFGTFxgBOo4H-EKD9d4e77WKOPHhk,17
84
91
  synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
+ synapse_sdk/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
93
+ synapse_sdk/shared/enums.py,sha256=WMZPag9deVF7VCXaQkLk7ly_uX1KwbNzRx9TdvgaeFE,138
85
94
  synapse_sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
- synapse_sdk/utils/debug.py,sha256=46sMFQLg_JSRUCymnT3wgszG1QsgrocRGiBjVX38r50,53
87
- synapse_sdk/utils/file.py,sha256=nuU6POe0F6_WvIB26X9Q6dpcwgys8unt5Qv66n0Bmg4,2482
95
+ synapse_sdk/utils/debug.py,sha256=F7JlUwYjTFZAMRbBqKm6hxOIz-_IXYA8lBInOS4jbS4,100
96
+ synapse_sdk/utils/file.py,sha256=OYch8D5Ub8oaGIIcpO6_R6-McpR3QJk7xlkaffhgd_c,2547
88
97
  synapse_sdk/utils/module_loading.py,sha256=chHpU-BZjtYaTBD_q0T7LcKWtqKvYBS4L0lPlKkoMQ8,1020
89
98
  synapse_sdk/utils/storage.py,sha256=a8OVbd38ATr0El4G4kuV07lr_tJZrpIJBSy4GHb0qZ8,2581
90
99
  synapse_sdk/utils/string.py,sha256=rEwuZ9SAaZLcQ8TYiwNKr1h2u4CfnrQx7SUL8NWmChg,216
@@ -92,9 +101,9 @@ synapse_sdk/utils/pydantic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
92
101
  synapse_sdk/utils/pydantic/config.py,sha256=1vYOcUI35GslfD1rrqhFkNXXJOXt4IDqOPSx9VWGfNE,123
93
102
  synapse_sdk/utils/pydantic/errors.py,sha256=0v0T12eQBr1KrFiEOBu6KMaPK4aPEGEC6etPJGoR5b4,1061
94
103
  synapse_sdk/utils/pydantic/validators.py,sha256=G47P8ObPhsePmd_QZDK8EdPnik2CbaYzr_N4Z6En8dc,193
95
- synapse_sdk-1.0.0a9.dist-info/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
96
- synapse_sdk-1.0.0a9.dist-info/METADATA,sha256=4pnZMrqZytZAvodVHryUt8WTbLnPwreD2iYPr7XTvvE,567
97
- synapse_sdk-1.0.0a9.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
98
- synapse_sdk-1.0.0a9.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
99
- synapse_sdk-1.0.0a9.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
100
- synapse_sdk-1.0.0a9.dist-info/RECORD,,
104
+ synapse_sdk-1.0.0a10.dist-info/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
105
+ synapse_sdk-1.0.0a10.dist-info/METADATA,sha256=PHpilI7Tj4BunXhrpfSl-MxT_5nnKjFivNut-BRUa14,1121
106
+ synapse_sdk-1.0.0a10.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
107
+ synapse_sdk-1.0.0a10.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
108
+ synapse_sdk-1.0.0a10.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
109
+ synapse_sdk-1.0.0a10.dist-info/RECORD,,
@@ -1,22 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: synapse-sdk
3
- Version: 1.0.0a9
4
- Summary: synapse sdk
5
- Author-email: datamaker <developer@datamaker.io>
6
- License: MIT
7
- Classifier: Programming Language :: Python :: 3
8
- Requires-Python: >=3.11
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE
11
- Requires-Dist: boto3
12
- Requires-Dist: click
13
- Requires-Dist: cookiecutter
14
- Requires-Dist: requests
15
- Requires-Dist: tqdm
16
- Requires-Dist: python-dotenv
17
- Requires-Dist: pyyaml
18
- Requires-Dist: pydantic
19
- Provides-Extra: all
20
- Requires-Dist: ray[all]; extra == "all"
21
-
22
- This is the SDK to develop synapse plugins