thestage 0.6.7__py3-none-any.whl → 0.6.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- thestage/__init__.py +1 -1
- thestage/cli_command_helper.py +2 -2
- thestage/config/__init__.py +1 -1
- thestage/{services → config/business}/app_config_service.py +3 -4
- thestage/{services/config_provider → config/business}/config_provider.py +6 -5
- thestage/config/{config_storage.py → business/config_storage.py} +1 -1
- thestage/{services → config/business}/validation_service.py +9 -10
- thestage/{controllers/config_controller.py → config/communication/config_command.py} +7 -7
- thestage/{services/connect → connect/business}/connect_service.py +22 -19
- thestage/{services → connect/business}/remote_server_service.py +4 -5
- thestage/connect/communication/connect_api_client.py +84 -0
- thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/add_ssh_key_to_user_response.py +0 -1
- thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/add_ssh_public_key_to_instance_response.py +1 -4
- thestage/{services/clients/thestage_api/dtos/base_controller → connect/dto}/connect_resolve_response.py +0 -1
- thestage/controllers/base_controller.py +2 -2
- thestage/debug_main.dist.py +16 -14
- thestage/{services/container → docker_container/business}/container_service.py +27 -22
- thestage/{services/container → docker_container/business}/mapper/container_mapper.py +3 -3
- thestage/docker_container/communication/__init__.py +0 -0
- thestage/{controllers/container_controller.py → docker_container/communication/docker_command.py} +17 -23
- thestage/docker_container/communication/docker_container_api_client.py +99 -0
- thestage/docker_container/dto/__init__.py +0 -0
- thestage/docker_container/dto/container_action_request.py +11 -0
- thestage/{services/clients/thestage_api/dtos → docker_container/dto}/container_response.py +4 -4
- thestage/{services/clients/thestage_api/dtos/docker_container_controller → docker_container/dto}/docker_container_list_response.py +3 -5
- thestage/docker_container/dto/enum/__init__.py +0 -0
- thestage/git/__init__.py +0 -0
- thestage/git/business/__init__.py +0 -0
- thestage/git/communication/__init__.py +0 -0
- thestage/{services/clients/git → git/communication}/git_client.py +4 -4
- thestage/global_dto/__init__.py +0 -0
- thestage/global_dto/enums/__init__.py +0 -0
- thestage/helpers/error_handler.py +3 -3
- thestage/helpers/logger/app_logger.py +1 -3
- thestage/i18n/en_GB/messages.po +14 -14
- thestage/inference_model/__init__.py +0 -0
- thestage/inference_model/business/__init__.py +0 -0
- thestage/inference_model/business/inference_model_service.py +281 -0
- thestage/inference_model/business/mapper/__init__.py +0 -0
- thestage/{services/project/mapper/project_inference_simulator_model_mapper.py → inference_model/business/mapper/inference_model_mapper.py} +5 -5
- thestage/inference_model/communication/__init__.py +0 -0
- thestage/inference_model/communication/inference_model_api_client.py +139 -0
- thestage/inference_model/communication/inference_model_command.py +246 -0
- thestage/inference_model/dto/__init__.py +0 -0
- thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/deploy_inference_model_to_instance_response.py +0 -1
- thestage/inference_model/dto/enum/__init__.py +0 -0
- thestage/{services/project/dto/inference_simulator_model_dto.py → inference_model/dto/inference_model.py} +1 -1
- thestage/{entities/project_inference_simulator_model.py → inference_model/dto/inference_model_entity.py} +1 -1
- thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/inference_simulator_model_list_for_project_response.py +2 -3
- thestage/{services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_request.py → inference_model/dto/push_inference_simulator_model_request.py} +1 -1
- thestage/{services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_response.py → inference_model/dto/push_inference_simulator_model_response.py} +1 -1
- thestage/inference_simulator/__init__.py +0 -0
- thestage/inference_simulator/business/__init__.py +0 -0
- thestage/inference_simulator/business/inference_simulator_service.py +338 -0
- thestage/inference_simulator/business/mapper/__init__.py +0 -0
- thestage/{services/project/mapper/project_inference_simulator_mapper.py → inference_simulator/business/mapper/inference_simulator_mapper.py} +5 -5
- thestage/inference_simulator/communication/__init__.py +0 -0
- thestage/inference_simulator/communication/inference_simulator_api_client.py +114 -0
- thestage/inference_simulator/communication/inference_simulator_command.py +347 -0
- thestage/inference_simulator/dto/__init__.py +0 -0
- thestage/inference_simulator/dto/enum/__init__.py +0 -0
- thestage/inference_simulator/dto/get_inference_simulator_response.py +12 -0
- thestage/{services/project/dto/inference_simulator_dto.py → inference_simulator/dto/inference_simulator.py} +1 -1
- thestage/{entities/project_inference_simulator.py → inference_simulator/dto/inference_simulator_entity.py} +1 -1
- thestage/{services/clients/thestage_api/dtos/inference_controller → inference_simulator/dto}/inference_simulator_list_response.py +2 -2
- thestage/{services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_request.py → inference_simulator/dto/start_inference_simulator_request.py} +1 -1
- thestage/inference_simulator/dto/start_inference_simulator_response.py +10 -0
- thestage/instance/__init__.py +0 -0
- thestage/instance/business/__init__.py +0 -0
- thestage/{services/instance → instance/business}/instance_service.py +26 -27
- thestage/instance/business/mapper/__init__.py +0 -0
- thestage/{services/instance/mapper/instance_mapper.py → instance/business/mapper/rented_instance_mapper.py} +3 -3
- thestage/{services/instance/mapper/selfhosted_mapper.py → instance/business/mapper/selfhosted_instance_mapper.py} +5 -7
- thestage/instance/communication/__init__.py +0 -0
- thestage/instance/communication/instance_api_client.py +150 -0
- thestage/{controllers/instance_controller.py → instance/communication/instance_command.py} +5 -5
- thestage/instance/dto/__init__.py +0 -0
- thestage/instance/dto/enum/__init__.py +0 -0
- thestage/{services/clients/thestage_api/dtos → instance/dto}/instance_detected_gpus.py +1 -2
- thestage/{services/clients/thestage_api/dtos → instance/dto}/instance_rented_response.py +2 -2
- thestage/{services/clients/thestage_api/dtos → instance/dto}/selfhosted_instance_response.py +2 -3
- thestage/logging/__init__.py +0 -0
- thestage/logging/business/__init__.py +0 -0
- thestage/{services/logging → logging/business}/logging_service.py +40 -28
- thestage/logging/communication/__init__.py +0 -0
- thestage/logging/communication/logging_api_client.py +63 -0
- thestage/logging/dto/__init__.py +0 -0
- thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/log_polling_response.py +2 -2
- thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/user_logs_query_response.py +2 -2
- thestage/main.py +47 -8
- thestage/project/__init__.py +0 -0
- thestage/project/business/__init__.py +0 -0
- thestage/project/business/project_service.py +480 -0
- thestage/project/communication/__init__.py +0 -0
- thestage/project/communication/project_api_client.py +46 -0
- thestage/project/communication/project_command.py +284 -0
- thestage/project/dto/__init__.py +0 -0
- thestage/services/clients/thestage_api/core/api_client_core.py +1 -1
- thestage/services/clients/thestage_api/dtos/entity_filter_request.py +1 -1
- thestage/services/clients/thestage_api/dtos/sftp_path_helper.py +1 -1
- thestage/services/filesystem_service.py +2 -2
- thestage/services/service_factory.py +130 -43
- thestage/task/__init__.py +0 -0
- thestage/task/business/__init__.py +0 -0
- thestage/task/business/mapper/__init__.py +0 -0
- thestage/{services/project/mapper/project_task_mapper.py → task/business/mapper/task_mapper.py} +5 -5
- thestage/task/business/task_service.py +304 -0
- thestage/task/communication/__init__.py +0 -0
- thestage/task/communication/task_api_client.py +122 -0
- thestage/task/communication/task_command.py +212 -0
- thestage/task/dto/__init__.py +0 -0
- thestage/task/dto/enum/__init__.py +0 -0
- thestage/{services/clients/thestage_api/dtos/task_controller/task_list_for_project_response.py → task/dto/list_for_project_response.py} +2 -2
- thestage/{services/clients/thestage_api/dtos/project_controller/project_run_task_request.py → task/dto/run_task_request.py} +1 -1
- thestage/task/dto/run_task_response.py +13 -0
- thestage/{services/task/dto/task_dto.py → task/dto/task.py} +1 -4
- thestage/{entities/project_task.py → task/dto/task_entity.py} +1 -1
- thestage/{services/clients/thestage_api/dtos/task_controller/task_view_response.py → task/dto/view_response.py} +2 -2
- {thestage-0.6.7.dist-info → thestage-0.6.8.dist-info}/METADATA +1 -1
- thestage-0.6.8.dist-info/RECORD +219 -0
- {thestage-0.6.7.dist-info → thestage-0.6.8.dist-info}/WHEEL +1 -1
- thestage/controllers/project_controller.py +0 -1056
- thestage/services/clients/thestage_api/api_client.py +0 -751
- thestage/services/clients/thestage_api/dtos/container_param_request.py +0 -11
- thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_response.py +0 -13
- thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py +0 -13
- thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_response.py +0 -10
- thestage/services/clients/thestage_api/dtos/user_controller/user_profile.py +0 -12
- thestage/services/project/project_service.py +0 -1287
- thestage-0.6.7.dist-info/RECORD +0 -167
- /thestage/{entities → color_scheme}/__init__.py +0 -0
- /thestage/{entities/enums → config/business}/__init__.py +0 -0
- /thestage/{services/clients/git → config/communication}/__init__.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → config/dto}/__init__.py +0 -0
- /thestage/{services/core_files → config/dto}/config_entity.py +0 -0
- /thestage/{services/connect → config}/dto/remote_server_config.py +0 -0
- /thestage/{services/config_provider → connect}/__init__.py +0 -0
- /thestage/{services/container → connect/business}/__init__.py +0 -0
- /thestage/{services/container/mapper → connect/communication}/__init__.py +0 -0
- /thestage/{services/instance → connect/dto}/__init__.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/add_ssh_key_to_user_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/add_ssh_public_key_to_instance_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/is_user_has_public_ssh_key_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/is_user_has_public_ssh_key_response.py +0 -0
- /thestage/{services/instance/mapper → docker_container}/__init__.py +0 -0
- /thestage/{services/project → docker_container/business}/__init__.py +0 -0
- /thestage/{services/project → docker_container/business}/mapper/__init__.py +0 -0
- /thestage/{entities/container.py → docker_container/dto/container_entity.py} +0 -0
- /thestage/{services/clients/thestage_api/dtos/docker_container_controller → docker_container/dto}/docker_container_list_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos → docker_container/dto}/docker_container_mapping.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → docker_container/dto/enum}/container_pending_action.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → docker_container/dto/enum}/container_status.py +0 -0
- /thestage/{services/logging/exception → exceptions}/log_polling_exception.py +0 -0
- /thestage/git/{ProgressPrinter.py → business/ProgressPrinter.py} +0 -0
- /thestage/{entities → global_dto}/enums/order_direction_type.py +0 -0
- /thestage/{entities → global_dto}/enums/shell_type.py +0 -0
- /thestage/{entities → global_dto}/enums/tail_output_type.py +0 -0
- /thestage/{entities → global_dto}/enums/yes_no_response.py +0 -0
- /thestage/{entities → global_dto}/file_item.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/deploy_inference_model_to_instance_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/deploy_inference_model_to_sagemaker_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/deploy_inference_model_to_sagemaker_response.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → inference_model/dto/enum}/inference_model_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/inference_simulator_model_list_for_project_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos → inference_model/dto}/inference_simulator_model_response.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → inference_simulator/dto/enum}/inference_simulator_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_simulator/dto}/get_inference_simulator_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_simulator/dto}/inference_simulator_list_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos → inference_simulator/dto}/inference_simulator_response.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/cpu_type.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/gpu_name.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/instance_rented_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/provider_name.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/selfhosted_status.py +0 -0
- /thestage/{entities → instance/dto}/rented_instance.py +0 -0
- /thestage/{entities → instance/dto}/self_hosted_instance.py +0 -0
- /thestage/{services/logging → logging}/byte_print_style.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/docker_container_log_stream_request.py +0 -0
- /thestage/{services/logging → logging}/dto/log_message.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/log_polling_request.py +0 -0
- /thestage/{services/logging → logging}/dto/log_type.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/task_log_stream_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/user_logs_query_request.py +0 -0
- /thestage/{services/logging → logging}/logging_constants.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_request.py → project/dto/get_deploy_ssh_key_request.py} +0 -0
- /thestage/{services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_response.py → project/dto/get_deploy_ssh_key_response.py} +0 -0
- /thestage/{services/project → project}/dto/project_config.py +0 -0
- /thestage/{services/clients/thestage_api/dtos → project/dto}/project_response.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → task/dto/enum}/task_execution_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → task/dto/enum}/task_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/task_controller/task_list_for_project_request.py → task/dto/list_for_project_request.py} +0 -0
- /thestage/{services/clients/thestage_api/dtos/task_controller/task_status_localized_map_response.py → task/dto/status_localized_map_response.py} +0 -0
- {thestage-0.6.7.dist-info → thestage-0.6.8.dist-info}/entry_points.txt +0 -0
- {thestage-0.6.7.dist-info → thestage-0.6.8.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import re
|
|
3
|
+
from typing import Optional, List
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from thestage.cli_command import CliCommand
|
|
8
|
+
from thestage.cli_command_helper import get_command_metadata, check_command_permission
|
|
9
|
+
from thestage.controllers.utils_controller import validate_config_and_get_service_factory, get_current_directory
|
|
10
|
+
from thestage.helpers.logger.app_logger import app_logger
|
|
11
|
+
from thestage.i18n.translation import __
|
|
12
|
+
from thestage.inference_model.business.inference_model_service import InferenceModelService
|
|
13
|
+
from thestage.logging.business.logging_service import LoggingService
|
|
14
|
+
from thestage.project.business.project_service import ProjectService
|
|
15
|
+
|
|
16
|
+
app = typer.Typer(no_args_is_help=True, help="Manage project inference simulator models")
|
|
17
|
+
@app.command("ls", help=__("List inference simulator models"), **get_command_metadata(CliCommand.PROJECT_MODEL_LS))
|
|
18
|
+
def list_inference_simulator_models(
|
|
19
|
+
project_public_id: Optional[str] = typer.Option(
|
|
20
|
+
None,
|
|
21
|
+
'--project-id',
|
|
22
|
+
'-pid',
|
|
23
|
+
help=__("Project ID. By default, project info is taken from the current directory"),
|
|
24
|
+
is_eager=False,
|
|
25
|
+
),
|
|
26
|
+
project_slug: Optional[str] = typer.Option(
|
|
27
|
+
None,
|
|
28
|
+
'--project-name',
|
|
29
|
+
'-pn',
|
|
30
|
+
help=__("Project name. By default, project info is taken from the current directory"),
|
|
31
|
+
is_eager=False,
|
|
32
|
+
),
|
|
33
|
+
row: int = typer.Option(
|
|
34
|
+
5,
|
|
35
|
+
'--row',
|
|
36
|
+
'-r',
|
|
37
|
+
help=__("Set number of rows displayed per page"),
|
|
38
|
+
is_eager=False,
|
|
39
|
+
),
|
|
40
|
+
page: int = typer.Option(
|
|
41
|
+
1,
|
|
42
|
+
'--page',
|
|
43
|
+
'-p',
|
|
44
|
+
help=__("Set starting page for displaying output"),
|
|
45
|
+
is_eager=False,
|
|
46
|
+
),
|
|
47
|
+
statuses: List[str] = typer.Option(
|
|
48
|
+
None,
|
|
49
|
+
'--status',
|
|
50
|
+
'-s',
|
|
51
|
+
help=__("Filter by status, use --status all to list all inference simulator models"),
|
|
52
|
+
is_eager=False,
|
|
53
|
+
),
|
|
54
|
+
):
|
|
55
|
+
command_name = CliCommand.PROJECT_MODEL_LS
|
|
56
|
+
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
57
|
+
check_command_permission(command_name)
|
|
58
|
+
|
|
59
|
+
if sum(v is not None for v in [project_public_id, project_slug]) > 1:
|
|
60
|
+
typer.echo("Provide a single identifier for project - ID or name.")
|
|
61
|
+
raise typer.Exit(1)
|
|
62
|
+
|
|
63
|
+
service_factory = validate_config_and_get_service_factory()
|
|
64
|
+
inference_model_service: InferenceModelService = service_factory.get_inference_model_service()
|
|
65
|
+
|
|
66
|
+
inference_model_service.print_inference_simulator_model_list(
|
|
67
|
+
project_public_id=project_public_id,
|
|
68
|
+
project_slug=project_slug,
|
|
69
|
+
statuses=statuses,
|
|
70
|
+
row=row,
|
|
71
|
+
page=page
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
typer.echo(__("Inference simulator models listing complete"))
|
|
75
|
+
raise typer.Exit(0)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@app.command("deploy-instance", no_args_is_help=True, help=__("Deploy inference simulator model to an instance"), **get_command_metadata(CliCommand.PROJECT_MODEL_DEPLOY_INSTANCE))
|
|
79
|
+
def deploy_inference_simulator_model_to_instance(
|
|
80
|
+
model_public_id: Optional[str] = typer.Option(
|
|
81
|
+
None,
|
|
82
|
+
'--model-id',
|
|
83
|
+
'-mid',
|
|
84
|
+
help="Inference simulator model ID",
|
|
85
|
+
is_eager=False,
|
|
86
|
+
),
|
|
87
|
+
model_slug: Optional[str] = typer.Option(
|
|
88
|
+
None,
|
|
89
|
+
'--model-name',
|
|
90
|
+
'-mn',
|
|
91
|
+
help="Inference simulator model name",
|
|
92
|
+
is_eager=False,
|
|
93
|
+
),
|
|
94
|
+
rented_instance_public_id: Optional[str] = typer.Option(
|
|
95
|
+
None,
|
|
96
|
+
'--rented-instance-id',
|
|
97
|
+
'-rid',
|
|
98
|
+
help=__("Rented instance ID on which the inference simulator will run"),
|
|
99
|
+
is_eager=False,
|
|
100
|
+
),
|
|
101
|
+
rented_instance_slug: Optional[str] = typer.Option(
|
|
102
|
+
None,
|
|
103
|
+
'--rented-instance-name',
|
|
104
|
+
'-rn',
|
|
105
|
+
help=__("Rented instance name on which the inference simulator will run"),
|
|
106
|
+
is_eager=False,
|
|
107
|
+
),
|
|
108
|
+
self_hosted_instance_public_id: Optional[str] = typer.Option(
|
|
109
|
+
None,
|
|
110
|
+
'--self-hosted-instance-id',
|
|
111
|
+
'-sid',
|
|
112
|
+
help=__("Self-hosted instance ID on which the inference simulator will run"),
|
|
113
|
+
is_eager=False,
|
|
114
|
+
),
|
|
115
|
+
self_hosted_instance_slug: Optional[str] = typer.Option(
|
|
116
|
+
None,
|
|
117
|
+
'--self-hosted-instance-name',
|
|
118
|
+
'-sn',
|
|
119
|
+
help=__("Self-hosted instance name on which the inference simulator will run"),
|
|
120
|
+
is_eager=False,
|
|
121
|
+
),
|
|
122
|
+
working_directory: Optional[str] = typer.Option(
|
|
123
|
+
None,
|
|
124
|
+
"--working-directory",
|
|
125
|
+
"-wd",
|
|
126
|
+
help=__("Full path to working directory. By default, the current directory is used"),
|
|
127
|
+
show_default=False,
|
|
128
|
+
is_eager=False,
|
|
129
|
+
),
|
|
130
|
+
enable_log_stream: Optional[bool] = typer.Option(
|
|
131
|
+
True,
|
|
132
|
+
"--no-logs",
|
|
133
|
+
"-nl",
|
|
134
|
+
help=__("Disable real-time log streaming"),
|
|
135
|
+
is_eager=False,
|
|
136
|
+
),
|
|
137
|
+
):
|
|
138
|
+
command_name = CliCommand.PROJECT_MODEL_DEPLOY_INSTANCE
|
|
139
|
+
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
140
|
+
check_command_permission(command_name)
|
|
141
|
+
|
|
142
|
+
if model_slug and not re.match(r"^[a-zA-Z0-9-]+$", model_slug):
|
|
143
|
+
raise typer.BadParameter(__("Invalid UID format. UID can only contain letters, numbers, and hyphens."))
|
|
144
|
+
|
|
145
|
+
new_inference_simulator_slug = f"{model_slug}-{int(time.time())}"
|
|
146
|
+
|
|
147
|
+
service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
|
|
148
|
+
inference_model_service: InferenceModelService = service_factory.get_inference_model_service()
|
|
149
|
+
|
|
150
|
+
inference_simulator_public_id=inference_model_service.project_deploy_inference_simulator_model_to_instance(
|
|
151
|
+
model_public_id=model_public_id,
|
|
152
|
+
model_slug=model_slug,
|
|
153
|
+
new_inference_simulator_slug=new_inference_simulator_slug,
|
|
154
|
+
rented_instance_public_id=rented_instance_public_id,
|
|
155
|
+
rented_instance_slug=rented_instance_slug,
|
|
156
|
+
self_hosted_instance_public_id=self_hosted_instance_public_id,
|
|
157
|
+
self_hosted_instance_slug=self_hosted_instance_slug,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if enable_log_stream:
|
|
161
|
+
logging_service: LoggingService = service_factory.get_logging_service()
|
|
162
|
+
|
|
163
|
+
logging_service.stream_inference_simulator_logs_with_controls(
|
|
164
|
+
public_id=inference_simulator_public_id
|
|
165
|
+
)
|
|
166
|
+
raise typer.Exit(0)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@app.command("deploy-sagemaker", no_args_is_help=True, help=__("Deploy inference simulator model to SageMaker"), **get_command_metadata(CliCommand.PROJECT_MODEL_DEPLOY_SAGEMAKER))
|
|
170
|
+
def deploy_inference_simulator_model_to_sagemaker(
|
|
171
|
+
model_public_id: Optional[str] = typer.Option(
|
|
172
|
+
None,
|
|
173
|
+
'--model-id',
|
|
174
|
+
'-mid',
|
|
175
|
+
help="Inference simulator model ID",
|
|
176
|
+
is_eager=False,
|
|
177
|
+
),
|
|
178
|
+
model_slug: Optional[str] = typer.Option(
|
|
179
|
+
None,
|
|
180
|
+
'--model-name',
|
|
181
|
+
'-mn',
|
|
182
|
+
help="Inference simulator model name",
|
|
183
|
+
is_eager=False,
|
|
184
|
+
),
|
|
185
|
+
arn: Optional[str] = typer.Option(
|
|
186
|
+
None,
|
|
187
|
+
'--amazon-resource-name',
|
|
188
|
+
'-arn',
|
|
189
|
+
help=__("Amazon Resource Name of the IAM Role to use, e.g., arn:aws:iam::{aws_account_id}:role/{role}"),
|
|
190
|
+
is_eager=False,
|
|
191
|
+
),
|
|
192
|
+
working_directory: Optional[str] = typer.Option(
|
|
193
|
+
None,
|
|
194
|
+
"--working-directory",
|
|
195
|
+
"-wd",
|
|
196
|
+
help=__("Full path to working directory. By default, the current directory is used"),
|
|
197
|
+
show_default=False,
|
|
198
|
+
is_eager=False,
|
|
199
|
+
),
|
|
200
|
+
instance_type: Optional[str] = typer.Option(
|
|
201
|
+
None,
|
|
202
|
+
'--instance-type',
|
|
203
|
+
'-it',
|
|
204
|
+
help=__("Instance type on which the inference simulator model will be deployed"),
|
|
205
|
+
is_eager=False,
|
|
206
|
+
),
|
|
207
|
+
initial_variant_weight: Optional[float] = typer.Option(
|
|
208
|
+
None,
|
|
209
|
+
"--initial-variant-weight",
|
|
210
|
+
"-ivw",
|
|
211
|
+
help=__("Initial Variant Weight. By default 1.0"),
|
|
212
|
+
show_default=False,
|
|
213
|
+
is_eager=False,
|
|
214
|
+
),
|
|
215
|
+
initial_instance_count: Optional[int] = typer.Option(
|
|
216
|
+
None,
|
|
217
|
+
"--initial-instance-count",
|
|
218
|
+
"-iic",
|
|
219
|
+
help=__("Initial Instance Count"),
|
|
220
|
+
show_default=False,
|
|
221
|
+
is_eager=False,
|
|
222
|
+
),
|
|
223
|
+
|
|
224
|
+
):
|
|
225
|
+
command_name = CliCommand.PROJECT_MODEL_DEPLOY_SAGEMAKER
|
|
226
|
+
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
227
|
+
check_command_permission(command_name)
|
|
228
|
+
|
|
229
|
+
if sum(v is not None for v in [model_public_id, model_slug]) != 1:
|
|
230
|
+
typer.echo("Provide a single identifier for inference simulator model - ID or name.")
|
|
231
|
+
raise typer.Exit(1)
|
|
232
|
+
|
|
233
|
+
if model_slug and not re.match(r"^[a-zA-Z0-9-]+$", model_slug):
|
|
234
|
+
raise typer.BadParameter(__("Invalid UID format. UID can only contain letters, numbers, and hyphens."))
|
|
235
|
+
|
|
236
|
+
service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
|
|
237
|
+
inference_model_service: InferenceModelService = service_factory.get_inference_model_service()
|
|
238
|
+
|
|
239
|
+
inference_model_service.project_deploy_inference_simulator_model_to_sagemaker(
|
|
240
|
+
model_public_id=model_public_id,
|
|
241
|
+
model_slug=model_slug,
|
|
242
|
+
arn=arn,
|
|
243
|
+
instance_type=instance_type,
|
|
244
|
+
initial_variant_weight=initial_variant_weight,
|
|
245
|
+
initial_instance_count=initial_instance_count,
|
|
246
|
+
)
|
|
File without changes
|
|
@@ -3,7 +3,6 @@ from typing import Optional
|
|
|
3
3
|
from pydantic import Field, ConfigDict
|
|
4
4
|
|
|
5
5
|
from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
|
|
6
|
-
from thestage.services.project.dto.inference_simulator_model_dto import InferenceSimulatorModelDto
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
class DeployInferenceModelToInstanceResponse(TheStageBaseResponse):
|
|
File without changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Optional, Any, Dict
|
|
2
2
|
from pydantic import BaseModel, ConfigDict, Field
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class InferenceModel(BaseModel):
|
|
5
5
|
model_config = ConfigDict(use_enum_values=True)
|
|
6
6
|
|
|
7
7
|
public_id: Optional[str] = Field(None, alias='publicId')
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
from pydantic import Field, ConfigDict
|
|
3
3
|
|
|
4
|
+
from thestage.inference_model.dto.inference_model import InferenceModel
|
|
4
5
|
from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
|
|
5
6
|
from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
|
|
6
|
-
from thestage.services.project.dto.inference_simulator_dto import InferenceSimulatorDto
|
|
7
|
-
from thestage.services.project.dto.inference_simulator_model_dto import InferenceSimulatorModelDto
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
class InferenceSimulatorModelListForProjectResponse(TheStageBaseResponse):
|
|
11
10
|
model_config = ConfigDict(use_enum_values=True)
|
|
12
11
|
|
|
13
|
-
inferenceSimulatorModels: PaginatedEntityList[
|
|
12
|
+
inferenceSimulatorModels: PaginatedEntityList[InferenceModel] = Field(None, alias='inferenceSimulatorModels')
|
|
@@ -3,7 +3,7 @@ from typing import Optional
|
|
|
3
3
|
from pydantic import Field, ConfigDict, BaseModel
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class
|
|
6
|
+
class PushInferenceSimulatorModelRequest(BaseModel):
|
|
7
7
|
model_config = ConfigDict(use_enum_values=True)
|
|
8
8
|
|
|
9
9
|
inferenceSimulatorPublicId: Optional[str] = Field(None, alias='inferenceSimulatorPublicId')
|
|
@@ -3,5 +3,5 @@ from pydantic import ConfigDict
|
|
|
3
3
|
from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class
|
|
6
|
+
class PushInferenceSimulatorModelResponse(TheStageBaseResponse):
|
|
7
7
|
model_config = ConfigDict(use_enum_values=True)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Optional, List
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
import typer
|
|
8
|
+
from git import Commit
|
|
9
|
+
from rich import print
|
|
10
|
+
|
|
11
|
+
from thestage.color_scheme.color_scheme import ColorScheme
|
|
12
|
+
from thestage.config.business.config_provider import ConfigProvider
|
|
13
|
+
from thestage.git.communication.git_client import GitLocalClient
|
|
14
|
+
from thestage.global_dto.enums.yes_no_response import YesOrNoResponse
|
|
15
|
+
from thestage.helpers.error_handler import error_handler
|
|
16
|
+
from thestage.i18n.translation import __
|
|
17
|
+
from thestage.inference_model.communication.inference_model_api_client import InferenceModelApiClient
|
|
18
|
+
from thestage.inference_model.dto.push_inference_simulator_model_response import \
|
|
19
|
+
PushInferenceSimulatorModelResponse
|
|
20
|
+
from thestage.inference_simulator.business.mapper.inference_simulator_mapper import InferenceSimulatorMapper
|
|
21
|
+
from thestage.inference_simulator.communication.inference_simulator_api_client import InferenceSimulatorApiClient
|
|
22
|
+
from thestage.inference_simulator.dto.enum.inference_simulator_status import InferenceSimulatorStatus
|
|
23
|
+
from thestage.inference_simulator.dto.get_inference_simulator_response import \
|
|
24
|
+
GetInferenceSimulatorResponse
|
|
25
|
+
from thestage.inference_simulator.dto.inference_simulator import InferenceSimulator
|
|
26
|
+
from thestage.inference_simulator.dto.inference_simulator_entity import InferenceSimulatorEntity
|
|
27
|
+
from thestage.inference_simulator.dto.start_inference_simulator_response import \
|
|
28
|
+
StartInferenceSimulatorResponse
|
|
29
|
+
from thestage.project.business.project_service import ProjectService
|
|
30
|
+
from thestage.project.dto.project_config import ProjectConfig
|
|
31
|
+
from thestage.services.abstract_service import AbstractService
|
|
32
|
+
from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class InferenceSimulatorService(AbstractService):
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
inference_simulator_api_client: InferenceSimulatorApiClient,
|
|
39
|
+
inference_model_api_client: InferenceModelApiClient,
|
|
40
|
+
config_provider: ConfigProvider,
|
|
41
|
+
git_local_client: GitLocalClient,
|
|
42
|
+
project_service: ProjectService,
|
|
43
|
+
):
|
|
44
|
+
self.__inference_simulator_api_client = inference_simulator_api_client
|
|
45
|
+
self.__inference_model_api_client = inference_model_api_client
|
|
46
|
+
self.__config_provider = config_provider
|
|
47
|
+
self.__git_local_client = git_local_client
|
|
48
|
+
self.__project_service = project_service
|
|
49
|
+
|
|
50
|
+
@error_handler()
|
|
51
|
+
def project_run_inference_simulator(
|
|
52
|
+
self,
|
|
53
|
+
commit_hash: Optional[str] = None,
|
|
54
|
+
rented_instance_public_id: Optional[str] = None,
|
|
55
|
+
rented_instance_slug: Optional[str] = None,
|
|
56
|
+
self_hosted_instance_public_id: Optional[str] = None,
|
|
57
|
+
self_hosted_instance_slug: Optional[str] = None,
|
|
58
|
+
inference_dir: Optional[str] = None,
|
|
59
|
+
is_skip_installation: Optional[bool] = False,
|
|
60
|
+
files_to_add: Optional[str] = None,
|
|
61
|
+
is_skip_auto_commit: Optional[bool] = False,
|
|
62
|
+
) -> Optional[InferenceSimulator]:
|
|
63
|
+
config = self.__config_provider.get_config()
|
|
64
|
+
project_config: ProjectConfig = self.__project_service.get_fixed_project_config()
|
|
65
|
+
|
|
66
|
+
if not project_config:
|
|
67
|
+
typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first. Or provide path to project using --working-directory option.",
|
|
68
|
+
{"path": config.runtime.working_directory}))
|
|
69
|
+
raise typer.Exit(1)
|
|
70
|
+
|
|
71
|
+
instance_args_count = sum(v is not None for v in [rented_instance_public_id, rented_instance_slug, self_hosted_instance_public_id, self_hosted_instance_slug])
|
|
72
|
+
if instance_args_count != 1:
|
|
73
|
+
typer.echo("Please provide a single instance (rented or self-hosted) identifier - name or ID.")
|
|
74
|
+
raise typer.Exit(1)
|
|
75
|
+
|
|
76
|
+
has_wrong_args = files_to_add and commit_hash or is_skip_auto_commit and commit_hash or files_to_add and is_skip_auto_commit
|
|
77
|
+
if has_wrong_args:
|
|
78
|
+
warning_msg = f"[{ColorScheme.WARNING.value}][WARNING] You can provide only one of the following arguments: --commit-hash, --files-add, --skip-autocommit[{ColorScheme.WARNING.value}]"
|
|
79
|
+
print(warning_msg)
|
|
80
|
+
raise typer.Exit(1)
|
|
81
|
+
|
|
82
|
+
if not is_skip_auto_commit and not commit_hash:
|
|
83
|
+
is_git_folder = self.__git_local_client.is_present_local_git(path=config.runtime.working_directory)
|
|
84
|
+
if not is_git_folder:
|
|
85
|
+
typer.echo("Error: Working directory is not a git repository.")
|
|
86
|
+
raise typer.Exit(1)
|
|
87
|
+
|
|
88
|
+
is_commit_allowed: bool = True
|
|
89
|
+
has_changes = self.__git_local_client.has_changes_with_untracked(
|
|
90
|
+
path=config.runtime.working_directory,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if self.__git_local_client.is_head_detached(path=config.runtime.working_directory):
|
|
94
|
+
print(f"[{ColorScheme.GIT_HEADLESS.value}]HEAD is detached[{ColorScheme.GIT_HEADLESS.value}]")
|
|
95
|
+
|
|
96
|
+
is_headless_commits_present = self.__git_local_client.is_head_committed_in_headless_state(
|
|
97
|
+
path=config.runtime.working_directory)
|
|
98
|
+
if is_headless_commits_present:
|
|
99
|
+
print(
|
|
100
|
+
f"[{ColorScheme.GIT_HEADLESS.value}]Current commit was made in detached head state. Cannot use it to start the inference simulator. Consider using 'project checkout' command to return to a valid reference.[{ColorScheme.GIT_HEADLESS.value}]")
|
|
101
|
+
raise typer.Exit(1)
|
|
102
|
+
|
|
103
|
+
if has_changes:
|
|
104
|
+
print(
|
|
105
|
+
f"[{ColorScheme.GIT_HEADLESS.value}]Local changes detected in detached head state. They will not impact the inference simulator.[{ColorScheme.GIT_HEADLESS.value}]")
|
|
106
|
+
is_commit_allowed = False
|
|
107
|
+
response: YesOrNoResponse = typer.prompt(
|
|
108
|
+
text=__('Continue?'),
|
|
109
|
+
show_choices=True,
|
|
110
|
+
default=YesOrNoResponse.YES.value,
|
|
111
|
+
type=click.Choice([r.value for r in YesOrNoResponse]),
|
|
112
|
+
show_default=True,
|
|
113
|
+
)
|
|
114
|
+
if response == YesOrNoResponse.NO:
|
|
115
|
+
raise typer.Exit(0)
|
|
116
|
+
|
|
117
|
+
if is_commit_allowed:
|
|
118
|
+
if not self.__git_local_client.add_files_with_size_limit_or_warn(config.runtime.working_directory, files_to_add):
|
|
119
|
+
warning_msg = f"[{ColorScheme.WARNING.value}][WARNING] Inference simulator was not started [{ColorScheme.WARNING.value}]"
|
|
120
|
+
print(warning_msg)
|
|
121
|
+
raise typer.Exit(1)
|
|
122
|
+
|
|
123
|
+
diff_stat = self.__git_local_client.git_diff_stat(repo_path=config.runtime.working_directory)
|
|
124
|
+
|
|
125
|
+
if has_changes and diff_stat:
|
|
126
|
+
branch_name = self.__git_local_client.get_active_branch_name(config.runtime.working_directory)
|
|
127
|
+
typer.echo(__('Active branch [%branch_name%] has uncommitted changes: %diff_stat_bottomline%', {
|
|
128
|
+
'diff_stat_bottomline': diff_stat,
|
|
129
|
+
'branch_name': branch_name,
|
|
130
|
+
}))
|
|
131
|
+
|
|
132
|
+
response: str = typer.prompt(
|
|
133
|
+
text=__('Commit changes?'),
|
|
134
|
+
show_choices=True,
|
|
135
|
+
default=YesOrNoResponse.YES.value,
|
|
136
|
+
type=click.Choice([r.value for r in YesOrNoResponse]),
|
|
137
|
+
show_default=True,
|
|
138
|
+
)
|
|
139
|
+
if response == YesOrNoResponse.NO.value:
|
|
140
|
+
typer.echo("inference simulator cannot use uncommitted changes - aborting")
|
|
141
|
+
raise typer.Exit(0)
|
|
142
|
+
|
|
143
|
+
commit_name = typer.prompt(
|
|
144
|
+
text=__('Please provide commit message'),
|
|
145
|
+
show_choices=False,
|
|
146
|
+
type=str,
|
|
147
|
+
show_default=False,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
if commit_name:
|
|
151
|
+
commit_result = self.__git_local_client.commit_local_changes(
|
|
152
|
+
path=config.runtime.working_directory,
|
|
153
|
+
name=commit_name
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
if commit_result:
|
|
157
|
+
# in docs not Commit object, on real - str
|
|
158
|
+
if isinstance(commit_result, str):
|
|
159
|
+
typer.echo(commit_result)
|
|
160
|
+
|
|
161
|
+
self.__git_local_client.push_changes(
|
|
162
|
+
path=config.runtime.working_directory,
|
|
163
|
+
deploy_key_path=project_config.deploy_key_path
|
|
164
|
+
)
|
|
165
|
+
typer.echo(__("Pushed changes to remote repository"))
|
|
166
|
+
else:
|
|
167
|
+
typer.echo(__('Cannot commit with empty commit name, your code will run without last changes.'))
|
|
168
|
+
else:
|
|
169
|
+
pass
|
|
170
|
+
# possible to push new empty branch - only that there's a wrong place to do so
|
|
171
|
+
|
|
172
|
+
if not commit_hash:
|
|
173
|
+
commit = self.__git_local_client.get_current_commit(path=config.runtime.working_directory)
|
|
174
|
+
if commit and isinstance(commit, Commit):
|
|
175
|
+
commit_hash = commit.hexsha
|
|
176
|
+
|
|
177
|
+
start_inference_simulator_response: StartInferenceSimulatorResponse = self.__inference_simulator_api_client.start_project_inference_simulator(
|
|
178
|
+
project_public_id=project_config.public_id,
|
|
179
|
+
commit_hash=commit_hash,
|
|
180
|
+
rented_instance_public_id=rented_instance_public_id,
|
|
181
|
+
rented_instance_slug=rented_instance_slug,
|
|
182
|
+
self_hosted_instance_public_id=self_hosted_instance_public_id,
|
|
183
|
+
self_hosted_instance_slug=self_hosted_instance_slug,
|
|
184
|
+
inference_dir=inference_dir,
|
|
185
|
+
is_skip_installation=is_skip_installation,
|
|
186
|
+
)
|
|
187
|
+
if start_inference_simulator_response:
|
|
188
|
+
if start_inference_simulator_response.message:
|
|
189
|
+
typer.echo(start_inference_simulator_response.message)
|
|
190
|
+
if start_inference_simulator_response.is_success and start_inference_simulator_response.inferenceSimulator:
|
|
191
|
+
typer.echo("Inference simulator has been scheduled to run successfully.")
|
|
192
|
+
return start_inference_simulator_response.inferenceSimulator
|
|
193
|
+
else:
|
|
194
|
+
typer.echo(__(
|
|
195
|
+
'Failed to start inference simulator: %server_massage%',
|
|
196
|
+
{'server_massage': start_inference_simulator_response.message or ""}
|
|
197
|
+
))
|
|
198
|
+
raise typer.Exit(1)
|
|
199
|
+
else:
|
|
200
|
+
typer.echo(__("Failed to start inference simulator"))
|
|
201
|
+
raise typer.Exit(1)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@error_handler()
|
|
205
|
+
def project_push_inference_simulator(
|
|
206
|
+
self,
|
|
207
|
+
public_id: Optional[str] = None,
|
|
208
|
+
slug: Optional[str] = None,
|
|
209
|
+
):
|
|
210
|
+
|
|
211
|
+
push_inference_simulator_model_response: PushInferenceSimulatorModelResponse = self.__inference_model_api_client.push_project_inference_simulator_model(
|
|
212
|
+
public_id=public_id,
|
|
213
|
+
slug=slug,
|
|
214
|
+
)
|
|
215
|
+
if push_inference_simulator_model_response:
|
|
216
|
+
if push_inference_simulator_model_response.message:
|
|
217
|
+
typer.echo(push_inference_simulator_model_response.message)
|
|
218
|
+
if push_inference_simulator_model_response.is_success:
|
|
219
|
+
typer.echo("Inference simulator has been successfully scheduled to be pushed to S3 and ECR.")
|
|
220
|
+
else:
|
|
221
|
+
typer.echo(__(
|
|
222
|
+
'Failed to push inference simulator: %server_massage%',
|
|
223
|
+
{'server_massage': push_inference_simulator_model_response.message or ""}
|
|
224
|
+
))
|
|
225
|
+
raise typer.Exit(1)
|
|
226
|
+
else:
|
|
227
|
+
typer.echo(__("Failed to push inference simulator"))
|
|
228
|
+
raise typer.Exit(1)
|
|
229
|
+
|
|
230
|
+
@error_handler()
|
|
231
|
+
def project_get_and_save_inference_simulator_metadata(
|
|
232
|
+
self,
|
|
233
|
+
inference_simulator_public_id: Optional[str] = None,
|
|
234
|
+
inference_simulator_slug: Optional[str] = None,
|
|
235
|
+
file_path: Optional[str] = None,
|
|
236
|
+
):
|
|
237
|
+
get_inference_metadata_response: GetInferenceSimulatorResponse = self.__inference_simulator_api_client.get_inference_simulator(
|
|
238
|
+
public_id=inference_simulator_public_id,
|
|
239
|
+
slug=inference_simulator_slug,
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
metadata = get_inference_metadata_response.inferenceSimulator.qlip_serve_metadata
|
|
243
|
+
|
|
244
|
+
if metadata:
|
|
245
|
+
typer.echo("qlip_serve_metadata:")
|
|
246
|
+
typer.echo(json.dumps(metadata, indent=4))
|
|
247
|
+
|
|
248
|
+
if not file_path:
|
|
249
|
+
file_path = Path(os.getcwd()) / "metadata.json"
|
|
250
|
+
typer.echo(__("No file path provided. Saving metadata to %file_path%", {"file_path": str(file_path)}))
|
|
251
|
+
|
|
252
|
+
try:
|
|
253
|
+
parsed_metadata = metadata
|
|
254
|
+
|
|
255
|
+
output_file = Path(file_path)
|
|
256
|
+
output_file.parent.mkdir(parents=True, exist_ok=True)
|
|
257
|
+
with output_file.open("w", encoding="utf-8") as file:
|
|
258
|
+
json.dump(parsed_metadata, file, indent=4)
|
|
259
|
+
typer.echo(__("Metadata successfully saved to %file_path%", {"file_path": str(file_path)}))
|
|
260
|
+
except Exception as e:
|
|
261
|
+
typer.echo(__("Failed to save metadata to %file_path%. Error: %error%",
|
|
262
|
+
{"file_path": file_path, "error": str(e)}))
|
|
263
|
+
raise typer.Exit(1)
|
|
264
|
+
else:
|
|
265
|
+
typer.echo(__("No qlip_serve_metadata found"))
|
|
266
|
+
raise typer.Exit(1)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@error_handler()
|
|
270
|
+
def get_project_inference_simulator_list(
|
|
271
|
+
self,
|
|
272
|
+
project_public_id: Optional[str],
|
|
273
|
+
project_slug: Optional[str],
|
|
274
|
+
statuses: List[str],
|
|
275
|
+
row: int = 5,
|
|
276
|
+
page: int = 1,
|
|
277
|
+
) -> PaginatedEntityList[InferenceSimulator]:
|
|
278
|
+
data: Optional[PaginatedEntityList[InferenceSimulator]] = self.__inference_simulator_api_client.get_inference_simulator_list(
|
|
279
|
+
statuses=statuses,
|
|
280
|
+
project_public_id=project_public_id,
|
|
281
|
+
project_slug=project_slug,
|
|
282
|
+
page=page,
|
|
283
|
+
limit=row,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
return data
|
|
287
|
+
|
|
288
|
+
@error_handler()
|
|
289
|
+
def print_inference_simulator_list(self, project_public_id, project_slug, statuses, row, page):
|
|
290
|
+
if not project_public_id and not project_slug:
|
|
291
|
+
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
292
|
+
if not project_config:
|
|
293
|
+
typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
|
|
294
|
+
raise typer.Exit(1)
|
|
295
|
+
project_public_id = project_config.public_id
|
|
296
|
+
|
|
297
|
+
inference_simulator_status_map = self.__inference_simulator_api_client.get_inference_simulator_business_status_map()
|
|
298
|
+
|
|
299
|
+
if not statuses:
|
|
300
|
+
statuses = ({key: inference_simulator_status_map[key] for key in [
|
|
301
|
+
InferenceSimulatorStatus.SCHEDULED,
|
|
302
|
+
InferenceSimulatorStatus.CREATING,
|
|
303
|
+
InferenceSimulatorStatus.RUNNING,
|
|
304
|
+
]}).values()
|
|
305
|
+
|
|
306
|
+
if "all" in statuses:
|
|
307
|
+
statuses = inference_simulator_status_map.values()
|
|
308
|
+
|
|
309
|
+
for input_status_item in statuses:
|
|
310
|
+
if input_status_item not in inference_simulator_status_map.values():
|
|
311
|
+
typer.echo(__("'%invalid_status%' is not one of %valid_statuses%", {
|
|
312
|
+
'invalid_status': input_status_item,
|
|
313
|
+
'valid_statuses': str(list(inference_simulator_status_map.values()))
|
|
314
|
+
}))
|
|
315
|
+
raise typer.Exit(1)
|
|
316
|
+
|
|
317
|
+
typer.echo(__(
|
|
318
|
+
"Listing inference simulators with the following statuses: %statuses%, to view all inference simulators, use --status all",
|
|
319
|
+
placeholders={
|
|
320
|
+
'statuses': ', '.join([status_item for status_item in statuses])
|
|
321
|
+
}))
|
|
322
|
+
|
|
323
|
+
backend_statuses: List[str] = [key for key, value in inference_simulator_status_map.items() if value in statuses]
|
|
324
|
+
|
|
325
|
+
self.print(
|
|
326
|
+
func_get_data=self.get_project_inference_simulator_list,
|
|
327
|
+
func_special_params={
|
|
328
|
+
'project_public_id': project_public_id,
|
|
329
|
+
'project_slug': project_slug,
|
|
330
|
+
'statuses': backend_statuses,
|
|
331
|
+
},
|
|
332
|
+
mapper=InferenceSimulatorMapper(),
|
|
333
|
+
headers=list(map(lambda x: x.alias, InferenceSimulatorEntity.model_fields.values())),
|
|
334
|
+
row=row,
|
|
335
|
+
page=page,
|
|
336
|
+
max_col_width=[100, 100, 100, 100, 100, 100, 100, 100],
|
|
337
|
+
show_index="never",
|
|
338
|
+
)
|
|
File without changes
|