synapse-sdk 1.0.0a13__py3-none-any.whl → 2025.11.7__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 +310 -5
- synapse_sdk/cli/alias/__init__.py +22 -0
- synapse_sdk/cli/alias/create.py +36 -0
- synapse_sdk/cli/alias/dataclass.py +31 -0
- synapse_sdk/cli/alias/default.py +16 -0
- synapse_sdk/cli/alias/delete.py +15 -0
- synapse_sdk/cli/alias/list.py +19 -0
- synapse_sdk/cli/alias/read.py +15 -0
- synapse_sdk/cli/alias/update.py +17 -0
- synapse_sdk/cli/alias/utils.py +61 -0
- synapse_sdk/cli/code_server.py +687 -0
- synapse_sdk/cli/config.py +440 -0
- synapse_sdk/cli/devtools.py +90 -0
- synapse_sdk/cli/plugin/__init__.py +33 -0
- synapse_sdk/cli/{create_plugin.py → plugin/create.py} +2 -2
- synapse_sdk/cli/plugin/publish.py +45 -0
- synapse_sdk/{plugins/cli → cli/plugin}/run.py +12 -5
- synapse_sdk/clients/agent/__init__.py +9 -3
- synapse_sdk/clients/agent/container.py +133 -0
- synapse_sdk/clients/agent/core.py +19 -0
- synapse_sdk/clients/agent/ray.py +298 -9
- synapse_sdk/clients/backend/__init__.py +41 -12
- synapse_sdk/clients/backend/annotation.py +13 -5
- synapse_sdk/clients/backend/core.py +59 -0
- synapse_sdk/clients/backend/data_collection.py +186 -0
- synapse_sdk/clients/backend/hitl.py +17 -0
- synapse_sdk/clients/backend/integration.py +19 -4
- synapse_sdk/clients/backend/ml.py +10 -7
- synapse_sdk/clients/backend/models.py +78 -0
- synapse_sdk/clients/base.py +381 -34
- synapse_sdk/clients/ray/serve.py +2 -0
- synapse_sdk/clients/validators/collections.py +31 -0
- synapse_sdk/devtools/config.py +94 -0
- synapse_sdk/devtools/docs/.gitignore +20 -0
- synapse_sdk/devtools/docs/README.md +41 -0
- synapse_sdk/devtools/docs/blog/2019-05-28-first-blog-post.md +12 -0
- synapse_sdk/devtools/docs/blog/2019-05-29-long-blog-post.md +44 -0
- synapse_sdk/devtools/docs/blog/2021-08-01-mdx-blog-post.mdx +24 -0
- synapse_sdk/devtools/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- synapse_sdk/devtools/docs/blog/2021-08-26-welcome/index.md +29 -0
- synapse_sdk/devtools/docs/blog/authors.yml +25 -0
- synapse_sdk/devtools/docs/blog/tags.yml +19 -0
- synapse_sdk/devtools/docs/docs/api/clients/agent.md +43 -0
- synapse_sdk/devtools/docs/docs/api/clients/annotation-mixin.md +378 -0
- synapse_sdk/devtools/docs/docs/api/clients/backend.md +420 -0
- synapse_sdk/devtools/docs/docs/api/clients/base.md +257 -0
- synapse_sdk/devtools/docs/docs/api/clients/core-mixin.md +477 -0
- synapse_sdk/devtools/docs/docs/api/clients/data-collection-mixin.md +422 -0
- synapse_sdk/devtools/docs/docs/api/clients/hitl-mixin.md +554 -0
- synapse_sdk/devtools/docs/docs/api/clients/index.md +391 -0
- synapse_sdk/devtools/docs/docs/api/clients/integration-mixin.md +571 -0
- synapse_sdk/devtools/docs/docs/api/clients/ml-mixin.md +578 -0
- synapse_sdk/devtools/docs/docs/api/clients/ray.md +342 -0
- synapse_sdk/devtools/docs/docs/api/index.md +52 -0
- synapse_sdk/devtools/docs/docs/api/plugins/categories.md +43 -0
- synapse_sdk/devtools/docs/docs/api/plugins/models.md +114 -0
- synapse_sdk/devtools/docs/docs/api/plugins/utils.md +328 -0
- synapse_sdk/devtools/docs/docs/categories.md +0 -0
- synapse_sdk/devtools/docs/docs/cli-usage.md +280 -0
- synapse_sdk/devtools/docs/docs/concepts/index.md +38 -0
- synapse_sdk/devtools/docs/docs/configuration.md +83 -0
- synapse_sdk/devtools/docs/docs/contributing.md +306 -0
- synapse_sdk/devtools/docs/docs/examples/index.md +29 -0
- synapse_sdk/devtools/docs/docs/faq.md +179 -0
- synapse_sdk/devtools/docs/docs/features/converters/index.md +455 -0
- synapse_sdk/devtools/docs/docs/features/index.md +24 -0
- synapse_sdk/devtools/docs/docs/features/utils/file.md +415 -0
- synapse_sdk/devtools/docs/docs/features/utils/network.md +378 -0
- synapse_sdk/devtools/docs/docs/features/utils/storage.md +57 -0
- synapse_sdk/devtools/docs/docs/features/utils/types.md +51 -0
- synapse_sdk/devtools/docs/docs/installation.md +94 -0
- synapse_sdk/devtools/docs/docs/introduction.md +47 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/neural-net-plugins/train-action-overview.md +814 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-action.md +948 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-overview.md +544 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-template.md +766 -0
- synapse_sdk/devtools/docs/docs/plugins/export-plugins.md +1092 -0
- synapse_sdk/devtools/docs/docs/plugins/plugins.md +852 -0
- synapse_sdk/devtools/docs/docs/quickstart.md +78 -0
- synapse_sdk/devtools/docs/docs/troubleshooting.md +519 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/_category_.json +8 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/congratulations.md +23 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-blog-post.md +34 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-document.md +57 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-page.md +43 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/deploy-your-site.md +31 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/markdown-features.mdx +152 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/_category_.json +7 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/manage-docs-versions.md +55 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/translate-your-site.md +88 -0
- synapse_sdk/devtools/docs/docusaurus.config.ts +148 -0
- synapse_sdk/devtools/docs/i18n/ko/code.json +325 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/agent.md +43 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/annotation-mixin.md +289 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/backend.md +420 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/base.md +257 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/core-mixin.md +417 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/data-collection-mixin.md +356 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/hitl-mixin.md +192 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/index.md +391 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/integration-mixin.md +479 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ml-mixin.md +284 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ray.md +342 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/index.md +52 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/plugins/models.md +114 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/categories.md +0 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/cli-usage.md +280 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/concepts/index.md +38 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/configuration.md +83 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/contributing.md +306 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/examples/index.md +29 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/faq.md +179 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/converters/index.md +30 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/index.md +24 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/file.md +415 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/network.md +378 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/storage.md +60 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/types.md +51 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/installation.md +94 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/introduction.md +47 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/neural-net-plugins/train-action-overview.md +815 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-action.md +948 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-overview.md +544 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-template.md +766 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/export-plugins.md +1092 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/plugins.md +117 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/quickstart.md +78 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/troubleshooting.md +519 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current.json +34 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/footer.json +42 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/navbar.json +18 -0
- synapse_sdk/devtools/docs/package-lock.json +18784 -0
- synapse_sdk/devtools/docs/package.json +48 -0
- synapse_sdk/devtools/docs/sidebars.ts +122 -0
- synapse_sdk/devtools/docs/src/components/HomepageFeatures/index.tsx +71 -0
- synapse_sdk/devtools/docs/src/components/HomepageFeatures/styles.module.css +11 -0
- synapse_sdk/devtools/docs/src/css/custom.css +30 -0
- synapse_sdk/devtools/docs/src/pages/index.module.css +23 -0
- synapse_sdk/devtools/docs/src/pages/index.tsx +21 -0
- synapse_sdk/devtools/docs/src/pages/markdown-page.md +7 -0
- synapse_sdk/devtools/docs/static/.nojekyll +0 -0
- synapse_sdk/devtools/docs/static/img/docusaurus-social-card.jpg +0 -0
- synapse_sdk/devtools/docs/static/img/docusaurus.png +0 -0
- synapse_sdk/devtools/docs/static/img/favicon.ico +0 -0
- synapse_sdk/devtools/docs/static/img/logo.png +0 -0
- synapse_sdk/devtools/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
- synapse_sdk/devtools/docs/static/img/undraw_docusaurus_react.svg +170 -0
- synapse_sdk/devtools/docs/static/img/undraw_docusaurus_tree.svg +40 -0
- synapse_sdk/devtools/docs/tsconfig.json +8 -0
- synapse_sdk/devtools/server.py +41 -0
- synapse_sdk/devtools/streamlit_app/__init__.py +5 -0
- synapse_sdk/devtools/streamlit_app/app.py +128 -0
- synapse_sdk/devtools/streamlit_app/services/__init__.py +11 -0
- synapse_sdk/devtools/streamlit_app/services/job_service.py +233 -0
- synapse_sdk/devtools/streamlit_app/services/plugin_service.py +236 -0
- synapse_sdk/devtools/streamlit_app/services/serve_service.py +95 -0
- synapse_sdk/devtools/streamlit_app/ui/__init__.py +15 -0
- synapse_sdk/devtools/streamlit_app/ui/config_tab.py +76 -0
- synapse_sdk/devtools/streamlit_app/ui/deployment_tab.py +66 -0
- synapse_sdk/devtools/streamlit_app/ui/http_tab.py +125 -0
- synapse_sdk/devtools/streamlit_app/ui/jobs_tab.py +573 -0
- synapse_sdk/devtools/streamlit_app/ui/serve_tab.py +346 -0
- synapse_sdk/devtools/streamlit_app/ui/status_bar.py +118 -0
- synapse_sdk/devtools/streamlit_app/utils/__init__.py +40 -0
- synapse_sdk/devtools/streamlit_app/utils/json_viewer.py +197 -0
- synapse_sdk/devtools/streamlit_app/utils/log_formatter.py +38 -0
- synapse_sdk/devtools/streamlit_app/utils/styles.py +241 -0
- synapse_sdk/devtools/streamlit_app/utils/ui_components.py +289 -0
- synapse_sdk/devtools/streamlit_app.py +10 -0
- synapse_sdk/loggers.py +74 -9
- synapse_sdk/plugins/README.md +1340 -0
- synapse_sdk/plugins/__init__.py +0 -13
- synapse_sdk/plugins/categories/base.py +145 -30
- synapse_sdk/plugins/categories/data_validation/actions/validation.py +72 -0
- synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +33 -5
- synapse_sdk/plugins/categories/export/actions/__init__.py +3 -0
- synapse_sdk/plugins/categories/export/actions/export/__init__.py +28 -0
- synapse_sdk/plugins/categories/export/actions/export/action.py +165 -0
- synapse_sdk/plugins/categories/export/actions/export/enums.py +113 -0
- synapse_sdk/plugins/categories/export/actions/export/exceptions.py +53 -0
- synapse_sdk/plugins/categories/export/actions/export/models.py +74 -0
- synapse_sdk/plugins/categories/export/actions/export/run.py +195 -0
- synapse_sdk/plugins/categories/export/actions/export/utils.py +187 -0
- synapse_sdk/plugins/categories/export/templates/config.yaml +21 -0
- synapse_sdk/plugins/categories/export/templates/plugin/__init__.py +390 -0
- synapse_sdk/plugins/categories/export/templates/plugin/export.py +160 -0
- synapse_sdk/plugins/categories/neural_net/actions/deployment.py +29 -14
- synapse_sdk/plugins/categories/neural_net/actions/inference.py +13 -1
- synapse_sdk/plugins/categories/neural_net/actions/train.py +1084 -38
- synapse_sdk/plugins/categories/neural_net/actions/tune.py +534 -0
- synapse_sdk/plugins/categories/neural_net/base/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/base/inference.py +37 -0
- synapse_sdk/plugins/categories/neural_net/templates/config.yaml +30 -5
- synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +26 -10
- synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +4 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation/__init__.py +3 -0
- synapse_sdk/plugins/categories/{export/actions/export.py → pre_annotation/actions/pre_annotation/action.py} +4 -4
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/__init__.py +28 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/action.py +145 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/enums.py +269 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/exceptions.py +14 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/factory.py +76 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/models.py +97 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/orchestrator.py +250 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/run.py +64 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/__init__.py +17 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/annotation.py +287 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/base.py +170 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/extraction.py +83 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/metrics.py +87 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/preprocessor.py +127 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/validation.py +143 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task.py +966 -0
- synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +19 -0
- synapse_sdk/plugins/categories/pre_annotation/templates/plugin/to_task.py +40 -0
- synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +5 -2
- synapse_sdk/plugins/categories/upload/__init__.py +0 -0
- synapse_sdk/plugins/categories/upload/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/upload/actions/upload/__init__.py +19 -0
- synapse_sdk/plugins/categories/upload/actions/upload/action.py +232 -0
- synapse_sdk/plugins/categories/upload/actions/upload/context.py +185 -0
- synapse_sdk/plugins/categories/upload/actions/upload/enums.py +471 -0
- synapse_sdk/plugins/categories/upload/actions/upload/exceptions.py +36 -0
- synapse_sdk/plugins/categories/upload/actions/upload/factory.py +138 -0
- synapse_sdk/plugins/categories/upload/actions/upload/models.py +203 -0
- synapse_sdk/plugins/categories/upload/actions/upload/orchestrator.py +183 -0
- synapse_sdk/plugins/categories/upload/actions/upload/registry.py +113 -0
- synapse_sdk/plugins/categories/upload/actions/upload/run.py +179 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/base.py +107 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/cleanup.py +62 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/collection.py +63 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/generate.py +84 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/initialize.py +82 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/metadata.py +235 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/organize.py +203 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/upload.py +97 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/validate.py +71 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/base.py +82 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/batch.py +39 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/single.py +29 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/flat.py +258 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/recursive.py +281 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/excel.py +174 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/none.py +16 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/sync.py +84 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/default.py +60 -0
- synapse_sdk/plugins/categories/upload/actions/upload/utils.py +250 -0
- synapse_sdk/plugins/categories/upload/templates/README.md +470 -0
- synapse_sdk/plugins/categories/upload/templates/config.yaml +33 -0
- synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py +294 -0
- synapse_sdk/plugins/categories/upload/templates/plugin/upload.py +102 -0
- synapse_sdk/plugins/enums.py +3 -1
- synapse_sdk/plugins/models.py +140 -16
- synapse_sdk/plugins/templates/plugin-config-schema.json +406 -0
- synapse_sdk/plugins/templates/schema.json +491 -0
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/config.yaml +1 -0
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +1 -1
- synapse_sdk/plugins/utils/__init__.py +46 -0
- synapse_sdk/plugins/utils/actions.py +119 -0
- synapse_sdk/plugins/utils/config.py +203 -0
- synapse_sdk/plugins/utils/legacy.py +95 -0
- synapse_sdk/plugins/utils/ray_gcs.py +66 -0
- synapse_sdk/plugins/utils/registry.py +58 -0
- synapse_sdk/shared/__init__.py +25 -0
- synapse_sdk/shared/enums.py +93 -0
- synapse_sdk/types.py +19 -0
- synapse_sdk/utils/converters/__init__.py +240 -0
- synapse_sdk/utils/converters/coco/__init__.py +0 -0
- synapse_sdk/utils/converters/coco/from_dm.py +322 -0
- synapse_sdk/utils/converters/coco/to_dm.py +215 -0
- synapse_sdk/utils/converters/dm/__init__.py +56 -0
- synapse_sdk/utils/converters/dm/from_v1.py +627 -0
- synapse_sdk/utils/converters/dm/to_v1.py +367 -0
- synapse_sdk/utils/converters/pascal/__init__.py +0 -0
- synapse_sdk/utils/converters/pascal/from_dm.py +244 -0
- synapse_sdk/utils/converters/pascal/to_dm.py +214 -0
- synapse_sdk/utils/converters/yolo/__init__.py +0 -0
- synapse_sdk/utils/converters/yolo/from_dm.py +384 -0
- synapse_sdk/utils/converters/yolo/to_dm.py +267 -0
- synapse_sdk/utils/dataset.py +46 -0
- synapse_sdk/utils/encryption.py +158 -0
- synapse_sdk/utils/file/__init__.py +39 -0
- synapse_sdk/utils/file/archive.py +32 -0
- synapse_sdk/utils/file/checksum.py +56 -0
- synapse_sdk/utils/file/chunking.py +31 -0
- synapse_sdk/utils/file/download.py +385 -0
- synapse_sdk/utils/file/encoding.py +40 -0
- synapse_sdk/utils/file/io.py +22 -0
- synapse_sdk/utils/file/video/__init__.py +29 -0
- synapse_sdk/utils/file/video/transcode.py +307 -0
- synapse_sdk/utils/file.py.backup +301 -0
- synapse_sdk/utils/http.py +138 -0
- synapse_sdk/utils/network.py +309 -0
- synapse_sdk/utils/storage/__init__.py +72 -0
- synapse_sdk/utils/storage/providers/__init__.py +183 -0
- synapse_sdk/utils/storage/providers/file_system.py +134 -0
- synapse_sdk/utils/storage/providers/gcp.py +13 -0
- synapse_sdk/utils/storage/providers/http.py +190 -0
- synapse_sdk/utils/storage/providers/s3.py +91 -0
- synapse_sdk/utils/storage/providers/sftp.py +47 -0
- synapse_sdk/utils/storage/registry.py +17 -0
- synapse_sdk-2025.11.7.dist-info/METADATA +122 -0
- synapse_sdk-2025.11.7.dist-info/RECORD +386 -0
- {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info}/WHEEL +1 -1
- synapse_sdk/clients/backend/dataset.py +0 -51
- synapse_sdk/plugins/categories/import/actions/import.py +0 -10
- synapse_sdk/plugins/cli/__init__.py +0 -21
- synapse_sdk/plugins/cli/publish.py +0 -37
- 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/main.py +0 -4
- synapse_sdk/plugins/utils.py +0 -50
- synapse_sdk/utils/file.py +0 -87
- synapse_sdk/utils/storage.py +0 -91
- synapse_sdk-1.0.0a13.dist-info/METADATA +0 -43
- synapse_sdk-1.0.0a13.dist-info/RECORD +0 -111
- /synapse_sdk/{plugins/categories/import → clients/validators}/__init__.py +0 -0
- /synapse_sdk/{plugins/categories/import/actions → devtools}/__init__.py +0 -0
- {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info}/entry_points.txt +0 -0
- {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info/licenses}/LICENSE +0 -0
- {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info}/top_level.txt +0 -0
synapse_sdk/clients/base.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import
|
|
2
|
+
import threading
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
import requests
|
|
6
|
+
from requests.adapters import HTTPAdapter
|
|
7
|
+
from urllib3.util.retry import Retry
|
|
6
8
|
|
|
7
9
|
from synapse_sdk.clients.exceptions import ClientError
|
|
8
10
|
from synapse_sdk.utils.file import files_url_to_path_from_objs
|
|
@@ -11,44 +13,147 @@ from synapse_sdk.utils.file import files_url_to_path_from_objs
|
|
|
11
13
|
class BaseClient:
|
|
12
14
|
name = None
|
|
13
15
|
base_url = None
|
|
16
|
+
page_size = 100
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
# TODO: Ensure that the Upload plugin's threading behavior works correctly within tasks and that progress management works properly.
|
|
19
|
+
def __init__(self, base_url, timeout=None):
|
|
20
|
+
self.base_url = base_url.rstrip('/')
|
|
21
|
+
# Set reasonable default timeouts for better UX
|
|
22
|
+
self.timeout = timeout or {
|
|
23
|
+
'connect': 5, # Connection timeout: 5 seconds
|
|
24
|
+
'read': 15, # Read timeout: 15 seconds
|
|
25
|
+
}
|
|
19
26
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
# Use thread-local storage for sessions to ensure thread safety
|
|
28
|
+
# Each thread gets its own requests.Session instance
|
|
29
|
+
self._thread_local = threading.local()
|
|
30
|
+
|
|
31
|
+
# Store retry configuration for creating sessions
|
|
32
|
+
self._retry_config = {
|
|
33
|
+
'total': 3, # Total retries
|
|
34
|
+
'backoff_factor': 1, # Backoff factor between retries
|
|
35
|
+
'status_forcelist': [502, 503, 504], # HTTP status codes to retry
|
|
36
|
+
'allowed_methods': ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
def _create_session(self):
|
|
40
|
+
"""Create a new requests session with retry strategy.
|
|
41
|
+
|
|
42
|
+
This is called once per thread to create a thread-local session.
|
|
43
|
+
"""
|
|
44
|
+
session = requests.Session()
|
|
45
|
+
|
|
46
|
+
# Configure retry strategy for transient failures
|
|
47
|
+
retry_strategy = Retry(**self._retry_config)
|
|
48
|
+
|
|
49
|
+
adapter = HTTPAdapter(max_retries=retry_strategy)
|
|
50
|
+
session.mount('http://', adapter)
|
|
51
|
+
session.mount('https://', adapter)
|
|
52
|
+
|
|
53
|
+
return session
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def requests_session(self):
|
|
57
|
+
"""Get the thread-local requests session.
|
|
58
|
+
|
|
59
|
+
Returns a thread-local session instance, creating one if it doesn't exist
|
|
60
|
+
for the current thread. This ensures thread safety when using the client
|
|
61
|
+
in multi-threaded environments (e.g., async uploads).
|
|
62
|
+
"""
|
|
63
|
+
if not hasattr(self._thread_local, 'session'):
|
|
64
|
+
self._thread_local.session = self._create_session()
|
|
65
|
+
return self._thread_local.session
|
|
66
|
+
|
|
67
|
+
def _get_url(self, path, trailing_slash=False):
|
|
68
|
+
"""Construct a full URL from a path.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
path (str): URL path or full URL
|
|
72
|
+
trailing_slash (bool): Whether to ensure URL ends with trailing slash
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
str: Complete URL
|
|
76
|
+
"""
|
|
77
|
+
# Use the path as-is if it's already a full URL, otherwise construct from base_url and path
|
|
78
|
+
url = path if path.startswith(('http://', 'https://')) else f'{self.base_url}/{path.lstrip("/")}'
|
|
79
|
+
|
|
80
|
+
# Add trailing slash if requested and not present
|
|
81
|
+
if trailing_slash and not url.endswith('/'):
|
|
82
|
+
url += '/'
|
|
83
|
+
|
|
84
|
+
return url
|
|
24
85
|
|
|
25
86
|
def _get_headers(self):
|
|
26
87
|
return {}
|
|
27
88
|
|
|
28
|
-
def _request(self, method, path, **kwargs):
|
|
89
|
+
def _request(self, method: str, path: str, **kwargs) -> dict | str:
|
|
90
|
+
"""Request handler for all HTTP methods.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
method (str): HTTP method to use.
|
|
94
|
+
path (str): URL path to request.
|
|
95
|
+
**kwargs: Additional keyword arguments to pass to the request.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
dict | str: JSON response or text response.
|
|
99
|
+
"""
|
|
29
100
|
url = self._get_url(path)
|
|
30
101
|
headers = self._get_headers()
|
|
102
|
+
headers.update(kwargs.pop('headers', {}))
|
|
103
|
+
|
|
104
|
+
# Set timeout if not provided in kwargs
|
|
105
|
+
if 'timeout' not in kwargs:
|
|
106
|
+
kwargs['timeout'] = (self.timeout['connect'], self.timeout['read'])
|
|
107
|
+
|
|
108
|
+
# List to store opened files to close after request
|
|
109
|
+
opened_files = []
|
|
31
110
|
|
|
32
111
|
if method in ['post', 'put', 'patch']:
|
|
112
|
+
# If files are included in the request, open them as binary files
|
|
33
113
|
if kwargs.get('files') is not None:
|
|
34
114
|
for name, file in kwargs['files'].items():
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
115
|
+
# Handle both string and Path object cases
|
|
116
|
+
if isinstance(file, str):
|
|
117
|
+
file = Path(file)
|
|
118
|
+
if isinstance(file, Path):
|
|
119
|
+
opened_file = file.open(mode='rb')
|
|
120
|
+
kwargs['files'][name] = (file.name, opened_file)
|
|
121
|
+
opened_files.append(opened_file)
|
|
122
|
+
if 'data' in kwargs:
|
|
123
|
+
for name, value in kwargs['data'].items():
|
|
124
|
+
if isinstance(value, dict):
|
|
125
|
+
kwargs['data'][name] = json.dumps(value)
|
|
39
126
|
else:
|
|
40
127
|
headers['Content-Type'] = 'application/json'
|
|
41
128
|
if 'data' in kwargs:
|
|
42
129
|
kwargs['data'] = json.dumps(kwargs['data'])
|
|
43
130
|
|
|
44
131
|
try:
|
|
132
|
+
# Send request
|
|
45
133
|
response = getattr(self.requests_session, method)(url, headers=headers, **kwargs)
|
|
46
134
|
if not response.ok:
|
|
47
135
|
raise ClientError(
|
|
48
136
|
response.status_code, response.json() if response.status_code == 400 else response.reason
|
|
49
137
|
)
|
|
50
|
-
except requests.
|
|
51
|
-
raise ClientError(408, f'{self.name}
|
|
138
|
+
except requests.exceptions.ConnectTimeout:
|
|
139
|
+
raise ClientError(408, f'{self.name} connection timeout (>{self.timeout["connect"]}s)')
|
|
140
|
+
except requests.exceptions.ReadTimeout:
|
|
141
|
+
raise ClientError(408, f'{self.name} read timeout (>{self.timeout["read"]}s)')
|
|
142
|
+
except requests.exceptions.ConnectionError as e:
|
|
143
|
+
# More specific error handling for different connection issues
|
|
144
|
+
if 'Name or service not known' in str(e) or 'nodename nor servname provided' in str(e):
|
|
145
|
+
raise ClientError(503, f'{self.name} host unreachable')
|
|
146
|
+
elif 'Connection refused' in str(e):
|
|
147
|
+
raise ClientError(503, f'{self.name} connection refused')
|
|
148
|
+
else:
|
|
149
|
+
raise ClientError(503, f'{self.name} connection error: {str(e)[:100]}')
|
|
150
|
+
except requests.exceptions.RequestException as e:
|
|
151
|
+
# Catch all other requests exceptions
|
|
152
|
+
raise ClientError(500, f'{self.name} request failed: {str(e)[:100]}')
|
|
153
|
+
|
|
154
|
+
# Close all opened files
|
|
155
|
+
for opened_file in opened_files:
|
|
156
|
+
opened_file.close()
|
|
52
157
|
|
|
53
158
|
return self._post_response(response)
|
|
54
159
|
|
|
@@ -58,39 +163,281 @@ class BaseClient:
|
|
|
58
163
|
except ValueError:
|
|
59
164
|
return response.text
|
|
60
165
|
|
|
61
|
-
def _get(self, path, url_conversion=None, **kwargs):
|
|
166
|
+
def _get(self, path, url_conversion=None, response_model=None, **kwargs):
|
|
167
|
+
"""Perform a GET request and optionally convert response to a pydantic model.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
path (str): URL path to request.
|
|
171
|
+
url_conversion (dict, optional): Configuration for URL to path conversion.
|
|
172
|
+
request_model (pydantic.BaseModel, optional): Pydantic model to validate the request.
|
|
173
|
+
response_model (pydantic.BaseModel, optional): Pydantic model to validate the response.
|
|
174
|
+
**kwargs: Additional keyword arguments to pass to the request.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
The response data, optionally converted to a pydantic model.
|
|
178
|
+
"""
|
|
62
179
|
response = self._request('get', path, **kwargs)
|
|
180
|
+
|
|
63
181
|
if url_conversion:
|
|
64
182
|
if url_conversion['is_list']:
|
|
65
|
-
files_url_to_path_from_objs(response['results'], **url_conversion)
|
|
183
|
+
files_url_to_path_from_objs(response['results'], **url_conversion, is_async=True)
|
|
66
184
|
else:
|
|
67
185
|
files_url_to_path_from_objs(response, **url_conversion)
|
|
186
|
+
|
|
187
|
+
if response_model:
|
|
188
|
+
return self._validate_response_with_pydantic_model(response, response_model)
|
|
189
|
+
|
|
68
190
|
return response
|
|
69
191
|
|
|
70
|
-
def _post(self, path, **kwargs):
|
|
71
|
-
|
|
192
|
+
def _post(self, path, request_model=None, response_model=None, **kwargs):
|
|
193
|
+
"""Perform a POST request and optionally convert response to a pydantic model.
|
|
72
194
|
|
|
73
|
-
|
|
74
|
-
|
|
195
|
+
Args:
|
|
196
|
+
path (str): URL path to request.
|
|
197
|
+
request_model (pydantic.BaseModel, optional): Pydantic model to validate the request.
|
|
198
|
+
response_model (pydantic.BaseModel, optional): Pydantic model to validate the response.
|
|
199
|
+
**kwargs: Additional keyword arguments to pass to the request.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
The response data, optionally converted to a pydantic model.
|
|
203
|
+
"""
|
|
204
|
+
if kwargs.get('data') and request_model:
|
|
205
|
+
kwargs['data'] = self._validate_request_body_with_pydantic_model(kwargs['data'], request_model)
|
|
206
|
+
response = self._request('post', path, **kwargs)
|
|
207
|
+
if response_model:
|
|
208
|
+
return self._validate_response_with_pydantic_model(response, response_model)
|
|
209
|
+
else:
|
|
210
|
+
return response
|
|
211
|
+
|
|
212
|
+
def _put(self, path, request_model=None, response_model=None, **kwargs):
|
|
213
|
+
"""Perform a PUT request to the specified path.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
path (str): The URL path for the request.
|
|
217
|
+
request_model (Optional[Type[BaseModel]]): A Pydantic model class to validate the request body against.
|
|
218
|
+
response_model (Optional[Type[BaseModel]]): A Pydantic model class to validate and parse the response.
|
|
219
|
+
**kwargs: Additional arguments to pass to the request method.
|
|
220
|
+
- data: The request body to be sent. If provided along with request_model, it will be validated.
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
Union[dict, BaseModel]:
|
|
224
|
+
If response_model is provided, returns an instance of that model populated with the response data.
|
|
225
|
+
"""
|
|
226
|
+
if kwargs.get('data') and request_model:
|
|
227
|
+
kwargs['data'] = self._validate_request_body_with_pydantic_model(kwargs['data'], request_model)
|
|
228
|
+
response = self._request('put', path, **kwargs)
|
|
229
|
+
if response_model:
|
|
230
|
+
return self._validate_response_with_pydantic_model(response, response_model)
|
|
231
|
+
else:
|
|
232
|
+
return response
|
|
75
233
|
|
|
76
|
-
def _patch(self, path, **kwargs):
|
|
77
|
-
|
|
234
|
+
def _patch(self, path, request_model=None, response_model=None, **kwargs):
|
|
235
|
+
"""Perform a PATCH HTTP request to the specified path.
|
|
78
236
|
|
|
79
|
-
|
|
80
|
-
|
|
237
|
+
Args:
|
|
238
|
+
path (str): The API endpoint path to make the request to.
|
|
239
|
+
request_model (Optional[Type[BaseModel]]): A Pydantic model class used to validate the request body.
|
|
240
|
+
response_model (Optional[Type[BaseModel]]): A Pydantic model class used to validate and parse the response.
|
|
241
|
+
**kwargs: Additional keyword arguments to pass to the request method.
|
|
242
|
+
- data: The request body data. If provided along with request_model, it will be validated.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
Union[dict, BaseModel]: If response_model is provided, returns an instance of that model.
|
|
246
|
+
Otherwise, returns the raw response data.
|
|
247
|
+
"""
|
|
248
|
+
if kwargs.get('data') and request_model:
|
|
249
|
+
kwargs['data'] = self._validate_request_body_with_pydantic_model(kwargs['data'], request_model)
|
|
250
|
+
response = self._request('patch', path, **kwargs)
|
|
251
|
+
if response_model:
|
|
252
|
+
return self._validate_response_with_pydantic_model(response, response_model)
|
|
253
|
+
else:
|
|
254
|
+
return response
|
|
255
|
+
|
|
256
|
+
def _delete(self, path, request_model=None, response_model=None, **kwargs):
|
|
257
|
+
"""Performs a DELETE request to the specified path.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
path (str): The API endpoint path to send the DELETE request to.
|
|
261
|
+
request_model (Optional[Type[BaseModel]]): Pydantic model to validate the request data against.
|
|
262
|
+
response_model (Optional[Type[BaseModel]]): Pydantic model to validate and convert the response data.
|
|
263
|
+
**kwargs: Additional keyword arguments passed to the request method.
|
|
264
|
+
- data: Request payload to send. Will be validated against request_model if both are provided.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
Union[dict, BaseModel]: If response_model is provided, returns an instance of that model.
|
|
268
|
+
Otherwise, returns the raw response data as a dictionary.
|
|
269
|
+
"""
|
|
270
|
+
if kwargs.get('data') and request_model:
|
|
271
|
+
kwargs['data'] = self._validate_request_body_with_pydantic_model(kwargs['data'], request_model)
|
|
272
|
+
response = self._request('delete', path, **kwargs)
|
|
273
|
+
if response_model:
|
|
274
|
+
return self._validate_response_with_pydantic_model(response, response_model)
|
|
275
|
+
else:
|
|
276
|
+
return response
|
|
277
|
+
|
|
278
|
+
def _list(self, path, url_conversion=None, list_all=False, params=None, **kwargs):
|
|
279
|
+
"""List resources from a paginated API endpoint.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
path (str): URL path to request.
|
|
283
|
+
url_conversion (dict, optional): Configuration for URL to path conversion.
|
|
284
|
+
Used to convert file URLs to local paths in the response.
|
|
285
|
+
Example: {'files_fields': ['files'], 'is_list': True}
|
|
286
|
+
This will convert file URLs in the 'files' field of each result.
|
|
287
|
+
list_all (bool): If True, returns a generator yielding all results across all pages.
|
|
288
|
+
Default is False, which returns only the first page.
|
|
289
|
+
params (dict, optional): Query parameters to pass to the request.
|
|
290
|
+
Example: {'status': 'active', 'project': 123}
|
|
291
|
+
**kwargs: Additional keyword arguments to pass to the request.
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
If list_all is False: dict response from the API containing:
|
|
295
|
+
- 'results': list of items on the current page
|
|
296
|
+
- 'count': total number of items
|
|
297
|
+
- 'next': URL to the next page (or None)
|
|
298
|
+
- 'previous': URL to the previous page (or None)
|
|
299
|
+
If list_all is True: tuple of (generator, count) where:
|
|
300
|
+
- generator: yields individual items from all pages
|
|
301
|
+
- count: total number of items across all pages
|
|
302
|
+
|
|
303
|
+
Examples:
|
|
304
|
+
Get first page only:
|
|
305
|
+
>>> response = client._list('api/tasks/')
|
|
306
|
+
>>> tasks = response['results'] # List of tasks on first page
|
|
307
|
+
>>> total_count = response['count'] # Total number of tasks
|
|
308
|
+
|
|
309
|
+
Get all results across all pages:
|
|
310
|
+
>>> generator, count = client._list('api/tasks/', list_all=True)
|
|
311
|
+
>>> all_tasks = list(generator) # Fetches all pages
|
|
312
|
+
|
|
313
|
+
With filters and url_conversion:
|
|
314
|
+
>>> url_conversion = {'files_fields': ['files'], 'is_list': True}
|
|
315
|
+
>>> params = {'status': 'active'}
|
|
316
|
+
>>> generator, count = client._list(
|
|
317
|
+
... 'api/data_units/',
|
|
318
|
+
... url_conversion=url_conversion,
|
|
319
|
+
... list_all=True,
|
|
320
|
+
... params=params
|
|
321
|
+
... )
|
|
322
|
+
>>> active_units = list(generator) # All active units with file URLs converted
|
|
323
|
+
"""
|
|
324
|
+
if params is None:
|
|
325
|
+
params = {}
|
|
81
326
|
|
|
82
|
-
def _list(self, path, url_conversion=None, list_all=False, **kwargs):
|
|
83
|
-
response = self._get(path, url_conversion, **kwargs)
|
|
84
327
|
if list_all:
|
|
85
|
-
|
|
328
|
+
response = self._get(path, params=params, **kwargs)
|
|
329
|
+
return self._list_all(path, url_conversion, params=params, **kwargs), response.get('count')
|
|
86
330
|
else:
|
|
331
|
+
response = self._get(path, params=params, **kwargs)
|
|
87
332
|
return response
|
|
88
333
|
|
|
89
|
-
def _list_all(self, path, url_conversion=None, **kwargs):
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
334
|
+
def _list_all(self, path, url_conversion=None, params=None, **kwargs):
|
|
335
|
+
"""Generator that yields all results from a paginated API endpoint.
|
|
336
|
+
|
|
337
|
+
This method handles pagination automatically by following the 'next' URLs
|
|
338
|
+
returned by the API until all pages have been fetched. It uses an iterative
|
|
339
|
+
approach (while loop) instead of recursion to avoid stack overflow with
|
|
340
|
+
deep pagination.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
path (str): Initial URL path to request.
|
|
344
|
+
url_conversion (dict, optional): Configuration for URL to path conversion.
|
|
345
|
+
Applied to all pages. Common structure:
|
|
346
|
+
- 'files_fields': List of field names containing file URLs
|
|
347
|
+
- 'is_list': Whether the response is a list (True for paginated results)
|
|
348
|
+
Example: {'files_fields': ['files', 'images'], 'is_list': True}
|
|
349
|
+
params (dict, optional): Query parameters for the first request only.
|
|
350
|
+
Subsequent requests use the 'next' URL which already includes
|
|
351
|
+
all necessary parameters. If 'page_size' is not specified,
|
|
352
|
+
it defaults to self.page_size (100).
|
|
353
|
+
Example: {'status': 'active', 'page_size': 50}
|
|
354
|
+
**kwargs: Additional keyword arguments to pass to requests.
|
|
355
|
+
Example: timeout, headers, etc.
|
|
356
|
+
|
|
357
|
+
Yields:
|
|
358
|
+
dict: Individual result items from all pages. Each item is yielded
|
|
359
|
+
as soon as it's fetched, allowing for memory-efficient processing
|
|
360
|
+
of large datasets.
|
|
361
|
+
|
|
362
|
+
Examples:
|
|
363
|
+
Basic usage - fetch all tasks:
|
|
364
|
+
>>> for task in client._list_all('api/tasks/'):
|
|
365
|
+
... process_task(task)
|
|
366
|
+
|
|
367
|
+
With filters:
|
|
368
|
+
>>> params = {'status': 'pending', 'priority': 'high'}
|
|
369
|
+
>>> for task in client._list_all('api/tasks/', params=params):
|
|
370
|
+
... print(task['id'])
|
|
371
|
+
|
|
372
|
+
With url_conversion for file fields:
|
|
373
|
+
>>> url_conversion = {'files_fields': ['files'], 'is_list': True}
|
|
374
|
+
>>> for data_unit in client._list_all('api/data_units/', url_conversion):
|
|
375
|
+
... # File URLs in 'files' field are converted to local paths
|
|
376
|
+
... print(data_unit['files'])
|
|
377
|
+
|
|
378
|
+
Collecting results into a list:
|
|
379
|
+
>>> all_tasks = list(client._list_all('api/tasks/'))
|
|
380
|
+
>>> print(f"Total tasks: {len(all_tasks)}")
|
|
381
|
+
|
|
382
|
+
Note:
|
|
383
|
+
- This is a generator function, so results are fetched lazily as you iterate
|
|
384
|
+
- The first page is fetched with the provided params
|
|
385
|
+
- Subsequent pages use the 'next' URL from the API response
|
|
386
|
+
- No duplicate page_size parameters are added to subsequent requests
|
|
387
|
+
- Memory efficient: processes one item at a time rather than loading all at once
|
|
388
|
+
"""
|
|
389
|
+
if params is None:
|
|
390
|
+
params = {}
|
|
391
|
+
|
|
392
|
+
# Set page_size only if not already specified by user
|
|
393
|
+
request_params = params.copy()
|
|
394
|
+
if 'page_size' not in request_params:
|
|
395
|
+
request_params['page_size'] = self.page_size
|
|
396
|
+
|
|
397
|
+
next_url = path
|
|
398
|
+
is_first_request = True
|
|
399
|
+
|
|
400
|
+
while next_url:
|
|
401
|
+
# First request uses params, subsequent requests use next URL directly
|
|
402
|
+
if is_first_request:
|
|
403
|
+
response = self._get(next_url, url_conversion, params=request_params, **kwargs)
|
|
404
|
+
is_first_request = False
|
|
405
|
+
else:
|
|
406
|
+
# next URL already contains all necessary query parameters
|
|
407
|
+
response = self._get(next_url, url_conversion, **kwargs)
|
|
408
|
+
|
|
409
|
+
yield from response['results']
|
|
410
|
+
next_url = response.get('next')
|
|
94
411
|
|
|
95
412
|
def exists(self, api, *args, **kwargs):
|
|
96
413
|
return getattr(self, api)(*args, **kwargs)['count'] > 0
|
|
414
|
+
|
|
415
|
+
def _validate_response_with_pydantic_model(self, response, pydantic_model):
|
|
416
|
+
"""Validate a response with a pydantic model."""
|
|
417
|
+
# Check if model is a pydantic model (has the __pydantic_model__ attribute)
|
|
418
|
+
if (
|
|
419
|
+
hasattr(pydantic_model, '__pydantic_model__')
|
|
420
|
+
or hasattr(pydantic_model, 'model_validate')
|
|
421
|
+
or hasattr(pydantic_model, 'parse_obj')
|
|
422
|
+
):
|
|
423
|
+
pydantic_model.model_validate(response)
|
|
424
|
+
return response
|
|
425
|
+
else:
|
|
426
|
+
# Not a pydantic model
|
|
427
|
+
raise TypeError('The provided model is not a pydantic model')
|
|
428
|
+
|
|
429
|
+
def _validate_request_body_with_pydantic_model(self, request_body, pydantic_model):
|
|
430
|
+
"""Validate a request body with a pydantic model."""
|
|
431
|
+
# Check if model is a pydantic model (has the __pydantic_model__ attribute)
|
|
432
|
+
if (
|
|
433
|
+
hasattr(pydantic_model, '__pydantic_model__')
|
|
434
|
+
or hasattr(pydantic_model, 'model_validate')
|
|
435
|
+
or hasattr(pydantic_model, 'parse_obj')
|
|
436
|
+
):
|
|
437
|
+
# Validate the request body and convert to model instance
|
|
438
|
+
model_instance = pydantic_model.model_validate(request_body)
|
|
439
|
+
# Convert model to dict and remove None values
|
|
440
|
+
return {k: v for k, v in model_instance.model_dump().items() if v is not None}
|
|
441
|
+
else:
|
|
442
|
+
# Not a pydantic model
|
|
443
|
+
raise TypeError('The provided model is not a pydantic model')
|
synapse_sdk/clients/ray/serve.py
CHANGED
|
@@ -8,6 +8,7 @@ class ServeClientMixin(BaseClient):
|
|
|
8
8
|
response = self._get(path, params=params)
|
|
9
9
|
for key, item in response['applications'].items():
|
|
10
10
|
response['applications'][key]['deployments'] = list(item['deployments'].values())
|
|
11
|
+
response['applications'][key]['route_prefix'] = item['route_prefix']
|
|
11
12
|
return list(response['applications'].values())
|
|
12
13
|
|
|
13
14
|
def get_serve_application(self, pk, params=None):
|
|
@@ -15,6 +16,7 @@ class ServeClientMixin(BaseClient):
|
|
|
15
16
|
response = self._get(path, params=params)
|
|
16
17
|
try:
|
|
17
18
|
response['applications'][pk]['deployments'] = list(response['applications'][pk]['deployments'].values())
|
|
19
|
+
response['applications'][pk]['route_prefix'] = response['applications'][pk]['route_prefix']
|
|
18
20
|
return response['applications'][pk]
|
|
19
21
|
except KeyError:
|
|
20
22
|
raise ClientError(404, 'Serve Application Not Found')
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class FileSpecificationValidator:
|
|
2
|
+
"""File specification validator class for synapse backend collection.
|
|
3
|
+
|
|
4
|
+
Args:
|
|
5
|
+
file_spec_template (list):
|
|
6
|
+
* List of dictionaries containing file specification template
|
|
7
|
+
* This is from synapse-backend file specification data.
|
|
8
|
+
organized_files (list): List of dictionaries containing organized files.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, file_spec_template, organized_files):
|
|
12
|
+
self.file_spec_template = file_spec_template
|
|
13
|
+
self.organized_files = organized_files
|
|
14
|
+
|
|
15
|
+
def validate(self):
|
|
16
|
+
"""Validate the file specification template with organized files.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
bool: True if the file specification template is valid, False otherwise.
|
|
20
|
+
"""
|
|
21
|
+
for spec in self.file_spec_template:
|
|
22
|
+
spec_name = spec['name']
|
|
23
|
+
is_required = spec['is_required']
|
|
24
|
+
|
|
25
|
+
for file_group in self.organized_files:
|
|
26
|
+
files = file_group['files']
|
|
27
|
+
if is_required and spec_name not in files:
|
|
28
|
+
return False
|
|
29
|
+
if spec_name in files and not files[spec_name]:
|
|
30
|
+
return False
|
|
31
|
+
return True
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Dict, Optional
|
|
4
|
+
|
|
5
|
+
CONFIG_DIR = Path.home() / '.config' / 'synapse'
|
|
6
|
+
DEVTOOLS_CONFIG_FILE = CONFIG_DIR / 'devtools.json'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def ensure_config_dir():
|
|
10
|
+
"""Ensure the config directory exists"""
|
|
11
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def load_devtools_config() -> Dict:
|
|
15
|
+
"""Load devtools configuration from file"""
|
|
16
|
+
ensure_config_dir()
|
|
17
|
+
|
|
18
|
+
# Handle both Path and string types for testing
|
|
19
|
+
config_file = Path(DEVTOOLS_CONFIG_FILE) if isinstance(DEVTOOLS_CONFIG_FILE, str) else DEVTOOLS_CONFIG_FILE
|
|
20
|
+
|
|
21
|
+
if not config_file.exists():
|
|
22
|
+
return {}
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
with open(config_file, 'r') as f:
|
|
26
|
+
return json.load(f)
|
|
27
|
+
except (json.JSONDecodeError, IOError):
|
|
28
|
+
return {}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def save_devtools_config(config: Dict):
|
|
32
|
+
"""Save devtools configuration to file"""
|
|
33
|
+
ensure_config_dir()
|
|
34
|
+
|
|
35
|
+
# Handle both Path and string types for testing
|
|
36
|
+
config_file = Path(DEVTOOLS_CONFIG_FILE) if isinstance(DEVTOOLS_CONFIG_FILE, str) else DEVTOOLS_CONFIG_FILE
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
with open(config_file, 'w') as f:
|
|
40
|
+
json.dump(config, f, indent=2)
|
|
41
|
+
except IOError:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_backend_config() -> Optional[Dict]:
|
|
46
|
+
"""Get backend configuration (host and token)"""
|
|
47
|
+
config = load_devtools_config()
|
|
48
|
+
backend = config.get('backend', {})
|
|
49
|
+
|
|
50
|
+
host = backend.get('host')
|
|
51
|
+
token = backend.get('token')
|
|
52
|
+
|
|
53
|
+
if host and token:
|
|
54
|
+
return {'host': host, 'token': token}
|
|
55
|
+
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def set_backend_config(host: str, token: str):
|
|
60
|
+
"""Set backend configuration"""
|
|
61
|
+
config = load_devtools_config()
|
|
62
|
+
config['backend'] = {'host': host, 'token': token}
|
|
63
|
+
save_devtools_config(config)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def clear_backend_config():
|
|
67
|
+
"""Clear backend configuration"""
|
|
68
|
+
config = load_devtools_config()
|
|
69
|
+
if 'backend' in config:
|
|
70
|
+
del config['backend']
|
|
71
|
+
save_devtools_config(config)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_server_config() -> Dict:
|
|
75
|
+
"""Get server configuration (host and port)"""
|
|
76
|
+
config = load_devtools_config()
|
|
77
|
+
server = config.get('server', {})
|
|
78
|
+
|
|
79
|
+
return {'host': server.get('host', '0.0.0.0'), 'port': server.get('port', 8080)}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def set_server_config(host: str = None, port: int = None):
|
|
83
|
+
"""Set server configuration"""
|
|
84
|
+
config = load_devtools_config()
|
|
85
|
+
|
|
86
|
+
if 'server' not in config:
|
|
87
|
+
config['server'] = {}
|
|
88
|
+
|
|
89
|
+
if host is not None:
|
|
90
|
+
config['server']['host'] = host
|
|
91
|
+
if port is not None:
|
|
92
|
+
config['server']['port'] = port
|
|
93
|
+
|
|
94
|
+
save_devtools_config(config)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
/node_modules
|
|
3
|
+
|
|
4
|
+
# Production
|
|
5
|
+
/build
|
|
6
|
+
|
|
7
|
+
# Generated files
|
|
8
|
+
.docusaurus
|
|
9
|
+
.cache-loader
|
|
10
|
+
|
|
11
|
+
# Misc
|
|
12
|
+
.DS_Store
|
|
13
|
+
.env.local
|
|
14
|
+
.env.development.local
|
|
15
|
+
.env.test.local
|
|
16
|
+
.env.production.local
|
|
17
|
+
|
|
18
|
+
npm-debug.log*
|
|
19
|
+
yarn-debug.log*
|
|
20
|
+
yarn-error.log*
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Website
|
|
2
|
+
|
|
3
|
+
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
yarn
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Local Development
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
yarn start
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
|
18
|
+
|
|
19
|
+
## Build
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
|
26
|
+
|
|
27
|
+
## Deployment
|
|
28
|
+
|
|
29
|
+
Using SSH:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
USE_SSH=true yarn deploy
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Not using SSH:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
GIT_USER=<Your GitHub username> yarn deploy
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|