dtlpy 1.118.15__tar.gz → 1.119.5__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.
- {dtlpy-1.118.15 → dtlpy-1.119.5}/PKG-INFO +1 -1
- dtlpy-1.119.5/dtlpy/__version__.py +1 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/app.py +19 -9
- dtlpy-1.119.5/dtlpy/entities/compute.py +241 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/dpk.py +315 -2
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/model.py +0 -23
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/service.py +46 -1
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/annotations.py +4 -2
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/apps.py +1 -1
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/computes.py +1 -1
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/feature_sets.py +1 -1
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/models.py +68 -56
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/tasks.py +10 -3
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/uploader.py +18 -2
- {dtlpy-1.118.15 → dtlpy-1.119.5}/setup.py +1 -1
- dtlpy-1.118.15/dtlpy/__version__.py +0 -1
- dtlpy-1.118.15/dtlpy/entities/compute.py +0 -450
- {dtlpy-1.118.15 → dtlpy-1.119.5}/LICENSE +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/MANIFEST.in +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/README.md +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/docs/requirements.txt +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/code_server/config.yaml +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/code_server/installation.sh +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/code_server/launch.json +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/code_server/settings.json +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/lock_open.png +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/main.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/main_partial.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/mock.json +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/model_adapter.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/package.json +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/package_catalog.json +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/package_gitignore +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/project_dataset_recipe_ontology.png +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/converter.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/multi_method.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/multi_method_annotation.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/multi_method_dataset.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/multi_method_item.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/multi_method_json.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/single_method.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/single_method_annotation.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/single_method_dataset.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/single_method_item.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/single_method_json.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/service_runners/single_method_multi_input.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/assets/voc_annotation_template.xml +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/caches/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/caches/base_cache.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/caches/cache.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/caches/dl_cache.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/caches/filesystem_cache.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/caches/redis_cache.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/dlp/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/dlp/cli_utilities.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/dlp/command_executor.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/dlp/dlp +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/dlp/dlp.bat +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/dlp/dlp.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/dlp/parser.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/analytic.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_collection.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/base_annotation_definition.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/box.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/classification.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/comparison.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/cube.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/cube_3d.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/description.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/ellipse.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/free_text.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/gis.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/note.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/point.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/polygon.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/polyline.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/pose.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/ref_image.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/segmentation.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/subtitle.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/text.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/annotation_definitions/undefined_annotation.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/app_module.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/artifact.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/assignment.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/base_entity.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/bot.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/codebase.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/collection.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/command.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/dataset.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/directory_tree.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/driver.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/execution.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/feature.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/feature_set.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/filters.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/gis_item.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/integration.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/item.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/label.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/links.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/message.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/node.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/ontology.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/organization.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/package.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/package_defaults.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/package_function.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/package_module.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/package_slot.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/paged_entities.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/pipeline.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/pipeline_execution.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/project.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/prompt_item.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/recipe.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/reflect_dict.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/resource_execution.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/service_driver.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/setting.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/task.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/time_series.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/trigger.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/user.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/entities/webhook.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/add_labels.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/add_metadata_to_item.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/annotate_items_using_model.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/annotate_video_using_model_and_tracker.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/annotations_convert_to_voc.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/annotations_convert_to_yolo.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/convert_annotation_types.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/converter.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/copy_annotations.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/copy_folder.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/create_annotations.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/create_video_annotations.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/delete_annotations.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/filters.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/move_item.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/play_video_annotation.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/show_item_and_mask.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/triggers.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/upload_batch_of_items.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/upload_items_and_custom_format_annotations.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/upload_items_with_modalities.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/upload_segmentation_annotations_from_mask_image.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/examples/upload_yolo_format_annotations.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/exceptions.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/miscellaneous/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/miscellaneous/dict_differ.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/miscellaneous/git_utils.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/miscellaneous/json_utils.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/miscellaneous/list_print.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/miscellaneous/path_utils.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/miscellaneous/zipping.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/ml/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/ml/base_feature_extractor_adapter.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/ml/base_model_adapter.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/ml/metrics.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/ml/predictions_utils.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/ml/summary_writer.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/ml/train_utils.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/new_instance.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/analytics.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/artifacts.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/assignments.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/bots.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/codebases.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/collections.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/commands.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/compositions.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/datasets.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/downloader.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/dpks.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/drivers.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/executions.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/features.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/integrations.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/items.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/messages.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/nodes.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/ontologies.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/organizations.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/packages.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/pipeline_executions.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/pipelines.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/projects.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/recipes.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/resource_executions.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/schema.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/service_drivers.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/services.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/settings.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/times_series.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/triggers.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/upload_element.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/repositories/webhooks.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/aihttp_retry.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/api_client.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/api_reference.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/async_utils.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/calls_counter.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/check_sdk.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/cookie.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/create_logger.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/events.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/logins.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/reporter.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/services/service_defaults.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/annotations/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/annotations/annotation_converters.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/base_package_runner.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/converter.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/dataset_generators/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/dataset_generators/dataset_generator.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/dataset_generators/dataset_generator_tensorflow.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/dataset_generators/dataset_generator_torch.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/local_development/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/local_development/local_session.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/reports/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/reports/figures.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/reports/report.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/videos/__init__.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/videos/video_player.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy/utilities/videos/videos.py +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/dtlpy.egg-info/SOURCES.txt +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/requirements.txt +0 -0
- {dtlpy-1.118.15 → dtlpy-1.119.5}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = '1.119.5'
|
|
@@ -48,6 +48,7 @@ class App(entities.BaseEntity):
|
|
|
48
48
|
metadata = attr.ib(type=dict)
|
|
49
49
|
status = attr.ib(type=entities.CompositionStatus)
|
|
50
50
|
settings = attr.ib(type=dict)
|
|
51
|
+
dpk = attr.ib(type=entities.Dpk)
|
|
51
52
|
|
|
52
53
|
# sdk
|
|
53
54
|
_project = attr.ib(type=entities.Project, repr=False)
|
|
@@ -57,11 +58,12 @@ class App(entities.BaseEntity):
|
|
|
57
58
|
|
|
58
59
|
@_repositories.default
|
|
59
60
|
def set_repositories(self):
|
|
60
|
-
reps = namedtuple('repositories', field_names=['projects', 'apps', 'compositions'])
|
|
61
|
+
reps = namedtuple('repositories', field_names=['projects', 'apps', 'compositions', 'models'])
|
|
61
62
|
return reps(
|
|
62
63
|
projects=repositories.Projects(client_api=self._client_api),
|
|
63
64
|
apps=repositories.Apps(client_api=self._client_api, project=self._project, project_id=self.project_id),
|
|
64
|
-
compositions=repositories.Compositions(client_api=self._client_api, project=self._project)
|
|
65
|
+
compositions=repositories.Compositions(client_api=self._client_api, project=self._project),
|
|
66
|
+
models=repositories.Models(client_api=self._client_api, app=self)
|
|
65
67
|
)
|
|
66
68
|
|
|
67
69
|
@property
|
|
@@ -80,6 +82,11 @@ class App(entities.BaseEntity):
|
|
|
80
82
|
assert isinstance(self._repositories.apps, repositories.Apps)
|
|
81
83
|
return self._repositories.apps
|
|
82
84
|
|
|
85
|
+
@property
|
|
86
|
+
def models(self):
|
|
87
|
+
assert isinstance(self._repositories.models, repositories.Models)
|
|
88
|
+
return self._repositories.models
|
|
89
|
+
|
|
83
90
|
@property
|
|
84
91
|
def compositions(self):
|
|
85
92
|
assert isinstance(self._repositories.compositions, repositories.Compositions)
|
|
@@ -141,15 +148,15 @@ class App(entities.BaseEntity):
|
|
|
141
148
|
:return:
|
|
142
149
|
"""
|
|
143
150
|
try:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
151
|
+
app = App.from_json(_json=_json,
|
|
152
|
+
client_api=client_api,
|
|
153
|
+
project=project,
|
|
154
|
+
is_fetched=is_fetched)
|
|
148
155
|
status = True
|
|
149
156
|
except Exception:
|
|
150
|
-
|
|
157
|
+
app = traceback.format_exc()
|
|
151
158
|
status = False
|
|
152
|
-
return status,
|
|
159
|
+
return status, app
|
|
153
160
|
|
|
154
161
|
def to_json(self):
|
|
155
162
|
_json = {}
|
|
@@ -189,6 +196,8 @@ class App(entities.BaseEntity):
|
|
|
189
196
|
_json['settings'] = self.settings
|
|
190
197
|
if self.integrations is not None:
|
|
191
198
|
_json['integrations'] = self.integrations
|
|
199
|
+
if self.dpk is not None:
|
|
200
|
+
_json['dpk'] = self.dpk.to_json()
|
|
192
201
|
|
|
193
202
|
return _json
|
|
194
203
|
|
|
@@ -214,7 +223,8 @@ class App(entities.BaseEntity):
|
|
|
214
223
|
metadata=_json.get('metadata', None),
|
|
215
224
|
status=_json.get('status', None),
|
|
216
225
|
settings=_json.get('settings', {}),
|
|
217
|
-
integrations=_json.get('integrations', None)
|
|
226
|
+
integrations=_json.get('integrations', None),
|
|
227
|
+
dpk=entities.Dpk.from_json(_json=_json.get('dpk', {}), client_api=client_api, project=project, is_fetched=is_fetched)
|
|
218
228
|
)
|
|
219
229
|
app.is_fetched = is_fetched
|
|
220
230
|
return app
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import List, Dict
|
|
4
|
+
from ..services.api_client import ApiClient
|
|
5
|
+
from .. import repositories, entities
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ClusterProvider(str, Enum):
|
|
9
|
+
GCP = 'gcp'
|
|
10
|
+
AWS = 'aws'
|
|
11
|
+
AZURE = 'azure'
|
|
12
|
+
HPC = 'hpc'
|
|
13
|
+
LOCAL = 'local'
|
|
14
|
+
RANCHER_K3S = 'rancher-k3s'
|
|
15
|
+
RANCHER_RKE = 'rancher-rke'
|
|
16
|
+
OPENSHIFT = 'openshift'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ComputeType(str, Enum):
|
|
20
|
+
KUBERNETES = "kubernetes"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ComputeStatus(str, Enum):
|
|
24
|
+
READY = "ready"
|
|
25
|
+
INITIALIZING = "initializing"
|
|
26
|
+
PAUSE = "pause"
|
|
27
|
+
FAILED = "failed"
|
|
28
|
+
VALIDATING = "validating"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ComputeConsumptionMethod(str, Enum):
|
|
32
|
+
MQ = "MQ",
|
|
33
|
+
API = "API"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ComputeSettings(entities.DlEntity):
|
|
37
|
+
default_namespace: str = entities.DlProperty(location=['defaultNamespace'], _type=str)
|
|
38
|
+
consumption_method: str = entities.DlProperty(location=['consumptionMethod'], _type=str)
|
|
39
|
+
|
|
40
|
+
def to_json(self) -> dict:
|
|
41
|
+
return self._dict.copy()
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def from_json(cls, _json):
|
|
45
|
+
return cls(_dict=_json)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Toleration(entities.DlEntity):
|
|
49
|
+
effect: str = entities.DlProperty(location=['effect'], _type=str)
|
|
50
|
+
key: str = entities.DlProperty(location=['key'], _type=str)
|
|
51
|
+
operator: str = entities.DlProperty(location=['operator'], _type=str)
|
|
52
|
+
value: str = entities.DlProperty(location=['value'], _type=str)
|
|
53
|
+
|
|
54
|
+
def to_json(self) -> dict:
|
|
55
|
+
return self._dict.copy()
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def from_json(cls, _json):
|
|
59
|
+
return cls(_dict=_json)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class DeploymentResource(entities.DlEntity):
|
|
63
|
+
gpu: int = entities.DlProperty(location=['gpu'], _type=int)
|
|
64
|
+
cpu: int = entities.DlProperty(location=['cpu'], _type=int)
|
|
65
|
+
memory: str = entities.DlProperty(location=['memory'], _type=str)
|
|
66
|
+
|
|
67
|
+
def to_json(self) -> dict:
|
|
68
|
+
return self._dict.copy()
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def from_json(cls, _json):
|
|
72
|
+
return cls(_dict=_json)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class DeploymentResources(entities.DlEntity):
|
|
76
|
+
request: DeploymentResource = entities.DlProperty(location=['request'], _kls='DeploymentResource')
|
|
77
|
+
limit: DeploymentResource = entities.DlProperty(location=['limit'], _kls='DeploymentResource')
|
|
78
|
+
|
|
79
|
+
def to_json(self) -> dict:
|
|
80
|
+
return self._dict.copy()
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def from_json(cls, _json):
|
|
84
|
+
return cls(_dict=_json)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class NodePool(entities.DlEntity):
|
|
88
|
+
name: str = entities.DlProperty(location=['name'], _type=str)
|
|
89
|
+
is_dl_type_default: bool = entities.DlProperty(location=['isDlTypeDefault'], _type=bool)
|
|
90
|
+
is_monitoring_configuration: bool = entities.DlProperty(location=['isMonitoringConfiguration'], _type=bool)
|
|
91
|
+
dl_types: List[str] = entities.DlProperty(location=['dlTypes'], _type=list)
|
|
92
|
+
tolerations: List[Toleration] = entities.DlProperty(location=['tolerations'], _kls='Toleration', default=[])
|
|
93
|
+
description: str = entities.DlProperty(location=['description'], _type=str, default='')
|
|
94
|
+
node_selector: str = entities.DlProperty(location=['nodeSelector'], _type=str, default='')
|
|
95
|
+
preemptible: bool = entities.DlProperty(location=['preemptible'], _type=bool, default=False)
|
|
96
|
+
deployment_resources: DeploymentResources = entities.DlProperty(location=['deploymentResources'], _kls='DeploymentResources')
|
|
97
|
+
|
|
98
|
+
def to_json(self) -> dict:
|
|
99
|
+
return self._dict.copy()
|
|
100
|
+
|
|
101
|
+
@classmethod
|
|
102
|
+
def from_json(cls, _json):
|
|
103
|
+
return cls(_dict=_json)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class AuthenticationIntegration(entities.DlEntity):
|
|
107
|
+
id: str = entities.DlProperty(location=['id'], _type=str)
|
|
108
|
+
type: str = entities.DlProperty(location=['type'], _type=str)
|
|
109
|
+
|
|
110
|
+
def to_json(self) -> dict:
|
|
111
|
+
return self._dict.copy()
|
|
112
|
+
|
|
113
|
+
@classmethod
|
|
114
|
+
def from_json(cls, _json):
|
|
115
|
+
return cls(_dict=_json)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class Authentication(entities.DlEntity):
|
|
119
|
+
integration: AuthenticationIntegration = entities.DlProperty(location=['integration'], _kls='AuthenticationIntegration')
|
|
120
|
+
|
|
121
|
+
def to_json(self) -> dict:
|
|
122
|
+
return self._dict.copy()
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def from_json(cls, _json):
|
|
126
|
+
return cls(_dict=_json)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class ComputeCluster(entities.DlEntity):
|
|
130
|
+
name: str = entities.DlProperty(location=['name'], _type=str)
|
|
131
|
+
endpoint: str = entities.DlProperty(location=['endpoint'], _type=str)
|
|
132
|
+
kubernetes_version: str = entities.DlProperty(location=['kubernetesVersion'], _type=str)
|
|
133
|
+
provider: str = entities.DlProperty(location=['provider'], _type=str)
|
|
134
|
+
node_pools: List[NodePool] = entities.DlProperty(location=['nodePools'], _kls='NodePool', default=[])
|
|
135
|
+
metadata: Dict = entities.DlProperty(location=['metadata'], _type=dict, default={})
|
|
136
|
+
authentication: Authentication = entities.DlProperty(location=['authentication'], _kls='Authentication')
|
|
137
|
+
plugins: dict = entities.DlProperty(location=['plugins'], _type=dict)
|
|
138
|
+
deployment_configuration: Dict = entities.DlProperty(location=['deploymentConfiguration'], _type=dict, default={})
|
|
139
|
+
|
|
140
|
+
def to_json(self) -> dict:
|
|
141
|
+
return self._dict.copy()
|
|
142
|
+
|
|
143
|
+
@classmethod
|
|
144
|
+
def from_json(cls, _json):
|
|
145
|
+
return cls(_dict=_json)
|
|
146
|
+
|
|
147
|
+
@classmethod
|
|
148
|
+
def from_setup_json(cls, devops_output, integration):
|
|
149
|
+
_json = {
|
|
150
|
+
'name': devops_output['config']['name'],
|
|
151
|
+
'endpoint': devops_output['config']['endpoint'],
|
|
152
|
+
'kubernetesVersion': devops_output['config']['kubernetesVersion'],
|
|
153
|
+
'provider': devops_output['config']['provider'],
|
|
154
|
+
'nodePools': devops_output['config']['nodePools'],
|
|
155
|
+
'metadata': {},
|
|
156
|
+
'authentication': {'integration': {'id': integration.id, 'type': integration.type}},
|
|
157
|
+
'plugins': devops_output['config'].get('plugins'),
|
|
158
|
+
'deploymentConfiguration': devops_output['config'].get('deploymentConfiguration', {})
|
|
159
|
+
}
|
|
160
|
+
return cls(_dict=_json)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class ComputeContext(entities.DlEntity):
|
|
164
|
+
labels: List[str] = entities.DlProperty(location=['labels'], _type=list, default=[])
|
|
165
|
+
org: str = entities.DlProperty(location=['org'], _type=str)
|
|
166
|
+
project: str = entities.DlProperty(location=['project'], _type=str)
|
|
167
|
+
|
|
168
|
+
def to_json(self) -> dict:
|
|
169
|
+
return self._dict.copy()
|
|
170
|
+
|
|
171
|
+
@classmethod
|
|
172
|
+
def from_json(cls, _json):
|
|
173
|
+
return cls(_dict=_json)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class Compute(entities.DlEntity):
|
|
177
|
+
id: str = entities.DlProperty(location=['id'], _type=str)
|
|
178
|
+
name: str = entities.DlProperty(location=['name'], _type=str)
|
|
179
|
+
context: ComputeContext = entities.DlProperty(location=['context'], _kls='ComputeContext')
|
|
180
|
+
shared_contexts: List[ComputeContext] = entities.DlProperty(location=['sharedContexts'], _kls='ComputeContext', default=[])
|
|
181
|
+
global_: bool = entities.DlProperty(location=['global'], _type=bool)
|
|
182
|
+
status: str = entities.DlProperty(location=['status'], _type=str, default=ComputeStatus.INITIALIZING.value)
|
|
183
|
+
type: str = entities.DlProperty(location=['type'], _type=str, default=ComputeType.KUBERNETES.value)
|
|
184
|
+
features: Dict = entities.DlProperty(location=['features'], _type=dict, default={})
|
|
185
|
+
metadata: Dict = entities.DlProperty(location=['metadata'], _type=dict, default={})
|
|
186
|
+
settings: ComputeSettings = entities.DlProperty(location=['settings'], _kls='ComputeSettings')
|
|
187
|
+
url: str = entities.DlProperty(location=['url'], _type=str)
|
|
188
|
+
|
|
189
|
+
def __init__(self, _dict=None, client_api: ApiClient = None, **kwargs):
|
|
190
|
+
super().__init__(_dict=_dict, **kwargs)
|
|
191
|
+
self._client_api = client_api
|
|
192
|
+
self._computes = None
|
|
193
|
+
self._serviceDrivers = None
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def computes(self):
|
|
197
|
+
if self._computes is None:
|
|
198
|
+
self._computes = repositories.Computes(client_api=self._client_api)
|
|
199
|
+
return self._computes
|
|
200
|
+
|
|
201
|
+
def delete(self, skip_destroy: bool = False):
|
|
202
|
+
return self.computes.delete(compute_id=self.id, skip_destroy=skip_destroy)
|
|
203
|
+
|
|
204
|
+
def update(self):
|
|
205
|
+
return self.computes.update(compute=self)
|
|
206
|
+
|
|
207
|
+
@staticmethod
|
|
208
|
+
def _protected_from_json(_json: dict, client_api: ApiClient):
|
|
209
|
+
"""
|
|
210
|
+
Same as from_json but with try-except to catch if error
|
|
211
|
+
|
|
212
|
+
:param _json: platform json
|
|
213
|
+
:param client_api: ApiClient entity
|
|
214
|
+
:return:
|
|
215
|
+
"""
|
|
216
|
+
try:
|
|
217
|
+
compute = Compute.from_json(_json=_json,
|
|
218
|
+
client_api=client_api)
|
|
219
|
+
status = True
|
|
220
|
+
except Exception:
|
|
221
|
+
compute = traceback.format_exc()
|
|
222
|
+
status = False
|
|
223
|
+
return status, compute
|
|
224
|
+
|
|
225
|
+
@classmethod
|
|
226
|
+
def from_json(cls, _json, client_api: ApiClient):
|
|
227
|
+
return cls(_dict=_json, client_api=client_api)
|
|
228
|
+
|
|
229
|
+
def to_json(self) -> dict:
|
|
230
|
+
return self._dict.copy()
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
class KubernetesCompute(Compute):
|
|
234
|
+
cluster: ComputeCluster = entities.DlProperty(location=['cluster'], _kls='ComputeCluster')
|
|
235
|
+
|
|
236
|
+
@classmethod
|
|
237
|
+
def from_json(cls, _json, client_api: ApiClient):
|
|
238
|
+
return cls(_dict=_json, client_api=client_api)
|
|
239
|
+
|
|
240
|
+
def to_json(self) -> dict:
|
|
241
|
+
return self._dict.copy()
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
from collections import namedtuple
|
|
2
|
-
from typing import List, Union
|
|
2
|
+
from typing import List, Union, Tuple
|
|
3
3
|
import traceback
|
|
4
4
|
import enum
|
|
5
|
+
import tempfile
|
|
6
|
+
import inspect
|
|
7
|
+
import os
|
|
8
|
+
import typing
|
|
5
9
|
|
|
6
|
-
from .. import entities, repositories, exceptions
|
|
10
|
+
from .. import entities, repositories, exceptions, assets
|
|
7
11
|
from ..services.api_client import ApiClient
|
|
12
|
+
from . import package_defaults
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
class SlotType(str, enum.Enum):
|
|
@@ -29,6 +34,18 @@ DEFAULT_STOPS = {SlotType.ITEM_VIEWER: {"type": "itemViewer",
|
|
|
29
34
|
}
|
|
30
35
|
}
|
|
31
36
|
|
|
37
|
+
DEFAULT_RUNTIME = {
|
|
38
|
+
"podType": "regular-xs",
|
|
39
|
+
"concurrency": 1,
|
|
40
|
+
"runnerImage": "docker.io/dataloopai/dtlpy-agent:cpu.py3.10.opencv",
|
|
41
|
+
"autoscaler": {
|
|
42
|
+
"type": "rabbitmq",
|
|
43
|
+
"minReplicas": 0,
|
|
44
|
+
"maxReplicas": 2,
|
|
45
|
+
"queueLength": 100
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
32
49
|
|
|
33
50
|
class Slot(entities.DlEntity):
|
|
34
51
|
type: str = entities.DlProperty(location=['type'], _type=str)
|
|
@@ -468,3 +485,299 @@ class Dpk(entities.DlEntity):
|
|
|
468
485
|
)
|
|
469
486
|
|
|
470
487
|
return res
|
|
488
|
+
|
|
489
|
+
@staticmethod
|
|
490
|
+
def _parse_function_io(func) -> Tuple[List[dict], List[dict]]:
|
|
491
|
+
"""
|
|
492
|
+
Parse function inputs and outputs from function signature and type hints.
|
|
493
|
+
|
|
494
|
+
This helper function extracts:
|
|
495
|
+
- Inputs: from function parameters (inspect.signature)
|
|
496
|
+
- Outputs: from return type hints (typing.get_type_hints)
|
|
497
|
+
|
|
498
|
+
:param func: The function to parse
|
|
499
|
+
:return: Tuple of (inputs, outputs) where each is a list of dicts with 'name' and 'type' keys
|
|
500
|
+
:rtype: Tuple[List[dict], List[dict]]
|
|
501
|
+
"""
|
|
502
|
+
# ============================================
|
|
503
|
+
# PARSE INPUTS FROM FUNCTION SIGNATURE
|
|
504
|
+
# ============================================
|
|
505
|
+
# Get all parameter names from the function signature
|
|
506
|
+
params = list(inspect.signature(func).parameters)
|
|
507
|
+
inputs = []
|
|
508
|
+
|
|
509
|
+
# Create a mapping of known input type names (lowercase) to PackageInputType values
|
|
510
|
+
# This allows matching parameter names like 'item', 'items', 'annotation', etc. to their types
|
|
511
|
+
inputs_types = {i.name.lower(): i.value for i in list(entities.PackageInputType)}
|
|
512
|
+
|
|
513
|
+
# Process each parameter
|
|
514
|
+
for arg in params:
|
|
515
|
+
# Check if the parameter name matches a known PackageInputType (case-insensitive)
|
|
516
|
+
# For example: 'item' -> PackageInputType.ITEM, 'items' -> PackageInputType.ITEMS
|
|
517
|
+
if arg in inputs_types:
|
|
518
|
+
inpt_type = inputs_types[arg]
|
|
519
|
+
else:
|
|
520
|
+
# If parameter name doesn't match a known type, default to JSON
|
|
521
|
+
inpt_type = entities.PackageInputType.JSON
|
|
522
|
+
|
|
523
|
+
# Create input dict with name and type
|
|
524
|
+
inputs.append({
|
|
525
|
+
'name': arg,
|
|
526
|
+
'type': inpt_type
|
|
527
|
+
})
|
|
528
|
+
|
|
529
|
+
# ============================================
|
|
530
|
+
# PARSE OUTPUTS FROM TYPE HINTS
|
|
531
|
+
# ============================================
|
|
532
|
+
outputs = []
|
|
533
|
+
try:
|
|
534
|
+
# Get return type hint from function annotations
|
|
535
|
+
# Returns None if no return type is specified
|
|
536
|
+
hint_outputs = typing.get_type_hints(func).get('return', None)
|
|
537
|
+
|
|
538
|
+
if hint_outputs is not None:
|
|
539
|
+
# ============================================
|
|
540
|
+
# STEP 1: Extract output types from type hint
|
|
541
|
+
# ============================================
|
|
542
|
+
# Handle different return type patterns:
|
|
543
|
+
# - Tuple[Type1, Type2, ...] -> multiple outputs
|
|
544
|
+
# - List[Type] -> single output that's a list
|
|
545
|
+
# - Type -> single output
|
|
546
|
+
output_types = []
|
|
547
|
+
|
|
548
|
+
if hasattr(hint_outputs, '__origin__') and hint_outputs.__origin__ is tuple:
|
|
549
|
+
# Multiple returns: Tuple[Type1, Type2, ...]
|
|
550
|
+
# Extract all types from the tuple
|
|
551
|
+
output_types = list(hint_outputs.__args__) if hasattr(hint_outputs, '__args__') else []
|
|
552
|
+
elif hasattr(hint_outputs, '__args__'):
|
|
553
|
+
# Single generic type (e.g., List[Item], Dict[str, int])
|
|
554
|
+
# Extract the inner type from the generic
|
|
555
|
+
output_types = [hint_outputs.__args__[0]]
|
|
556
|
+
else:
|
|
557
|
+
# Single simple type (e.g., Item, str, int)
|
|
558
|
+
output_types = [hint_outputs]
|
|
559
|
+
|
|
560
|
+
# ============================================
|
|
561
|
+
# STEP 2: Process each output type
|
|
562
|
+
# ============================================
|
|
563
|
+
for idx, output_type in enumerate(output_types):
|
|
564
|
+
io_type = output_type
|
|
565
|
+
is_list = False
|
|
566
|
+
|
|
567
|
+
# ============================================
|
|
568
|
+
# STEP 2a: Check if it's a List type
|
|
569
|
+
# ============================================
|
|
570
|
+
# Handle List[Type] patterns (e.g., List[Item], List[Annotation])
|
|
571
|
+
if hasattr(io_type, '__origin__'):
|
|
572
|
+
origin = io_type.__origin__
|
|
573
|
+
origin_str = str(origin)
|
|
574
|
+
|
|
575
|
+
# Check if origin is list or typing.List
|
|
576
|
+
# This handles both 'list' and 'typing.List' cases
|
|
577
|
+
if origin is list or origin_str.startswith('typing.List') or origin_str.startswith('<class \'list\'>'):
|
|
578
|
+
is_list = True
|
|
579
|
+
# Extract inner type from List[InnerType]
|
|
580
|
+
# Example: List[Item] -> extract 'Item'
|
|
581
|
+
if hasattr(io_type, '__args__') and len(io_type.__args__) > 0:
|
|
582
|
+
io_type = io_type.__args__[0]
|
|
583
|
+
|
|
584
|
+
# ============================================
|
|
585
|
+
# STEP 2b: Handle special type cases
|
|
586
|
+
# ============================================
|
|
587
|
+
# Handle Enum types - convert to string name
|
|
588
|
+
if isinstance(io_type, enum.Enum):
|
|
589
|
+
io_type = io_type.name
|
|
590
|
+
|
|
591
|
+
# Handle nested generic types (only if not already extracted from List)
|
|
592
|
+
# Example: Optional[List[Item]] -> extract List[Item] first, then Item
|
|
593
|
+
if not is_list and hasattr(io_type, '__args__'):
|
|
594
|
+
io_type = io_type.__args__[0]
|
|
595
|
+
|
|
596
|
+
# ============================================
|
|
597
|
+
# STEP 2c: Extract type name as string
|
|
598
|
+
# ============================================
|
|
599
|
+
# Convert type to string representation
|
|
600
|
+
if isinstance(io_type, type):
|
|
601
|
+
# Direct type object (e.g., Item class) -> get class name
|
|
602
|
+
type_str = io_type.__name__
|
|
603
|
+
else:
|
|
604
|
+
# Type hint object -> convert to string
|
|
605
|
+
type_str = str(io_type)
|
|
606
|
+
# Extract class name from fully qualified name
|
|
607
|
+
# Example: "dtlpy.entities.item.Item" -> "Item"
|
|
608
|
+
if '.' in type_str:
|
|
609
|
+
type_str = type_str.rsplit('.', maxsplit=1)[-1]
|
|
610
|
+
|
|
611
|
+
# ============================================
|
|
612
|
+
# STEP 2d: Map type string to PackageInputType
|
|
613
|
+
# ============================================
|
|
614
|
+
# Map Python type names to PackageInputType enum values
|
|
615
|
+
# Special case: 'str' maps to STRING
|
|
616
|
+
if type_str == 'str':
|
|
617
|
+
mapped_type = entities.PackageInputType.STRING
|
|
618
|
+
else:
|
|
619
|
+
mapped_type = None
|
|
620
|
+
|
|
621
|
+
# If it's a list, try to find the array version first
|
|
622
|
+
# Example: Item -> ITEMS, Annotation -> ANNOTATIONS
|
|
623
|
+
if is_list:
|
|
624
|
+
array_type_name = f"{type_str.upper()}S" # Item -> ITEMS
|
|
625
|
+
for pkg_input_type in entities.PackageInputType:
|
|
626
|
+
if pkg_input_type.name.upper() == array_type_name:
|
|
627
|
+
mapped_type = pkg_input_type
|
|
628
|
+
break
|
|
629
|
+
|
|
630
|
+
# If not found or not a list, try the regular type
|
|
631
|
+
# Example: Item -> ITEM, Annotation -> ANNOTATION
|
|
632
|
+
if mapped_type is None:
|
|
633
|
+
for pkg_input_type in entities.PackageInputType:
|
|
634
|
+
if pkg_input_type.name.upper() == type_str.upper():
|
|
635
|
+
mapped_type = pkg_input_type
|
|
636
|
+
break
|
|
637
|
+
|
|
638
|
+
# Default to JSON if no match found
|
|
639
|
+
# This handles unknown types gracefully
|
|
640
|
+
if mapped_type is None:
|
|
641
|
+
mapped_type = entities.PackageInputType.JSON
|
|
642
|
+
|
|
643
|
+
# ============================================
|
|
644
|
+
# STEP 2e: Create output dict
|
|
645
|
+
# ============================================
|
|
646
|
+
# Name outputs: 'output' for single, 'output_0', 'output_1', etc. for multiple
|
|
647
|
+
output_name = 'output' if len(output_types) == 1 else f'output_{idx}'
|
|
648
|
+
outputs.append({
|
|
649
|
+
'name': output_name,
|
|
650
|
+
'type': mapped_type
|
|
651
|
+
})
|
|
652
|
+
except Exception:
|
|
653
|
+
# If type hints extraction fails (e.g., no type hints, invalid syntax),
|
|
654
|
+
# leave outputs empty - this is not a fatal error
|
|
655
|
+
pass
|
|
656
|
+
|
|
657
|
+
return inputs, outputs
|
|
658
|
+
|
|
659
|
+
@classmethod
|
|
660
|
+
def from_function(
|
|
661
|
+
cls,
|
|
662
|
+
func,
|
|
663
|
+
name: str = None,
|
|
664
|
+
version: str = '1.0.0',
|
|
665
|
+
description: str = None,
|
|
666
|
+
project: 'entities.Project' = None,
|
|
667
|
+
client_api: ApiClient = None,
|
|
668
|
+
scope: str = 'project',
|
|
669
|
+
runtime: dict = None,
|
|
670
|
+
execution_timeout: int = 3600,
|
|
671
|
+
) -> 'entities.Dpk':
|
|
672
|
+
"""
|
|
673
|
+
Build a DPK from a Python function (codebase + components). Does not publish or install.
|
|
674
|
+
Runtime is held on the service component (modules have no runtime). Use the runtime param to override defaults.
|
|
675
|
+
|
|
676
|
+
:param Callable func: Function to deploy
|
|
677
|
+
:param str name: DPK name (default: function __name__)
|
|
678
|
+
:param str version: DPK version (default: '1.0.0')
|
|
679
|
+
:param str description: DPK description
|
|
680
|
+
:param entities.Project project: Project (required)
|
|
681
|
+
:param ApiClient client_api: API client (required)
|
|
682
|
+
:param str scope: 'project' or 'organization'
|
|
683
|
+
:param dict runtime: podType, concurrency, runnerImage, autoscaler; default: DEFAULT_RUNTIME
|
|
684
|
+
:param int execution_timeout: Service timeout in seconds (default: 3600)
|
|
685
|
+
:return: Built DPK (with codebase); use Service.from_function to publish, install, and get the Service
|
|
686
|
+
:rtype: dtlpy.entities.Dpk
|
|
687
|
+
"""
|
|
688
|
+
if client_api is None:
|
|
689
|
+
raise ValueError('client_api is required')
|
|
690
|
+
if project is None:
|
|
691
|
+
raise ValueError('project is required for codebase packing')
|
|
692
|
+
|
|
693
|
+
# Get function name if name not provided
|
|
694
|
+
if name is None:
|
|
695
|
+
name = func.__name__
|
|
696
|
+
|
|
697
|
+
# Resolve runtime: use copy to avoid mutating caller's dict or DEFAULT_RUNTIME
|
|
698
|
+
if runtime is None:
|
|
699
|
+
runtime = dict(DEFAULT_RUNTIME)
|
|
700
|
+
else:
|
|
701
|
+
runtime = dict(runtime)
|
|
702
|
+
|
|
703
|
+
# Create temporary directory for the function code
|
|
704
|
+
dpk_dir = tempfile.mkdtemp()
|
|
705
|
+
|
|
706
|
+
# Create main.py file with the function
|
|
707
|
+
main_file = os.path.join(dpk_dir, package_defaults.DEFAULT_PACKAGE_ENTRY_POINT)
|
|
708
|
+
|
|
709
|
+
# Read the partial main template (ServiceRunner class structure)
|
|
710
|
+
with open(assets.paths.PARTIAL_MAIN_FILEPATH, 'r') as f:
|
|
711
|
+
main_template = f.read()
|
|
712
|
+
|
|
713
|
+
# Extract function source code and adjust indentation
|
|
714
|
+
lines = inspect.getsourcelines(func)
|
|
715
|
+
tabs_diff = lines[0][0].count(' ') - 1
|
|
716
|
+
for line_index in range(len(lines[0])):
|
|
717
|
+
line_tabs = lines[0][line_index].count(' ') - tabs_diff
|
|
718
|
+
lines[0][line_index] = (' ' * line_tabs) + lines[0][line_index].strip() + '\n'
|
|
719
|
+
|
|
720
|
+
method_func_string = "".join(lines[0])
|
|
721
|
+
|
|
722
|
+
# Write main.py with ServiceRunner class and function
|
|
723
|
+
with open(main_file, 'w') as f:
|
|
724
|
+
f.write(f'{main_template}\n @staticmethod\n{method_func_string}')
|
|
725
|
+
|
|
726
|
+
# Parse function inputs and outputs from signature and type hints
|
|
727
|
+
inputs, outputs = cls._parse_function_io(func)
|
|
728
|
+
|
|
729
|
+
# Build module dict (no runtime on module/functions)
|
|
730
|
+
function_dict = {
|
|
731
|
+
'name': func.__name__,
|
|
732
|
+
'input': inputs,
|
|
733
|
+
'output': outputs,
|
|
734
|
+
}
|
|
735
|
+
module_dict = {
|
|
736
|
+
'name': package_defaults.DEFAULT_PACKAGE_MODULE_NAME,
|
|
737
|
+
'entryPoint': package_defaults.DEFAULT_PACKAGE_ENTRY_POINT,
|
|
738
|
+
'className': package_defaults.DEFAULT_PACKAGE_CLASS_NAME,
|
|
739
|
+
'functions': [function_dict],
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
# Service component (smart-search style): holds runtime, references module
|
|
743
|
+
service_name = f"{name}-service".replace("_", "-")
|
|
744
|
+
service_entry = {
|
|
745
|
+
"name": service_name,
|
|
746
|
+
"moduleName": package_defaults.DEFAULT_PACKAGE_MODULE_NAME,
|
|
747
|
+
"packageRevision": "latest",
|
|
748
|
+
"runtime": runtime,
|
|
749
|
+
"executionTimeout": execution_timeout,
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
components_dict = {
|
|
753
|
+
"modules": [module_dict],
|
|
754
|
+
"services": [service_entry],
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
# Create DPK entity
|
|
758
|
+
dpk_json = {
|
|
759
|
+
'name': name,
|
|
760
|
+
'version': version,
|
|
761
|
+
'display_name': name,
|
|
762
|
+
'description': description or f'DPK created from function {func.__name__}',
|
|
763
|
+
'scope': scope,
|
|
764
|
+
'components': components_dict,
|
|
765
|
+
'context': {
|
|
766
|
+
'project': project.id
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
dpk = cls.from_json(
|
|
771
|
+
_json=dpk_json,
|
|
772
|
+
client_api=client_api,
|
|
773
|
+
project=project
|
|
774
|
+
)
|
|
775
|
+
|
|
776
|
+
# Pack the temporary directory as codebase
|
|
777
|
+
dpk.codebase = project.codebases.pack(
|
|
778
|
+
directory=dpk_dir,
|
|
779
|
+
name=name,
|
|
780
|
+
extension='dpk'
|
|
781
|
+
)
|
|
782
|
+
|
|
783
|
+
return dpk
|