synapse-sdk 1.0.0a65__tar.gz → 1.0.0a67__tar.gz
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-1.0.0a65 → synapse_sdk-1.0.0a67}/.gitignore +3 -1
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/PKG-INFO +1 -1
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/converters/__init__.py +135 -72
- synapse_sdk-1.0.0a67/synapse_sdk/utils/converters/coco/to_dm.py +113 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/storage/__init__.py +30 -3
- synapse_sdk-1.0.0a67/synapse_sdk/utils/storage/providers/http.py +190 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/storage/registry.py +4 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk.egg-info/PKG-INFO +1 -1
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk.egg-info/SOURCES.txt +4 -1
- synapse_sdk-1.0.0a67/tests/utils/storage/test_provider_selection.py +225 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/.coverage +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/.github/workflows/lint.yml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/.github/workflows/pypi-publish.yml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/.pre-commit-config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/LICENSE +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/README.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/clients/agent.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/clients/backend.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/clients/base.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/index.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/plugins/categories.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/plugins/models.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/plugins/utils.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/utils/file.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/utils/storage.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/api/utils/types.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/categories.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/changelog.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/concepts/index.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/configuration.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/contributing.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/examples/index.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/faq.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/i18n/ko/code.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/i18n/ko/docusaurus-plugin-content-docs/current/introduction.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/i18n/ko/docusaurus-plugin-content-docs/current.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/i18n/ko/docusaurus-theme-classic/footer.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/i18n/ko/docusaurus-theme-classic/navbar.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/installation.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/introduction.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/quickstart.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/troubleshooting.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-basics/_category_.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-basics/congratulations.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-basics/create-a-blog-post.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-basics/create-a-document.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-basics/create-a-page.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-basics/deploy-your-site.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-basics/markdown-features.mdx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-extras/_category_.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-extras/img/localeDropdown.png +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-extras/manage-docs-versions.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/docs/tutorial-extras/translate-your-site.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/locale/en/LC_MESSAGES/messages.mo +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/locale/en/LC_MESSAGES/messages.po +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/locale/ko/LC_MESSAGES/messages.mo +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/locale/ko/LC_MESSAGES/messages.po +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/pyproject.toml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/requirements.test.txt +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/requirements.txt +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/setup.cfg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/alias/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/alias/create.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/alias/dataclass.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/alias/default.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/alias/delete.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/alias/list.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/alias/read.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/alias/update.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/alias/utils.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/config.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/devtools.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/plugin/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/plugin/create.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/plugin/publish.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/cli/plugin/run.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/agent/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/agent/core.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/agent/ray.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/agent/service.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/backend/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/backend/annotation.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/backend/core.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/backend/data_collection.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/backend/hitl.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/backend/integration.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/backend/ml.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/backend/models.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/base.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/exceptions.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/ray/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/ray/core.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/ray/serve.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/utils.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/validators/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/clients/validators/collections.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/config.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/.gitignore +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/README.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/blog/2019-05-28-first-blog-post.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/blog/2019-05-29-long-blog-post.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/blog/2021-08-01-mdx-blog-post.mdx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/blog/2021-08-26-welcome/index.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/blog/authors.yml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/blog/tags.yml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/docusaurus.config.ts +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/package-lock.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/package.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/sidebars.ts +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/src/components/HomepageFeatures/index.tsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/src/components/HomepageFeatures/styles.module.css +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/src/css/custom.css +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/src/pages/index.module.css +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/src/pages/index.tsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/src/pages/markdown-page.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/static/.nojekyll +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/static/img/docusaurus-social-card.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/static/img/docusaurus.png +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/static/img/favicon.ico +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/static/img/logo.png +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/static/img/undraw_docusaurus_mountain.svg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/static/img/undraw_docusaurus_react.svg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/static/img/undraw_docusaurus_tree.svg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/docs/tsconfig.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/models.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/server.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/utils.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/.gitignore +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/README.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/dist/index.html +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/index.html +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/jsconfig.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/package-lock.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/package.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/pnpm-lock.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/App.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/App.module.css +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/assets/favicon.ico +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/components/Breadcrumbs.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/components/Layout.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/components/LogViewer.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/components/MessageViewer.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/components/NavigationSidebar.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/components/ServerStatusBar.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/components/icons.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/index.css +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/index.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/logo.svg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/router.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/utils/api.js +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/views/ApplicationDetailView.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/views/ApplicationsView.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/views/HomeView.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/views/JobDetailView.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/src/views/PluginView.jsx +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/devtools/web/vite.config.js +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/i18n.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/loggers.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/base.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/data_validation/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/data_validation/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/data_validation/actions/validation.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/data_validation/templates/config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/data_validation/templates/plugin/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/decorators.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/export/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/export/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/export/actions/export.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/export/enums.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/export/templates/config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/export/templates/plugin/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/export/templates/plugin/export.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/actions/deployment.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/actions/gradio.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/actions/inference.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/actions/test.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/actions/train.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/actions/tune.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/base/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/base/inference.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/templates/config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/templates/plugin/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/templates/plugin/test.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/neural_net/templates/plugin/train.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/post_annotation/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/post_annotation/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/post_annotation/actions/post_annotation.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/post_annotation/templates/config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/post_annotation/templates/plugin/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/post_annotation/templates/plugin/post_annotation.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/pre_annotation/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/pre_annotation/actions/to_task.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/pre_annotation/templates/plugin/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/pre_annotation/templates/plugin/pre_annotation.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/pre_annotation/templates/plugin/to_task.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/registry.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/smart_tool/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/smart_tool/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/templates.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/upload/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/upload/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/upload/actions/upload.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/upload/templates/config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/categories/upload/templates/plugin/upload.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/enums.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/exceptions.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/models.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/cookiecutter.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/hooks/post_gen_project.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/hooks/pre_prompt.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/plugin-config-schema.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/schema.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.gitignore +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.pre-commit-config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/README.md +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/config.yaml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/plugin/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/pyproject.toml +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/upload.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/plugins/utils.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/shared/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/shared/enums.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/types.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/converters/coco/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/converters/coco/from_dm.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/dataset.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/debug.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/file.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/http.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/module_loading.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/network.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/pydantic/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/pydantic/config.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/pydantic/errors.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/pydantic/validators.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/storage/providers/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/storage/providers/gcp.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/storage/providers/s3.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/storage/providers/sftp.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk/utils/string.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk.egg-info/dependency_links.txt +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk.egg-info/entry_points.txt +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk.egg-info/requires.txt +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/synapse_sdk.egg-info/top_level.txt +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/clients/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/clients/test_backend_models.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/clients/test_base_client.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/clients/test_collection_validators.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/conftest.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/loggers/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/loggers/test_base_logger.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/test_cli.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/test_cli_integration.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/__init__,py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/conftest.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/__init__.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/test/json/dm_1.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/test/json/dm_2.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/test/json/dm_3.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/test/original_files/dm_1.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/test/original_files/dm_2.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/test/original_files/dm_3.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/train/json/dm_4.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/train/json/dm_5.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/train/json/dm_6.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/train/json/dm_7.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/train/original_files/dm_4.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/train/original_files/dm_5.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/train/original_files/dm_6.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/train/original_files/dm_7.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/valid/json/dm_8.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/valid/json/dm_9.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/valid/original_files/dm_8.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/categorized/valid/original_files/dm_9.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/not_categorized/json/dm_1.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/not_categorized/json/dm_2.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/not_categorized/json/dm_3.json +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/not_categorized/original_files/dm_1.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/not_categorized/original_files/dm_2.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/data_types/image/not_categorized/original_files/dm_3.jpg +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/fixtures/dm_schema.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/converters/test_coco_from_dm.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/tests/utils/test_debug.py +0 -0
- {synapse_sdk-1.0.0a65 → synapse_sdk-1.0.0a67}/uv.lock +0 -0
|
@@ -1,7 +1,72 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import os
|
|
3
|
+
import shutil
|
|
4
|
+
import uuid
|
|
2
5
|
|
|
3
6
|
|
|
4
|
-
class
|
|
7
|
+
class BaseConverter:
|
|
8
|
+
"""Base class for shared logic between converters."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, root_dir: str, is_categorized_dataset: bool = False) -> None:
|
|
11
|
+
self.root_dir: str = root_dir
|
|
12
|
+
self.is_categorized_dataset: bool = is_categorized_dataset
|
|
13
|
+
self.converted_data = None
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def ensure_dir(path: str) -> None:
|
|
17
|
+
"""Ensure that the directory exists, creating it if necessary."""
|
|
18
|
+
if not os.path.exists(path):
|
|
19
|
+
os.makedirs(path)
|
|
20
|
+
|
|
21
|
+
def _validate_required_dirs(self, dirs):
|
|
22
|
+
"""Validate that all required directories exist."""
|
|
23
|
+
for name, path in dirs.items():
|
|
24
|
+
if not os.path.exists(path):
|
|
25
|
+
raise FileNotFoundError(f'[ERROR] Required directory "{name}" does not exist at {path}')
|
|
26
|
+
|
|
27
|
+
def _validate_optional_dirs(self, dirs):
|
|
28
|
+
"""Validate optional directories and return those that exist."""
|
|
29
|
+
existing_dirs = {}
|
|
30
|
+
for name, path in dirs.items():
|
|
31
|
+
if os.path.exists(path):
|
|
32
|
+
existing_dirs[name] = path
|
|
33
|
+
else:
|
|
34
|
+
print(f'[WARNING] Optional directory "{name}" does not exist. Skipping.')
|
|
35
|
+
return existing_dirs
|
|
36
|
+
|
|
37
|
+
def _validate_splits(self, required_splits, optional_splits=[]):
|
|
38
|
+
"""Validate required and optional splits in the dataset."""
|
|
39
|
+
splits = {}
|
|
40
|
+
|
|
41
|
+
if self.is_categorized_dataset:
|
|
42
|
+
required_dirs = {split: os.path.join(self.root_dir, split) for split in required_splits}
|
|
43
|
+
self._validate_required_dirs(required_dirs)
|
|
44
|
+
splits.update(required_dirs)
|
|
45
|
+
|
|
46
|
+
optional_dirs = {split: os.path.join(self.root_dir, split) for split in optional_splits}
|
|
47
|
+
splits.update(self._validate_optional_dirs(optional_dirs))
|
|
48
|
+
else:
|
|
49
|
+
required_dirs = {
|
|
50
|
+
'json': os.path.join(self.root_dir, 'json'),
|
|
51
|
+
'original_file': os.path.join(self.root_dir, 'original_file'),
|
|
52
|
+
}
|
|
53
|
+
self._validate_required_dirs(required_dirs)
|
|
54
|
+
splits['root'] = self.root_dir
|
|
55
|
+
|
|
56
|
+
return splits
|
|
57
|
+
|
|
58
|
+
def _set_directories(self, split=None):
|
|
59
|
+
"""Set `self.json_dir` and `self.original_file_dir` based on the dataset split."""
|
|
60
|
+
if split:
|
|
61
|
+
split_dir = os.path.join(self.root_dir, split)
|
|
62
|
+
self.json_dir = os.path.join(split_dir, 'json')
|
|
63
|
+
self.original_file_dir = os.path.join(split_dir, 'original_file')
|
|
64
|
+
else:
|
|
65
|
+
self.json_dir = os.path.join(self.root_dir, 'json')
|
|
66
|
+
self.original_file_dir = os.path.join(self.root_dir, 'original_file')
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class FromDMConverter(BaseConverter):
|
|
5
70
|
"""Base class for converting data from DM format to a specific format.
|
|
6
71
|
|
|
7
72
|
Attrs:
|
|
@@ -42,10 +107,8 @@ class FromDMConverter:
|
|
|
42
107
|
"""
|
|
43
108
|
|
|
44
109
|
def __init__(self, root_dir: str, is_categorized_dataset: bool = False) -> None:
|
|
45
|
-
|
|
46
|
-
self.is_categorized_dataset: bool = is_categorized_dataset
|
|
110
|
+
super().__init__(root_dir, is_categorized_dataset)
|
|
47
111
|
self.version: str = '1.0'
|
|
48
|
-
self.converted_data = None
|
|
49
112
|
|
|
50
113
|
def convert(self):
|
|
51
114
|
"""Convert DM format to a specific format.
|
|
@@ -61,85 +124,85 @@ class FromDMConverter:
|
|
|
61
124
|
# Automatically call convert() if converted_data is not set
|
|
62
125
|
self.converted_data = self.convert()
|
|
63
126
|
|
|
64
|
-
@staticmethod
|
|
65
|
-
def ensure_dir(path: str) -> None:
|
|
66
|
-
"""Ensure that the directory exists, creating it if necessary."""
|
|
67
|
-
if not os.path.exists(path):
|
|
68
|
-
os.makedirs(path)
|
|
69
127
|
|
|
70
|
-
|
|
71
|
-
|
|
128
|
+
class ToDMConverter(BaseConverter):
|
|
129
|
+
"""Base class for converting data to DM format.
|
|
72
130
|
|
|
73
|
-
|
|
74
|
-
|
|
131
|
+
Attrs:
|
|
132
|
+
root_dir (str): Root directory containing data.
|
|
133
|
+
is_categorized_dataset (bool): Whether to handle train, test, valid splits.
|
|
134
|
+
converted_data: Holds the converted data after calling `convert()`.
|
|
75
135
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
raise FileNotFoundError(f'[ERROR] Required directory "{name}" does not exist at {path}')
|
|
136
|
+
Usage:
|
|
137
|
+
1. Subclass this base class and implement the `convert()` method.
|
|
138
|
+
2. Instantiate the converter with the required arguments.
|
|
139
|
+
3. Call `convert()` to perform the in-memory conversion and obtain the result as a dict or list of dicts.
|
|
140
|
+
4. Call `save_to_folder(output_dir)` to save the converted data and optionally copy original files.
|
|
82
141
|
|
|
83
|
-
|
|
84
|
-
|
|
142
|
+
Args:
|
|
143
|
+
root_dir (str): Path to the root directory containing data.
|
|
144
|
+
- If `is_categorized_dataset=True`, the directory should contain subdirectories for
|
|
145
|
+
`train`, `valid`, and optionally `test`.
|
|
146
|
+
- Each subdirectory should contain `annotations.json` and the corresponding image files.
|
|
147
|
+
- `train` and `valid` are required, while `test` is optional.
|
|
148
|
+
is_categorized_dataset (bool): Whether to handle train, test, valid splits.
|
|
85
149
|
|
|
86
|
-
|
|
87
|
-
|
|
150
|
+
Returns:
|
|
151
|
+
- convert(): Returns the converted data as a Python dict or a dictionary with keys for each split.
|
|
152
|
+
- save_to_folder(): Saves the converted data and optionally copies original files
|
|
153
|
+
to the specified output directory.
|
|
88
154
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if os.path.exists(path):
|
|
95
|
-
existing_dirs[name] = path
|
|
96
|
-
else:
|
|
97
|
-
print(f'[WARNING] Optional directory "{name}" does not exist. Skipping.')
|
|
98
|
-
return existing_dirs
|
|
155
|
+
Example usage:
|
|
156
|
+
# Dataset with splits
|
|
157
|
+
converter = MyCustomToDMConverter(root_dir='/path/to/data', is_categorized_dataset=True)
|
|
158
|
+
converted = converter.convert() # Returns a dict with keys for `train`, `valid`, and optionally `test`
|
|
159
|
+
converter.save_to_folder('/my/target/output') # Writes files/folders to output location
|
|
99
160
|
|
|
100
|
-
|
|
101
|
-
|
|
161
|
+
# Dataset without splits
|
|
162
|
+
converter = MyCustomToDMConverter(root_dir='/path/to/data', is_categorized_dataset=False)
|
|
163
|
+
converted = converter.convert() # Returns a dict or a list, depending on the implementation
|
|
164
|
+
converter.save_to_folder('/my/target/output') # Writes files/folders to output location
|
|
165
|
+
"""
|
|
102
166
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
optional_splits (list): List of optional split names (e.g., ['test']).
|
|
167
|
+
def convert(self):
|
|
168
|
+
"""Convert data to DM format.
|
|
106
169
|
|
|
107
|
-
|
|
108
|
-
dict: A dictionary with split names as keys and their corresponding directories as values.
|
|
170
|
+
This method should be implemented by subclasses to perform the actual conversion.
|
|
109
171
|
"""
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if self.is_categorized_dataset:
|
|
113
|
-
# Validate required splits
|
|
114
|
-
required_dirs = {split: os.path.join(self.root_dir, split) for split in required_splits}
|
|
115
|
-
self._validate_required_dirs(required_dirs)
|
|
116
|
-
splits.update(required_dirs)
|
|
117
|
-
|
|
118
|
-
# Validate optional splits
|
|
119
|
-
optional_dirs = {split: os.path.join(self.root_dir, split) for split in optional_splits}
|
|
120
|
-
splits.update(self._validate_optional_dirs(optional_dirs))
|
|
121
|
-
else:
|
|
122
|
-
# Validate `json` and `original_file` folders for non-split datasets
|
|
123
|
-
required_dirs = {
|
|
124
|
-
'json': os.path.join(self.root_dir, 'json'),
|
|
125
|
-
'original_file': os.path.join(self.root_dir, 'original_file'),
|
|
126
|
-
}
|
|
127
|
-
self._validate_required_dirs(required_dirs)
|
|
128
|
-
splits['root'] = self.root_dir
|
|
172
|
+
raise NotImplementedError
|
|
129
173
|
|
|
130
|
-
|
|
174
|
+
def _generate_unique_id(self):
|
|
175
|
+
"""Generate a unique 10-character UUID."""
|
|
176
|
+
return uuid.uuid4().hex[:10]
|
|
131
177
|
|
|
132
|
-
def
|
|
133
|
-
"""
|
|
178
|
+
def save_to_folder(self, output_dir: str) -> None:
|
|
179
|
+
"""Save converted DM schema data to the specified folder."""
|
|
180
|
+
self.ensure_dir(output_dir)
|
|
181
|
+
if self.converted_data is None:
|
|
182
|
+
self.converted_data = self.convert()
|
|
134
183
|
|
|
135
|
-
|
|
136
|
-
split
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
184
|
+
if self.is_categorized_dataset:
|
|
185
|
+
for split, img_dict in self.converted_data.items():
|
|
186
|
+
split_dir = os.path.join(output_dir, split)
|
|
187
|
+
json_dir = os.path.join(split_dir, 'json')
|
|
188
|
+
original_file_dir = os.path.join(split_dir, 'original_file')
|
|
189
|
+
self.ensure_dir(json_dir)
|
|
190
|
+
self.ensure_dir(original_file_dir)
|
|
191
|
+
for img_filename, (dm_json, img_src_path) in img_dict.items():
|
|
192
|
+
json_filename = os.path.splitext(img_filename)[0] + '.json'
|
|
193
|
+
with open(os.path.join(json_dir, json_filename), 'w', encoding='utf-8') as jf:
|
|
194
|
+
json.dump(dm_json, jf, indent=2, ensure_ascii=False)
|
|
195
|
+
if img_src_path and os.path.exists(img_src_path):
|
|
196
|
+
shutil.copy(img_src_path, os.path.join(original_file_dir, img_filename))
|
|
143
197
|
else:
|
|
144
|
-
|
|
145
|
-
|
|
198
|
+
json_dir = os.path.join(output_dir, 'json')
|
|
199
|
+
original_file_dir = os.path.join(output_dir, 'original_file')
|
|
200
|
+
self.ensure_dir(json_dir)
|
|
201
|
+
self.ensure_dir(original_file_dir)
|
|
202
|
+
for img_filename, (dm_json, img_src_path) in self.converted_data.items():
|
|
203
|
+
json_filename = os.path.splitext(img_filename)[0] + '.json'
|
|
204
|
+
with open(os.path.join(json_dir, json_filename), 'w', encoding='utf-8') as jf:
|
|
205
|
+
json.dump(dm_json, jf, indent=2, ensure_ascii=False)
|
|
206
|
+
if img_src_path and os.path.exists(img_src_path):
|
|
207
|
+
shutil.copy(img_src_path, os.path.join(original_file_dir, img_filename))
|
|
208
|
+
print(f'[DM] Data exported to {output_dir}')
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from synapse_sdk.utils.converters import ToDMConverter
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class COCOToDMConverter(ToDMConverter):
|
|
8
|
+
"""Convert COCO format annotations to DM (Data Manager) format."""
|
|
9
|
+
|
|
10
|
+
def convert(self):
|
|
11
|
+
if self.is_categorized_dataset:
|
|
12
|
+
splits = self._validate_splits(['train', 'valid'], ['test'])
|
|
13
|
+
all_split_data = {}
|
|
14
|
+
for split, split_dir in splits.items():
|
|
15
|
+
annotation_path = os.path.join(split_dir, 'annotations.json')
|
|
16
|
+
if not os.path.exists(annotation_path):
|
|
17
|
+
raise FileNotFoundError(f'annotations.json not found in {split_dir}')
|
|
18
|
+
with open(annotation_path, 'r', encoding='utf-8') as f:
|
|
19
|
+
coco_data = json.load(f)
|
|
20
|
+
split_data = self._convert_coco_ann_to_dm(coco_data, split_dir)
|
|
21
|
+
all_split_data[split] = split_data
|
|
22
|
+
self.converted_data = all_split_data
|
|
23
|
+
return all_split_data
|
|
24
|
+
else:
|
|
25
|
+
annotation_path = os.path.join(self.root_dir, 'annotations.json')
|
|
26
|
+
if not os.path.exists(annotation_path):
|
|
27
|
+
raise FileNotFoundError(f'annotations.json not found in {self.root_dir}')
|
|
28
|
+
with open(annotation_path, 'r', encoding='utf-8') as f:
|
|
29
|
+
coco_data = json.load(f)
|
|
30
|
+
converted_data = self._convert_coco_ann_to_dm(coco_data, self.root_dir)
|
|
31
|
+
self.converted_data = converted_data
|
|
32
|
+
return converted_data
|
|
33
|
+
|
|
34
|
+
def _convert_coco_ann_to_dm(self, coco_data, base_dir):
|
|
35
|
+
"""Convert COCO annotations to DM format."""
|
|
36
|
+
dataset_type = coco_data.get('type', 'image') # Default to 'image' if type is not specified
|
|
37
|
+
if dataset_type == 'image':
|
|
38
|
+
return self._process_image_data(coco_data, base_dir)
|
|
39
|
+
else:
|
|
40
|
+
raise ValueError(f'Unsupported dataset type: {dataset_type}')
|
|
41
|
+
|
|
42
|
+
def _process_image_data(self, coco_data, img_base_dir):
|
|
43
|
+
"""Process COCO image data and convert to DM format."""
|
|
44
|
+
images = coco_data.get('images', [])
|
|
45
|
+
annotations = coco_data.get('annotations', [])
|
|
46
|
+
categories = coco_data.get('categories', [])
|
|
47
|
+
cat_map = {cat['id']: cat for cat in categories}
|
|
48
|
+
|
|
49
|
+
# Build image_id -> annotation list
|
|
50
|
+
ann_by_img_id = {}
|
|
51
|
+
for ann in annotations:
|
|
52
|
+
img_id = ann['image_id']
|
|
53
|
+
ann_by_img_id.setdefault(img_id, []).append(ann)
|
|
54
|
+
|
|
55
|
+
result = {}
|
|
56
|
+
for img in images:
|
|
57
|
+
img_id = img['id']
|
|
58
|
+
img_filename = img['file_name']
|
|
59
|
+
img_path = os.path.join(img_base_dir, img_filename)
|
|
60
|
+
anns = ann_by_img_id.get(img_id, [])
|
|
61
|
+
|
|
62
|
+
# DM image structure
|
|
63
|
+
dm_img = {
|
|
64
|
+
'bounding_box': [],
|
|
65
|
+
'keypoint': [],
|
|
66
|
+
'relation': [],
|
|
67
|
+
'group': [],
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Handle bounding_box
|
|
71
|
+
bbox_ids = []
|
|
72
|
+
for ann in anns:
|
|
73
|
+
cat = cat_map.get(ann['category_id'], {})
|
|
74
|
+
if 'bbox' in ann and ann['bbox']:
|
|
75
|
+
bbox_id = self._generate_unique_id()
|
|
76
|
+
bbox_ids.append(bbox_id)
|
|
77
|
+
dm_img['bounding_box'].append({
|
|
78
|
+
'id': bbox_id,
|
|
79
|
+
'classification': cat.get('name', str(ann['category_id'])),
|
|
80
|
+
'attrs': ann.get('attrs', []),
|
|
81
|
+
'data': list(ann['bbox']),
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
# Handle keypoints
|
|
85
|
+
for ann in anns:
|
|
86
|
+
cat = cat_map.get(ann['category_id'], {})
|
|
87
|
+
attrs = ann.get('attrs', [])
|
|
88
|
+
if 'keypoints' in ann and ann['keypoints']:
|
|
89
|
+
kp_names = cat.get('keypoints', [])
|
|
90
|
+
kps = ann['keypoints']
|
|
91
|
+
keypoint_ids = []
|
|
92
|
+
for idx in range(min(len(kps) // 3, len(kp_names))):
|
|
93
|
+
x, y, v = kps[idx * 3 : idx * 3 + 3]
|
|
94
|
+
kp_id = self._generate_unique_id()
|
|
95
|
+
keypoint_ids.append(kp_id)
|
|
96
|
+
dm_img['keypoint'].append({
|
|
97
|
+
'id': kp_id,
|
|
98
|
+
'classification': kp_names[idx] if idx < len(kp_names) else f'keypoint_{idx}',
|
|
99
|
+
'attrs': attrs,
|
|
100
|
+
'data': [x, y],
|
|
101
|
+
})
|
|
102
|
+
group_ids = bbox_ids + keypoint_ids
|
|
103
|
+
if group_ids:
|
|
104
|
+
dm_img['group'].append({
|
|
105
|
+
'id': self._generate_unique_id(),
|
|
106
|
+
'classification': cat.get('name', str(ann['category_id'])),
|
|
107
|
+
'attrs': attrs,
|
|
108
|
+
'data': group_ids,
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
dm_json = {'images': [dm_img]}
|
|
112
|
+
result[img_filename] = (dm_json, img_path)
|
|
113
|
+
return result
|
|
@@ -14,13 +14,40 @@ def get_storage(connection_param: str | dict):
|
|
|
14
14
|
Returns:
|
|
15
15
|
BaseStorage: The storage class object with connection param.
|
|
16
16
|
"""
|
|
17
|
+
if connection_param is None:
|
|
18
|
+
raise ValueError(_('Connection parameter cannot be None'))
|
|
19
|
+
|
|
17
20
|
storage_scheme = None
|
|
18
21
|
if isinstance(connection_param, dict):
|
|
19
|
-
|
|
22
|
+
if not connection_param:
|
|
23
|
+
raise ValueError(_('Connection parameter dictionary cannot be empty'))
|
|
24
|
+
|
|
25
|
+
# Check if there's a URL field that should take priority
|
|
26
|
+
if 'url' in connection_param and connection_param['url']:
|
|
27
|
+
storage_scheme = urlparse(connection_param['url']).scheme
|
|
28
|
+
elif 'provider' in connection_param:
|
|
29
|
+
storage_scheme = connection_param['provider']
|
|
30
|
+
if not storage_scheme:
|
|
31
|
+
raise ValueError(_('Provider name cannot be empty'))
|
|
32
|
+
else:
|
|
33
|
+
raise ValueError(_('Dictionary must contain either "url" or "provider" field'))
|
|
34
|
+
elif isinstance(connection_param, str):
|
|
35
|
+
if not connection_param or connection_param.isspace():
|
|
36
|
+
raise ValueError(_('Connection parameter string cannot be empty'))
|
|
37
|
+
|
|
38
|
+
parsed_url = urlparse(connection_param)
|
|
39
|
+
storage_scheme = parsed_url.scheme
|
|
40
|
+
if not storage_scheme:
|
|
41
|
+
raise ValueError(_('Invalid URL format: no scheme found'))
|
|
20
42
|
else:
|
|
21
|
-
|
|
43
|
+
raise TypeError(_('Connection parameter must be a string or dictionary'))
|
|
44
|
+
|
|
45
|
+
if storage_scheme not in STORAGE_PROVIDERS:
|
|
46
|
+
supported_schemes = ', '.join(STORAGE_PROVIDERS.keys())
|
|
47
|
+
raise ValueError(
|
|
48
|
+
_('Storage provider "{}" not supported. Supported providers: {}').format(storage_scheme, supported_schemes)
|
|
49
|
+
)
|
|
22
50
|
|
|
23
|
-
assert storage_scheme in STORAGE_PROVIDERS.keys(), _('Storage provider not supported.')
|
|
24
51
|
return STORAGE_PROVIDERS[storage_scheme](connection_param)
|
|
25
52
|
|
|
26
53
|
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from urllib.parse import urljoin, urlparse
|
|
3
|
+
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
from synapse_sdk.utils.storage.providers import BaseStorage
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HTTPStorage(BaseStorage):
|
|
10
|
+
"""Storage provider for no-auth HTTP file servers (e.g., Django FileSystemStorage served over HTTP)."""
|
|
11
|
+
|
|
12
|
+
OPTION_CASTS = {
|
|
13
|
+
'timeout': int,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
def __init__(self, connection_params: str | dict):
|
|
17
|
+
super().__init__(connection_params)
|
|
18
|
+
|
|
19
|
+
# Extract base URL
|
|
20
|
+
if isinstance(connection_params, dict):
|
|
21
|
+
self.base_url = self.query_params.get('base_url', '')
|
|
22
|
+
self.timeout = self.query_params.get('timeout', 30)
|
|
23
|
+
else:
|
|
24
|
+
# Parse URL like: http://example.com/media/
|
|
25
|
+
parsed = urlparse(connection_params)
|
|
26
|
+
self.base_url = f'{parsed.scheme}://{parsed.netloc}{parsed.path}'
|
|
27
|
+
self.timeout = self.query_params.get('timeout', 30)
|
|
28
|
+
|
|
29
|
+
# Ensure base_url ends with /
|
|
30
|
+
if not self.base_url.endswith('/'):
|
|
31
|
+
self.base_url += '/'
|
|
32
|
+
|
|
33
|
+
# Setup session for connection pooling
|
|
34
|
+
self.session = requests.Session()
|
|
35
|
+
|
|
36
|
+
def _get_full_url(self, path: str) -> str:
|
|
37
|
+
"""Get the full URL for a given path."""
|
|
38
|
+
# Remove leading slash from path to avoid double slashes
|
|
39
|
+
if path.startswith('/'):
|
|
40
|
+
path = path[1:]
|
|
41
|
+
return urljoin(self.base_url, path)
|
|
42
|
+
|
|
43
|
+
def upload(self, source: str, target: str) -> str:
|
|
44
|
+
"""Upload a file to the HTTP server.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
source: Local file path to upload
|
|
48
|
+
target: Target path on the HTTP server
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
URL of the uploaded file
|
|
52
|
+
"""
|
|
53
|
+
url = self._get_full_url(target)
|
|
54
|
+
|
|
55
|
+
with open(source, 'rb') as f:
|
|
56
|
+
files = {'file': (os.path.basename(source), f)}
|
|
57
|
+
|
|
58
|
+
# Try PUT first (more RESTful), fallback to POST
|
|
59
|
+
response = self.session.put(url, files=files, timeout=self.timeout)
|
|
60
|
+
|
|
61
|
+
if response.status_code == 405: # Method not allowed
|
|
62
|
+
# Reset file pointer and try POST
|
|
63
|
+
f.seek(0)
|
|
64
|
+
response = self.session.post(url, files=files, timeout=self.timeout)
|
|
65
|
+
|
|
66
|
+
response.raise_for_status()
|
|
67
|
+
|
|
68
|
+
return url
|
|
69
|
+
|
|
70
|
+
def exists(self, target: str) -> bool:
|
|
71
|
+
"""Check if a file exists on the HTTP server.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
target: Path to check
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
True if file exists, False otherwise
|
|
78
|
+
"""
|
|
79
|
+
url = self._get_full_url(target)
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
response = self.session.head(url, timeout=self.timeout)
|
|
83
|
+
return response.status_code == 200
|
|
84
|
+
except requests.RequestException:
|
|
85
|
+
return False
|
|
86
|
+
|
|
87
|
+
def get_url(self, target: str) -> str:
|
|
88
|
+
"""Get the URL for a file.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
target: File path
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Full URL of the file
|
|
95
|
+
"""
|
|
96
|
+
return self._get_full_url(target)
|
|
97
|
+
|
|
98
|
+
def get_pathlib(self, path: str) -> 'HTTPPath':
|
|
99
|
+
"""Get a pathlib-like object for HTTP operations.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
path: Path to wrap
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
HTTPPath object
|
|
106
|
+
"""
|
|
107
|
+
return HTTPPath(self, path)
|
|
108
|
+
|
|
109
|
+
def get_path_file_count(self, pathlib_obj) -> int:
|
|
110
|
+
"""Get file count in a directory.
|
|
111
|
+
|
|
112
|
+
Note: This requires the HTTP server to provide directory listing functionality.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
pathlib_obj: HTTPPath object
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
File count
|
|
119
|
+
"""
|
|
120
|
+
# Most HTTP servers don't provide directory listing
|
|
121
|
+
# This would need custom server-side support
|
|
122
|
+
raise NotImplementedError('File counting requires server-side directory listing support')
|
|
123
|
+
|
|
124
|
+
def get_path_total_size(self, pathlib_obj) -> int:
|
|
125
|
+
"""Get total size of files in a directory.
|
|
126
|
+
|
|
127
|
+
Note: This requires the HTTP server to provide directory listing functionality.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
pathlib_obj: HTTPPath object
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Total size in bytes
|
|
134
|
+
"""
|
|
135
|
+
# Most HTTP servers don't provide directory listing
|
|
136
|
+
# This would need custom server-side support
|
|
137
|
+
raise NotImplementedError('Size calculation requires server-side directory listing support')
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class HTTPPath:
|
|
141
|
+
"""A pathlib-like interface for HTTP paths."""
|
|
142
|
+
|
|
143
|
+
def __init__(self, storage: HTTPStorage, path: str):
|
|
144
|
+
self.storage = storage
|
|
145
|
+
self.path = path.strip('/')
|
|
146
|
+
|
|
147
|
+
def __str__(self):
|
|
148
|
+
return self.path
|
|
149
|
+
|
|
150
|
+
def __truediv__(self, other):
|
|
151
|
+
"""Join paths using / operator."""
|
|
152
|
+
new_path = f'{self.path}/{other}' if self.path else str(other)
|
|
153
|
+
return HTTPPath(self.storage, new_path)
|
|
154
|
+
|
|
155
|
+
def joinuri(self, *parts):
|
|
156
|
+
"""Join path parts."""
|
|
157
|
+
parts = [self.path] + [str(p) for p in parts]
|
|
158
|
+
new_path = '/'.join(p.strip('/') for p in parts if p)
|
|
159
|
+
return HTTPPath(self.storage, new_path)
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def name(self):
|
|
163
|
+
"""Get the final component of the path."""
|
|
164
|
+
return os.path.basename(self.path)
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def parent(self):
|
|
168
|
+
"""Get the parent directory."""
|
|
169
|
+
parent_path = os.path.dirname(self.path)
|
|
170
|
+
return HTTPPath(self.storage, parent_path)
|
|
171
|
+
|
|
172
|
+
def exists(self):
|
|
173
|
+
"""Check if this path exists."""
|
|
174
|
+
return self.storage.exists(self.path)
|
|
175
|
+
|
|
176
|
+
def is_file(self):
|
|
177
|
+
"""Check if this path is a file."""
|
|
178
|
+
# For HTTP, we assume it's a file if it exists
|
|
179
|
+
return self.exists()
|
|
180
|
+
|
|
181
|
+
def read_bytes(self):
|
|
182
|
+
"""Read file contents as bytes."""
|
|
183
|
+
url = self.storage.get_url(self.path)
|
|
184
|
+
response = self.storage.session.get(url, timeout=self.storage.timeout)
|
|
185
|
+
response.raise_for_status()
|
|
186
|
+
return response.content
|
|
187
|
+
|
|
188
|
+
def read_text(self, encoding='utf-8'):
|
|
189
|
+
"""Read file contents as text."""
|
|
190
|
+
return self.read_bytes().decode(encoding)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from synapse_sdk.utils.storage.providers.gcp import GCPStorage
|
|
2
|
+
from synapse_sdk.utils.storage.providers.http import HTTPStorage
|
|
2
3
|
from synapse_sdk.utils.storage.providers.s3 import S3Storage
|
|
3
4
|
from synapse_sdk.utils.storage.providers.sftp import SFTPStorage
|
|
4
5
|
|
|
@@ -6,6 +7,9 @@ STORAGE_PROVIDERS = {
|
|
|
6
7
|
's3': S3Storage,
|
|
7
8
|
'amazon_s3': S3Storage,
|
|
8
9
|
'minio': S3Storage,
|
|
10
|
+
'gs': GCPStorage,
|
|
9
11
|
'gcp': GCPStorage,
|
|
10
12
|
'sftp': SFTPStorage,
|
|
13
|
+
'http': HTTPStorage,
|
|
14
|
+
'https': HTTPStorage,
|
|
11
15
|
}
|
|
@@ -252,6 +252,7 @@ synapse_sdk/utils/string.py
|
|
|
252
252
|
synapse_sdk/utils/converters/__init__.py
|
|
253
253
|
synapse_sdk/utils/converters/coco/__init__.py
|
|
254
254
|
synapse_sdk/utils/converters/coco/from_dm.py
|
|
255
|
+
synapse_sdk/utils/converters/coco/to_dm.py
|
|
255
256
|
synapse_sdk/utils/pydantic/__init__.py
|
|
256
257
|
synapse_sdk/utils/pydantic/config.py
|
|
257
258
|
synapse_sdk/utils/pydantic/errors.py
|
|
@@ -260,6 +261,7 @@ synapse_sdk/utils/storage/__init__.py
|
|
|
260
261
|
synapse_sdk/utils/storage/registry.py
|
|
261
262
|
synapse_sdk/utils/storage/providers/__init__.py
|
|
262
263
|
synapse_sdk/utils/storage/providers/gcp.py
|
|
264
|
+
synapse_sdk/utils/storage/providers/http.py
|
|
263
265
|
synapse_sdk/utils/storage/providers/s3.py
|
|
264
266
|
synapse_sdk/utils/storage/providers/sftp.py
|
|
265
267
|
tests/__init__.py
|
|
@@ -302,4 +304,5 @@ tests/utils/converters/fixtures/data_types/image/not_categorized/json/dm_2.json
|
|
|
302
304
|
tests/utils/converters/fixtures/data_types/image/not_categorized/json/dm_3.json
|
|
303
305
|
tests/utils/converters/fixtures/data_types/image/not_categorized/original_files/dm_1.jpg
|
|
304
306
|
tests/utils/converters/fixtures/data_types/image/not_categorized/original_files/dm_2.jpg
|
|
305
|
-
tests/utils/converters/fixtures/data_types/image/not_categorized/original_files/dm_3.jpg
|
|
307
|
+
tests/utils/converters/fixtures/data_types/image/not_categorized/original_files/dm_3.jpg
|
|
308
|
+
tests/utils/storage/test_provider_selection.py
|