synapse-sdk 1.0.0a11__py3-none-any.whl → 2026.1.1b2__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/__init__.py +24 -0
- synapse_sdk/cli/__init__.py +9 -8
- synapse_sdk/cli/agent/__init__.py +25 -0
- synapse_sdk/cli/agent/config.py +104 -0
- synapse_sdk/cli/agent/select.py +197 -0
- synapse_sdk/cli/auth.py +104 -0
- synapse_sdk/cli/main.py +1025 -0
- synapse_sdk/cli/plugin/__init__.py +58 -0
- synapse_sdk/cli/plugin/create.py +566 -0
- synapse_sdk/cli/plugin/job.py +196 -0
- synapse_sdk/cli/plugin/publish.py +322 -0
- synapse_sdk/cli/plugin/run.py +131 -0
- synapse_sdk/cli/plugin/test.py +200 -0
- synapse_sdk/clients/README.md +239 -0
- synapse_sdk/clients/__init__.py +5 -0
- synapse_sdk/clients/_template.py +266 -0
- synapse_sdk/clients/agent/__init__.py +84 -29
- synapse_sdk/clients/agent/async_ray.py +289 -0
- synapse_sdk/clients/agent/container.py +83 -0
- synapse_sdk/clients/agent/plugin.py +101 -0
- synapse_sdk/clients/agent/ray.py +296 -39
- synapse_sdk/clients/backend/__init__.py +152 -12
- synapse_sdk/clients/backend/annotation.py +164 -22
- synapse_sdk/clients/backend/core.py +101 -0
- synapse_sdk/clients/backend/data_collection.py +292 -0
- synapse_sdk/clients/backend/hitl.py +87 -0
- synapse_sdk/clients/backend/integration.py +374 -46
- synapse_sdk/clients/backend/ml.py +134 -22
- synapse_sdk/clients/backend/models.py +247 -0
- synapse_sdk/clients/base.py +538 -59
- synapse_sdk/clients/exceptions.py +35 -7
- synapse_sdk/clients/pipeline/__init__.py +5 -0
- synapse_sdk/clients/pipeline/client.py +636 -0
- synapse_sdk/clients/protocols.py +178 -0
- synapse_sdk/clients/utils.py +86 -8
- synapse_sdk/clients/validation.py +58 -0
- synapse_sdk/enums.py +76 -0
- synapse_sdk/exceptions.py +168 -0
- synapse_sdk/integrations/__init__.py +74 -0
- synapse_sdk/integrations/_base.py +119 -0
- synapse_sdk/integrations/_context.py +53 -0
- synapse_sdk/integrations/ultralytics/__init__.py +78 -0
- synapse_sdk/integrations/ultralytics/_callbacks.py +126 -0
- synapse_sdk/integrations/ultralytics/_patches.py +124 -0
- synapse_sdk/loggers.py +476 -95
- synapse_sdk/mcp/MCP.md +69 -0
- synapse_sdk/mcp/__init__.py +48 -0
- synapse_sdk/mcp/__main__.py +6 -0
- synapse_sdk/mcp/config.py +349 -0
- synapse_sdk/mcp/prompts/__init__.py +4 -0
- synapse_sdk/mcp/resources/__init__.py +4 -0
- synapse_sdk/mcp/server.py +1352 -0
- synapse_sdk/mcp/tools/__init__.py +6 -0
- synapse_sdk/plugins/__init__.py +133 -9
- synapse_sdk/plugins/action.py +229 -0
- synapse_sdk/plugins/actions/__init__.py +82 -0
- synapse_sdk/plugins/actions/dataset/__init__.py +37 -0
- synapse_sdk/plugins/actions/dataset/action.py +471 -0
- synapse_sdk/plugins/actions/export/__init__.py +55 -0
- synapse_sdk/plugins/actions/export/action.py +183 -0
- synapse_sdk/plugins/actions/export/context.py +59 -0
- synapse_sdk/plugins/actions/inference/__init__.py +84 -0
- synapse_sdk/plugins/actions/inference/action.py +285 -0
- synapse_sdk/plugins/actions/inference/context.py +81 -0
- synapse_sdk/plugins/actions/inference/deployment.py +322 -0
- synapse_sdk/plugins/actions/inference/serve.py +252 -0
- synapse_sdk/plugins/actions/train/__init__.py +54 -0
- synapse_sdk/plugins/actions/train/action.py +326 -0
- synapse_sdk/plugins/actions/train/context.py +57 -0
- synapse_sdk/plugins/actions/upload/__init__.py +49 -0
- synapse_sdk/plugins/actions/upload/action.py +165 -0
- synapse_sdk/plugins/actions/upload/context.py +61 -0
- synapse_sdk/plugins/config.py +98 -0
- synapse_sdk/plugins/context/__init__.py +109 -0
- synapse_sdk/plugins/context/env.py +113 -0
- synapse_sdk/plugins/datasets/__init__.py +113 -0
- synapse_sdk/plugins/datasets/converters/__init__.py +76 -0
- synapse_sdk/plugins/datasets/converters/base.py +347 -0
- synapse_sdk/plugins/datasets/converters/yolo/__init__.py +9 -0
- synapse_sdk/plugins/datasets/converters/yolo/from_dm.py +468 -0
- synapse_sdk/plugins/datasets/converters/yolo/to_dm.py +381 -0
- synapse_sdk/plugins/datasets/formats/__init__.py +82 -0
- synapse_sdk/plugins/datasets/formats/dm.py +351 -0
- synapse_sdk/plugins/datasets/formats/yolo.py +240 -0
- synapse_sdk/plugins/decorators.py +83 -0
- synapse_sdk/plugins/discovery.py +790 -0
- synapse_sdk/plugins/docs/ACTION_DEV_GUIDE.md +933 -0
- synapse_sdk/plugins/docs/ARCHITECTURE.md +1225 -0
- synapse_sdk/plugins/docs/LOGGING_SYSTEM.md +683 -0
- synapse_sdk/plugins/docs/OVERVIEW.md +531 -0
- synapse_sdk/plugins/docs/PIPELINE_GUIDE.md +145 -0
- synapse_sdk/plugins/docs/README.md +513 -0
- synapse_sdk/plugins/docs/STEP.md +656 -0
- synapse_sdk/plugins/enums.py +70 -10
- synapse_sdk/plugins/errors.py +92 -0
- synapse_sdk/plugins/executors/__init__.py +43 -0
- synapse_sdk/plugins/executors/local.py +99 -0
- synapse_sdk/plugins/executors/ray/__init__.py +18 -0
- synapse_sdk/plugins/executors/ray/base.py +282 -0
- synapse_sdk/plugins/executors/ray/job.py +298 -0
- synapse_sdk/plugins/executors/ray/jobs_api.py +511 -0
- synapse_sdk/plugins/executors/ray/packaging.py +137 -0
- synapse_sdk/plugins/executors/ray/pipeline.py +792 -0
- synapse_sdk/plugins/executors/ray/task.py +257 -0
- synapse_sdk/plugins/models/__init__.py +26 -0
- synapse_sdk/plugins/models/logger.py +173 -0
- synapse_sdk/plugins/models/pipeline.py +25 -0
- synapse_sdk/plugins/pipelines/__init__.py +81 -0
- synapse_sdk/plugins/pipelines/action_pipeline.py +417 -0
- synapse_sdk/plugins/pipelines/context.py +107 -0
- synapse_sdk/plugins/pipelines/display.py +311 -0
- synapse_sdk/plugins/runner.py +114 -0
- synapse_sdk/plugins/schemas/__init__.py +19 -0
- synapse_sdk/plugins/schemas/results.py +152 -0
- synapse_sdk/plugins/steps/__init__.py +63 -0
- synapse_sdk/plugins/steps/base.py +128 -0
- synapse_sdk/plugins/steps/context.py +90 -0
- synapse_sdk/plugins/steps/orchestrator.py +128 -0
- synapse_sdk/plugins/steps/registry.py +103 -0
- synapse_sdk/plugins/steps/utils/__init__.py +20 -0
- synapse_sdk/plugins/steps/utils/logging.py +85 -0
- synapse_sdk/plugins/steps/utils/timing.py +71 -0
- synapse_sdk/plugins/steps/utils/validation.py +68 -0
- synapse_sdk/plugins/templates/__init__.py +50 -0
- synapse_sdk/plugins/templates/base/.gitignore.j2 +26 -0
- synapse_sdk/plugins/templates/base/.synapseignore.j2 +11 -0
- synapse_sdk/plugins/templates/base/README.md.j2 +26 -0
- synapse_sdk/plugins/templates/base/plugin/__init__.py.j2 +1 -0
- synapse_sdk/plugins/templates/base/pyproject.toml.j2 +14 -0
- synapse_sdk/plugins/templates/base/requirements.txt.j2 +1 -0
- synapse_sdk/plugins/templates/custom/plugin/main.py.j2 +18 -0
- synapse_sdk/plugins/templates/data_validation/plugin/validate.py.j2 +32 -0
- synapse_sdk/plugins/templates/export/plugin/export.py.j2 +36 -0
- synapse_sdk/plugins/templates/neural_net/plugin/inference.py.j2 +36 -0
- synapse_sdk/plugins/templates/neural_net/plugin/train.py.j2 +33 -0
- synapse_sdk/plugins/templates/post_annotation/plugin/post_annotate.py.j2 +32 -0
- synapse_sdk/plugins/templates/pre_annotation/plugin/pre_annotate.py.j2 +32 -0
- synapse_sdk/plugins/templates/smart_tool/plugin/auto_label.py.j2 +44 -0
- synapse_sdk/plugins/templates/upload/plugin/upload.py.j2 +35 -0
- synapse_sdk/plugins/testing/__init__.py +25 -0
- synapse_sdk/plugins/testing/sample_actions.py +98 -0
- synapse_sdk/plugins/types.py +206 -0
- synapse_sdk/plugins/upload.py +595 -64
- synapse_sdk/plugins/utils.py +325 -37
- synapse_sdk/shared/__init__.py +25 -0
- synapse_sdk/utils/__init__.py +1 -0
- synapse_sdk/utils/auth.py +74 -0
- synapse_sdk/utils/file/__init__.py +58 -0
- synapse_sdk/utils/file/archive.py +449 -0
- synapse_sdk/utils/file/checksum.py +167 -0
- synapse_sdk/utils/file/download.py +286 -0
- synapse_sdk/utils/file/io.py +129 -0
- synapse_sdk/utils/file/requirements.py +36 -0
- synapse_sdk/utils/network.py +168 -0
- synapse_sdk/utils/storage/__init__.py +238 -0
- synapse_sdk/utils/storage/config.py +188 -0
- synapse_sdk/utils/storage/errors.py +52 -0
- synapse_sdk/utils/storage/providers/__init__.py +13 -0
- synapse_sdk/utils/storage/providers/base.py +76 -0
- synapse_sdk/utils/storage/providers/gcs.py +168 -0
- synapse_sdk/utils/storage/providers/http.py +250 -0
- synapse_sdk/utils/storage/providers/local.py +126 -0
- synapse_sdk/utils/storage/providers/s3.py +177 -0
- synapse_sdk/utils/storage/providers/sftp.py +208 -0
- synapse_sdk/utils/storage/registry.py +125 -0
- synapse_sdk/utils/websocket.py +99 -0
- synapse_sdk-2026.1.1b2.dist-info/METADATA +715 -0
- synapse_sdk-2026.1.1b2.dist-info/RECORD +172 -0
- {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/WHEEL +1 -1
- synapse_sdk-2026.1.1b2.dist-info/licenses/LICENSE +201 -0
- locale/en/LC_MESSAGES/messages.mo +0 -0
- locale/en/LC_MESSAGES/messages.po +0 -39
- locale/ko/LC_MESSAGES/messages.mo +0 -0
- locale/ko/LC_MESSAGES/messages.po +0 -34
- synapse_sdk/cli/create_plugin.py +0 -10
- synapse_sdk/clients/agent/core.py +0 -7
- synapse_sdk/clients/agent/service.py +0 -15
- synapse_sdk/clients/backend/dataset.py +0 -51
- synapse_sdk/clients/ray/__init__.py +0 -6
- synapse_sdk/clients/ray/core.py +0 -22
- synapse_sdk/clients/ray/serve.py +0 -20
- synapse_sdk/i18n.py +0 -35
- synapse_sdk/plugins/categories/__init__.py +0 -0
- synapse_sdk/plugins/categories/base.py +0 -235
- synapse_sdk/plugins/categories/data_validation/__init__.py +0 -0
- synapse_sdk/plugins/categories/data_validation/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/data_validation/actions/validation.py +0 -10
- synapse_sdk/plugins/categories/data_validation/templates/config.yaml +0 -3
- synapse_sdk/plugins/categories/data_validation/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +0 -5
- synapse_sdk/plugins/categories/decorators.py +0 -13
- synapse_sdk/plugins/categories/export/__init__.py +0 -0
- synapse_sdk/plugins/categories/export/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/export/actions/export.py +0 -10
- synapse_sdk/plugins/categories/import/__init__.py +0 -0
- synapse_sdk/plugins/categories/import/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/import/actions/import.py +0 -10
- synapse_sdk/plugins/categories/neural_net/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/actions/deployment.py +0 -45
- synapse_sdk/plugins/categories/neural_net/actions/inference.py +0 -18
- synapse_sdk/plugins/categories/neural_net/actions/test.py +0 -10
- synapse_sdk/plugins/categories/neural_net/actions/train.py +0 -143
- synapse_sdk/plugins/categories/neural_net/templates/config.yaml +0 -12
- synapse_sdk/plugins/categories/neural_net/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +0 -4
- synapse_sdk/plugins/categories/neural_net/templates/plugin/test.py +0 -2
- synapse_sdk/plugins/categories/neural_net/templates/plugin/train.py +0 -14
- synapse_sdk/plugins/categories/post_annotation/__init__.py +0 -0
- synapse_sdk/plugins/categories/post_annotation/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/post_annotation/actions/post_annotation.py +0 -10
- synapse_sdk/plugins/categories/post_annotation/templates/config.yaml +0 -3
- synapse_sdk/plugins/categories/post_annotation/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/post_annotation/templates/plugin/post_annotation.py +0 -3
- synapse_sdk/plugins/categories/pre_annotation/__init__.py +0 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation.py +0 -10
- synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +0 -3
- synapse_sdk/plugins/categories/pre_annotation/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/pre_annotation/templates/plugin/pre_annotation.py +0 -3
- synapse_sdk/plugins/categories/registry.py +0 -16
- synapse_sdk/plugins/categories/smart_tool/__init__.py +0 -0
- synapse_sdk/plugins/categories/smart_tool/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py +0 -37
- synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +0 -7
- synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py +0 -11
- synapse_sdk/plugins/categories/templates.py +0 -32
- synapse_sdk/plugins/cli/__init__.py +0 -21
- synapse_sdk/plugins/cli/publish.py +0 -37
- synapse_sdk/plugins/cli/run.py +0 -67
- synapse_sdk/plugins/exceptions.py +0 -22
- synapse_sdk/plugins/models.py +0 -121
- synapse_sdk/plugins/templates/cookiecutter.json +0 -11
- synapse_sdk/plugins/templates/hooks/post_gen_project.py +0 -3
- synapse_sdk/plugins/templates/hooks/pre_prompt.py +0 -21
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env +0 -24
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env.dist +0 -24
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.gitignore +0 -27
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.pre-commit-config.yaml +0 -7
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/README.md +0 -5
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/config.yaml +0 -6
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/main.py +0 -4
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/plugin/__init__.py +0 -0
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/pyproject.toml +0 -13
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +0 -1
- synapse_sdk/shared/enums.py +0 -8
- synapse_sdk/utils/debug.py +0 -5
- synapse_sdk/utils/file.py +0 -87
- synapse_sdk/utils/module_loading.py +0 -29
- synapse_sdk/utils/pydantic/__init__.py +0 -0
- synapse_sdk/utils/pydantic/config.py +0 -4
- synapse_sdk/utils/pydantic/errors.py +0 -33
- synapse_sdk/utils/pydantic/validators.py +0 -7
- synapse_sdk/utils/storage.py +0 -91
- synapse_sdk/utils/string.py +0 -11
- synapse_sdk-1.0.0a11.dist-info/LICENSE +0 -21
- synapse_sdk-1.0.0a11.dist-info/METADATA +0 -43
- synapse_sdk-1.0.0a11.dist-info/RECORD +0 -111
- {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/entry_points.txt +0 -0
- {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/top_level.txt +0 -0
synapse_sdk/plugins/enums.py
CHANGED
|
@@ -1,21 +1,81 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from enum import StrEnum
|
|
3
4
|
|
|
4
|
-
class RunMethod(Enum):
|
|
5
|
-
JOB = 'job'
|
|
6
|
-
TASK = 'task'
|
|
7
|
-
RESTAPI = 'restapi'
|
|
8
5
|
|
|
6
|
+
class PluginCategory(StrEnum):
|
|
7
|
+
"""Categories for organizing plugins by functionality."""
|
|
9
8
|
|
|
10
|
-
class PluginCategory(Enum):
|
|
11
9
|
NEURAL_NET = 'neural_net'
|
|
12
10
|
EXPORT = 'export'
|
|
13
|
-
|
|
11
|
+
UPLOAD = 'upload'
|
|
14
12
|
SMART_TOOL = 'smart_tool'
|
|
15
13
|
POST_ANNOTATION = 'post_annotation'
|
|
16
14
|
PRE_ANNOTATION = 'pre_annotation'
|
|
17
15
|
DATA_VALIDATION = 'data_validation'
|
|
16
|
+
CUSTOM = 'custom'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RunMethod(StrEnum):
|
|
20
|
+
"""Execution methods for plugin actions."""
|
|
21
|
+
|
|
22
|
+
JOB = 'job'
|
|
23
|
+
TASK = 'task'
|
|
24
|
+
SERVE = 'serve'
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class PackageManager(StrEnum):
|
|
28
|
+
"""Package managers for plugin dependencies."""
|
|
29
|
+
|
|
30
|
+
PIP = 'pip'
|
|
31
|
+
UV = 'uv'
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class DataType(StrEnum):
|
|
35
|
+
"""Data types handled by plugins."""
|
|
36
|
+
|
|
37
|
+
IMAGE = 'image'
|
|
38
|
+
TEXT = 'text'
|
|
39
|
+
VIDEO = 'video'
|
|
40
|
+
PCD = 'pcd'
|
|
41
|
+
AUDIO = 'audio'
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class AnnotationCategory(StrEnum):
|
|
45
|
+
"""Annotation categories for smart tools."""
|
|
46
|
+
|
|
47
|
+
OBJECT_DETECTION = 'object_detection'
|
|
48
|
+
CLASSIFICATION = 'classification'
|
|
49
|
+
SEGMENTATION = 'segmentation'
|
|
50
|
+
KEYPOINT = 'keypoint'
|
|
51
|
+
TEXT = 'text'
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class AnnotationType(StrEnum):
|
|
55
|
+
"""Annotation types for smart tools."""
|
|
56
|
+
|
|
57
|
+
BBOX = 'bbox'
|
|
58
|
+
POLYGON = 'polygon'
|
|
59
|
+
POINT = 'point'
|
|
60
|
+
LINE = 'line'
|
|
61
|
+
MASK = 'mask'
|
|
62
|
+
LABEL = 'label'
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class SmartToolType(StrEnum):
|
|
66
|
+
"""Smart tool implementation types."""
|
|
67
|
+
|
|
68
|
+
INTERACTIVE = 'interactive'
|
|
69
|
+
AUTOMATIC = 'automatic'
|
|
70
|
+
SEMI_AUTOMATIC = 'semi_automatic'
|
|
71
|
+
|
|
18
72
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
73
|
+
__all__ = [
|
|
74
|
+
'PluginCategory',
|
|
75
|
+
'RunMethod',
|
|
76
|
+
'PackageManager',
|
|
77
|
+
'DataType',
|
|
78
|
+
'AnnotationCategory',
|
|
79
|
+
'AnnotationType',
|
|
80
|
+
'SmartToolType',
|
|
81
|
+
]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class PluginError(Exception):
|
|
7
|
+
"""Base exception for plugin-related errors."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, message: str, details: Any = None):
|
|
10
|
+
self.message = message
|
|
11
|
+
self.details = details
|
|
12
|
+
super().__init__(message)
|
|
13
|
+
|
|
14
|
+
def __repr__(self) -> str:
|
|
15
|
+
return f'{self.__class__.__name__}(message={self.message!r}, details={self.details!r})'
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ValidationError(PluginError):
|
|
19
|
+
"""Raised when plugin parameters fail validation."""
|
|
20
|
+
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ActionNotFoundError(PluginError):
|
|
25
|
+
"""Raised when the requested action doesn't exist in the plugin."""
|
|
26
|
+
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ExecutionError(PluginError):
|
|
31
|
+
"""Raised when action execution fails."""
|
|
32
|
+
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class PluginUploadError(PluginError):
|
|
37
|
+
"""Raised when plugin upload fails.
|
|
38
|
+
|
|
39
|
+
Covers storage upload failures, network errors during upload,
|
|
40
|
+
and other upload-related issues.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ArchiveError(PluginError):
|
|
47
|
+
"""Raised when archive creation fails.
|
|
48
|
+
|
|
49
|
+
Covers ZIP creation failures, git ls-files failures,
|
|
50
|
+
and file permission errors during archiving.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class BuildError(PluginError):
|
|
57
|
+
"""Raised when wheel build fails.
|
|
58
|
+
|
|
59
|
+
Covers wheel build failures, missing pyproject.toml,
|
|
60
|
+
and package manager not found errors.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ChecksumMismatchError(PluginError):
|
|
67
|
+
"""Raised when checksum verification fails.
|
|
68
|
+
|
|
69
|
+
Indicates file integrity issues - the actual checksum
|
|
70
|
+
does not match the expected value.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class PluginRunError(PluginError):
|
|
77
|
+
"""Raised when plugin run fails."""
|
|
78
|
+
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
__all__ = [
|
|
83
|
+
'ActionNotFoundError',
|
|
84
|
+
'ArchiveError',
|
|
85
|
+
'BuildError',
|
|
86
|
+
'ChecksumMismatchError',
|
|
87
|
+
'ExecutionError',
|
|
88
|
+
'PluginError',
|
|
89
|
+
'PluginRunError',
|
|
90
|
+
'PluginUploadError',
|
|
91
|
+
'ValidationError',
|
|
92
|
+
]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from synapse_sdk.plugins.action import BaseAction
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@runtime_checkable
|
|
10
|
+
class ExecutorProtocol(Protocol):
|
|
11
|
+
"""Protocol for plugin action executors.
|
|
12
|
+
|
|
13
|
+
Executors handle the lifecycle of action execution:
|
|
14
|
+
1. Build RuntimeContext (logger, env, job_id)
|
|
15
|
+
2. Instantiate the action with validated params
|
|
16
|
+
3. Call execute() and handle errors
|
|
17
|
+
4. Clean up and return result
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def execute(
|
|
21
|
+
self,
|
|
22
|
+
action_cls: type[BaseAction],
|
|
23
|
+
params: dict[str, Any],
|
|
24
|
+
**kwargs: Any,
|
|
25
|
+
) -> Any:
|
|
26
|
+
"""Execute an action class with parameters.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
action_cls: The BaseAction subclass to execute.
|
|
30
|
+
params: Raw parameters dict (will be validated).
|
|
31
|
+
**kwargs: Executor-specific options.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Action result.
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
ValidationError: If params fail validation.
|
|
38
|
+
ExecutionError: If action execution fails.
|
|
39
|
+
"""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
__all__ = ['ExecutorProtocol']
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from synapse_sdk.loggers import ConsoleLogger
|
|
6
|
+
from synapse_sdk.plugins.action import NoResult, validate_result
|
|
7
|
+
from synapse_sdk.plugins.context import PluginEnvironment, RuntimeContext
|
|
8
|
+
from synapse_sdk.plugins.errors import ExecutionError, ValidationError
|
|
9
|
+
from synapse_sdk.utils.auth import create_backend_client
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from synapse_sdk.plugins.action import BaseAction
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class LocalExecutor:
|
|
16
|
+
"""Execute actions in the current process.
|
|
17
|
+
|
|
18
|
+
Best for development and testing. Uses ConsoleLogger by default.
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
>>> executor = LocalExecutor()
|
|
22
|
+
>>> result = executor.execute(TrainAction, {'epochs': 10})
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
env: PluginEnvironment | dict[str, Any] | None = None,
|
|
28
|
+
job_id: str | None = None,
|
|
29
|
+
) -> None:
|
|
30
|
+
"""Initialize executor.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
env: Environment config. If None, loads from os.environ.
|
|
34
|
+
job_id: Optional job identifier.
|
|
35
|
+
"""
|
|
36
|
+
if env is None:
|
|
37
|
+
self._env = PluginEnvironment.from_environ()
|
|
38
|
+
elif isinstance(env, dict):
|
|
39
|
+
self._env = PluginEnvironment(env)
|
|
40
|
+
else:
|
|
41
|
+
self._env = env
|
|
42
|
+
self._job_id = job_id
|
|
43
|
+
self._client = create_backend_client()
|
|
44
|
+
|
|
45
|
+
def execute(
|
|
46
|
+
self,
|
|
47
|
+
action_cls: type[BaseAction],
|
|
48
|
+
params: dict[str, Any],
|
|
49
|
+
**kwargs: Any,
|
|
50
|
+
) -> Any:
|
|
51
|
+
"""Execute action synchronously in current process.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
action_cls: BaseAction subclass to execute.
|
|
55
|
+
params: Parameters dict to validate and pass.
|
|
56
|
+
**kwargs: Ignored (for protocol compatibility).
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
Action result from execute().
|
|
60
|
+
|
|
61
|
+
Raises:
|
|
62
|
+
ValidationError: If params fail validation.
|
|
63
|
+
ExecutionError: If action raises an exception.
|
|
64
|
+
"""
|
|
65
|
+
del kwargs # Unused, for protocol compatibility
|
|
66
|
+
|
|
67
|
+
# Validate params
|
|
68
|
+
try:
|
|
69
|
+
validated_params = action_cls.params_model.model_validate(params)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
raise ValidationError(f'Parameter validation failed: {e}') from e
|
|
72
|
+
|
|
73
|
+
# Build context
|
|
74
|
+
logger = ConsoleLogger()
|
|
75
|
+
ctx = RuntimeContext(
|
|
76
|
+
logger=logger,
|
|
77
|
+
env=self._env.to_dict(),
|
|
78
|
+
job_id=self._job_id,
|
|
79
|
+
client=self._client,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Instantiate and execute
|
|
83
|
+
action = action_cls(validated_params, ctx)
|
|
84
|
+
try:
|
|
85
|
+
result = action.execute()
|
|
86
|
+
except Exception as e:
|
|
87
|
+
logger.finish()
|
|
88
|
+
raise ExecutionError(f'Action execution failed: {e}') from e
|
|
89
|
+
|
|
90
|
+
# Validate result with warning-only mode
|
|
91
|
+
result_model = getattr(action_cls, 'result_model', NoResult)
|
|
92
|
+
if result_model is not NoResult:
|
|
93
|
+
result = validate_result(result, result_model, logger)
|
|
94
|
+
|
|
95
|
+
logger.finish()
|
|
96
|
+
return result
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
__all__ = ['LocalExecutor']
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from synapse_sdk.plugins.executors.ray.base import BaseRayExecutor, read_requirements
|
|
4
|
+
from synapse_sdk.plugins.executors.ray.job import RayJobExecutor
|
|
5
|
+
from synapse_sdk.plugins.executors.ray.jobs_api import RayJobsApiExecutor
|
|
6
|
+
from synapse_sdk.plugins.executors.ray.pipeline import PipelineDefinition, RayPipelineExecutor
|
|
7
|
+
from synapse_sdk.plugins.executors.ray.task import RayActorExecutor, RayTaskExecutor
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
'BaseRayExecutor',
|
|
11
|
+
'PipelineDefinition',
|
|
12
|
+
'RayActorExecutor',
|
|
13
|
+
'RayJobExecutor',
|
|
14
|
+
'RayJobsApiExecutor',
|
|
15
|
+
'RayPipelineExecutor',
|
|
16
|
+
'RayTaskExecutor',
|
|
17
|
+
'read_requirements',
|
|
18
|
+
]
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"""Base class for Ray executors with shared runtime env logic."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Literal
|
|
7
|
+
|
|
8
|
+
from synapse_sdk.plugins.context import PluginEnvironment
|
|
9
|
+
from synapse_sdk.plugins.enums import PackageManager
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def read_requirements(file_path: str | Path) -> list[str] | None:
|
|
13
|
+
"""Read and parse a requirements.txt file.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
file_path: Path to the requirements.txt file.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
List of requirement strings, or None if file doesn't exist.
|
|
20
|
+
"""
|
|
21
|
+
path = Path(file_path)
|
|
22
|
+
if not path.exists():
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
requirements = []
|
|
26
|
+
for line in path.read_text().splitlines():
|
|
27
|
+
stripped = line.strip()
|
|
28
|
+
if stripped and not stripped.startswith('#'):
|
|
29
|
+
requirements.append(stripped)
|
|
30
|
+
return requirements
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class BaseRayExecutor:
|
|
34
|
+
"""Base class for Ray executors with shared runtime env building logic."""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
env: PluginEnvironment | dict[str, Any] | None = None,
|
|
39
|
+
*,
|
|
40
|
+
runtime_env: dict[str, Any] | None = None,
|
|
41
|
+
working_dir: str | Path | None = None,
|
|
42
|
+
requirements_file: str | Path | None = None,
|
|
43
|
+
package_manager: PackageManager | Literal['pip', 'uv'] = PackageManager.PIP,
|
|
44
|
+
package_manager_options: list[str] | None = None,
|
|
45
|
+
wheels_dir: str = 'wheels',
|
|
46
|
+
ray_address: str = 'auto',
|
|
47
|
+
include_sdk: bool = False,
|
|
48
|
+
) -> None:
|
|
49
|
+
"""Initialize base Ray executor.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
env: Environment config for the action. If None, loads from os.environ.
|
|
53
|
+
runtime_env: Ray runtime environment config.
|
|
54
|
+
working_dir: Plugin working directory.
|
|
55
|
+
requirements_file: Path to requirements.txt.
|
|
56
|
+
package_manager: Package manager to use ('pip' or 'uv').
|
|
57
|
+
package_manager_options: Additional options for the package manager.
|
|
58
|
+
wheels_dir: Directory containing .whl files relative to working_dir.
|
|
59
|
+
ray_address: Ray cluster address (for detecting remote mode).
|
|
60
|
+
include_sdk: If True, bundle local SDK with upload (for development).
|
|
61
|
+
"""
|
|
62
|
+
if env is None:
|
|
63
|
+
self._env = PluginEnvironment.from_environ()
|
|
64
|
+
elif isinstance(env, dict):
|
|
65
|
+
self._env = PluginEnvironment(env)
|
|
66
|
+
else:
|
|
67
|
+
self._env = env
|
|
68
|
+
|
|
69
|
+
self._runtime_env = runtime_env or {}
|
|
70
|
+
self._working_dir = Path(working_dir) if working_dir else None
|
|
71
|
+
self._requirements_file = Path(requirements_file) if requirements_file else None
|
|
72
|
+
self._package_manager = PackageManager(package_manager)
|
|
73
|
+
self._package_manager_options = package_manager_options
|
|
74
|
+
self._wheels_dir = wheels_dir
|
|
75
|
+
self._ray_address = ray_address
|
|
76
|
+
self._include_sdk = include_sdk
|
|
77
|
+
self._gcs_uri: str | None = None # Cached GCS URI
|
|
78
|
+
|
|
79
|
+
def _ray_init(self) -> None:
|
|
80
|
+
"""Initialize Ray connection with SDK bundling if requested."""
|
|
81
|
+
import ray
|
|
82
|
+
|
|
83
|
+
if ray.is_initialized():
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
# Build init kwargs
|
|
87
|
+
init_kwargs: dict[str, Any] = {
|
|
88
|
+
'address': self._ray_address,
|
|
89
|
+
'ignore_reinit_error': True,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# Build runtime_env for init level
|
|
93
|
+
runtime_env: dict[str, Any] = {}
|
|
94
|
+
|
|
95
|
+
# Include SDK at init level (directories only work here, not at actor level)
|
|
96
|
+
if self._include_sdk:
|
|
97
|
+
import synapse_sdk
|
|
98
|
+
|
|
99
|
+
sdk_path = str(Path(synapse_sdk.__file__).parent)
|
|
100
|
+
runtime_env['py_modules'] = [sdk_path]
|
|
101
|
+
|
|
102
|
+
# Include working_dir at init level for local mode
|
|
103
|
+
# (local paths are only supported at ray.init() level, not at actor level)
|
|
104
|
+
if self._working_dir and not self._is_remote_cluster():
|
|
105
|
+
runtime_env['working_dir'] = str(self._working_dir)
|
|
106
|
+
|
|
107
|
+
if runtime_env:
|
|
108
|
+
init_kwargs['runtime_env'] = runtime_env
|
|
109
|
+
|
|
110
|
+
ray.init(**init_kwargs)
|
|
111
|
+
|
|
112
|
+
def _is_remote_cluster(self) -> bool:
|
|
113
|
+
"""Check if connecting to a remote Ray cluster."""
|
|
114
|
+
# Remote if address starts with ray:// protocol
|
|
115
|
+
return self._ray_address.startswith('ray://')
|
|
116
|
+
|
|
117
|
+
def _get_working_dir_uri(self) -> str | None:
|
|
118
|
+
"""Get working directory URI, uploading to GCS for remote clusters."""
|
|
119
|
+
if not self._working_dir:
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
# For remote clusters, upload to GCS
|
|
123
|
+
if self._is_remote_cluster():
|
|
124
|
+
if self._gcs_uri is None:
|
|
125
|
+
from synapse_sdk.plugins.executors.ray.packaging import upload_working_dir_to_gcs
|
|
126
|
+
|
|
127
|
+
self._gcs_uri = upload_working_dir_to_gcs(self._working_dir)
|
|
128
|
+
return self._gcs_uri
|
|
129
|
+
|
|
130
|
+
# Local mode - use path directly
|
|
131
|
+
return str(self._working_dir)
|
|
132
|
+
|
|
133
|
+
def _build_runtime_env(self) -> dict[str, Any]:
|
|
134
|
+
"""Build runtime environment with working_dir, requirements, and env vars."""
|
|
135
|
+
runtime_env = {**self._runtime_env}
|
|
136
|
+
|
|
137
|
+
# Set working_dir if provided (uploads to GCS for remote clusters)
|
|
138
|
+
# Note: Local paths are only supported at ray.init() level, not at actor level
|
|
139
|
+
if self._working_dir and 'working_dir' not in runtime_env:
|
|
140
|
+
if self._is_remote_cluster():
|
|
141
|
+
working_dir_uri = self._get_working_dir_uri()
|
|
142
|
+
if working_dir_uri:
|
|
143
|
+
runtime_env['working_dir'] = working_dir_uri
|
|
144
|
+
# For local mode, working_dir is passed at ray.init() level
|
|
145
|
+
|
|
146
|
+
# Build package manager config with requirements and wheels
|
|
147
|
+
pm_key = str(self._package_manager) # 'pip' or 'uv'
|
|
148
|
+
requirements = self._get_requirements() or []
|
|
149
|
+
wheel_files = self._get_wheel_files()
|
|
150
|
+
|
|
151
|
+
# Check if requirements.txt contains pip args (lines starting with -)
|
|
152
|
+
# If so, use file path instead of package list (Ray only supports pip args via file)
|
|
153
|
+
has_pip_args = any(req.strip().startswith('-') for req in requirements)
|
|
154
|
+
req_file_path = self._get_requirements_file_path()
|
|
155
|
+
|
|
156
|
+
if has_pip_args and req_file_path:
|
|
157
|
+
# Use requirements.txt file path to preserve pip args like --extra-index-url
|
|
158
|
+
# Reference the file relative to working_dir
|
|
159
|
+
runtime_env[pm_key] = 'requirements.txt'
|
|
160
|
+
# Add wheel files separately if any
|
|
161
|
+
if wheel_files:
|
|
162
|
+
# Wheels need to be in packages list, so we need a hybrid approach
|
|
163
|
+
# For now, log a warning - wheels with pip args is not fully supported
|
|
164
|
+
pass
|
|
165
|
+
else:
|
|
166
|
+
# Combine requirements and wheel files as package list
|
|
167
|
+
all_packages = requirements + wheel_files
|
|
168
|
+
|
|
169
|
+
if all_packages:
|
|
170
|
+
# Initialize package manager config
|
|
171
|
+
if pm_key not in runtime_env:
|
|
172
|
+
runtime_env[pm_key] = {'packages': []}
|
|
173
|
+
elif isinstance(runtime_env[pm_key], list):
|
|
174
|
+
runtime_env[pm_key] = {'packages': runtime_env[pm_key]}
|
|
175
|
+
|
|
176
|
+
runtime_env[pm_key].setdefault('packages', [])
|
|
177
|
+
runtime_env[pm_key]['packages'].extend(all_packages)
|
|
178
|
+
|
|
179
|
+
# Apply package manager options (only when using packages list)
|
|
180
|
+
pm_options = self._get_package_manager_options()
|
|
181
|
+
if pm_options and pm_key in runtime_env and isinstance(runtime_env[pm_key], dict):
|
|
182
|
+
for key, value in pm_options.items():
|
|
183
|
+
runtime_env[pm_key][key] = value
|
|
184
|
+
|
|
185
|
+
# Add env vars
|
|
186
|
+
runtime_env.setdefault('env_vars', {})
|
|
187
|
+
runtime_env['env_vars'].update(self._env.to_dict())
|
|
188
|
+
|
|
189
|
+
# Include Synapse credentials for backend client on workers
|
|
190
|
+
from synapse_sdk.utils.auth import ENV_SYNAPSE_ACCESS_TOKEN, ENV_SYNAPSE_HOST, load_credentials
|
|
191
|
+
|
|
192
|
+
host, token = load_credentials()
|
|
193
|
+
if host and ENV_SYNAPSE_HOST not in runtime_env['env_vars']:
|
|
194
|
+
runtime_env['env_vars'][ENV_SYNAPSE_HOST] = host
|
|
195
|
+
if token and ENV_SYNAPSE_ACCESS_TOKEN not in runtime_env['env_vars']:
|
|
196
|
+
runtime_env['env_vars'][ENV_SYNAPSE_ACCESS_TOKEN] = token
|
|
197
|
+
|
|
198
|
+
return runtime_env
|
|
199
|
+
|
|
200
|
+
def _get_package_manager_options(self) -> dict[str, Any]:
|
|
201
|
+
"""Get package manager options with defaults.
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Dict of package manager options.
|
|
205
|
+
"""
|
|
206
|
+
user_options = self._package_manager_options or []
|
|
207
|
+
|
|
208
|
+
if self._package_manager == PackageManager.UV:
|
|
209
|
+
defaults = ['--no-cache']
|
|
210
|
+
options_list = defaults.copy()
|
|
211
|
+
for opt in user_options:
|
|
212
|
+
if opt not in options_list:
|
|
213
|
+
options_list.append(opt)
|
|
214
|
+
return {'uv_pip_install_options': options_list}
|
|
215
|
+
else:
|
|
216
|
+
# pip - use pip_install_options with --upgrade flag
|
|
217
|
+
defaults = ['--upgrade']
|
|
218
|
+
options_list = defaults.copy()
|
|
219
|
+
for opt in user_options:
|
|
220
|
+
if opt not in options_list:
|
|
221
|
+
options_list.append(opt)
|
|
222
|
+
return {'pip_install_options': options_list}
|
|
223
|
+
|
|
224
|
+
def _get_requirements(self) -> list[str] | None:
|
|
225
|
+
"""Get requirements from file.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
List of requirements, or None if no requirements file found.
|
|
229
|
+
"""
|
|
230
|
+
# Explicit requirements file takes priority
|
|
231
|
+
if self._requirements_file:
|
|
232
|
+
return read_requirements(self._requirements_file)
|
|
233
|
+
|
|
234
|
+
# Auto-discover from working_dir
|
|
235
|
+
if self._working_dir:
|
|
236
|
+
req_path = self._working_dir / 'requirements.txt'
|
|
237
|
+
return read_requirements(req_path)
|
|
238
|
+
|
|
239
|
+
return None
|
|
240
|
+
|
|
241
|
+
def _get_requirements_file_path(self) -> Path | None:
|
|
242
|
+
"""Get path to requirements.txt file if it exists.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
Path to requirements.txt, or None if not found.
|
|
246
|
+
"""
|
|
247
|
+
if self._requirements_file and Path(self._requirements_file).exists():
|
|
248
|
+
return Path(self._requirements_file)
|
|
249
|
+
|
|
250
|
+
if self._working_dir:
|
|
251
|
+
req_path = self._working_dir / 'requirements.txt'
|
|
252
|
+
if req_path.exists():
|
|
253
|
+
return req_path
|
|
254
|
+
|
|
255
|
+
return None
|
|
256
|
+
|
|
257
|
+
def _get_wheel_files(self) -> list[str]:
|
|
258
|
+
"""Get wheel file paths for Ray runtime env.
|
|
259
|
+
|
|
260
|
+
Scans the wheels_dir for .whl files and returns them as Ray-compatible
|
|
261
|
+
paths using ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
List of wheel file paths for Ray.
|
|
265
|
+
"""
|
|
266
|
+
if not self._working_dir:
|
|
267
|
+
return []
|
|
268
|
+
|
|
269
|
+
wheels_path = self._working_dir / self._wheels_dir
|
|
270
|
+
if not wheels_path.exists():
|
|
271
|
+
return []
|
|
272
|
+
|
|
273
|
+
wheel_files = []
|
|
274
|
+
for whl in wheels_path.glob('*.whl'):
|
|
275
|
+
# Use Ray's working dir variable for the path
|
|
276
|
+
ray_path = f'${{RAY_RUNTIME_ENV_CREATE_WORKING_DIR}}/{self._wheels_dir}/{whl.name}'
|
|
277
|
+
wheel_files.append(ray_path)
|
|
278
|
+
|
|
279
|
+
return wheel_files
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
__all__ = ['BaseRayExecutor', 'read_requirements']
|