thestage 0.6.6__py3-none-any.whl → 0.6.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- thestage/__init__.py +1 -1
- thestage/controllers/container_controller.py +13 -66
- thestage/controllers/instance_controller.py +4 -4
- thestage/controllers/project_controller.py +8 -10
- thestage/entities/project_inference_simulator_model.py +1 -1
- thestage/helpers/error_handler.py +2 -2
- thestage/main.py +1 -1
- thestage/services/clients/git/git_client.py +1 -1
- thestage/services/clients/thestage_api/api_client.py +3 -5
- thestage/services/clients/thestage_api/dtos/base_controller/connect_resolve_response.py +1 -0
- thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_request.py +0 -2
- thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py +2 -0
- thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py +1 -1
- thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py +3 -0
- thestage/services/connect/connect_service.py +6 -6
- thestage/services/container/container_service.py +97 -22
- thestage/services/logging/logging_service.py +5 -8
- thestage/services/project/dto/project_config.py +1 -2
- thestage/services/project/project_service.py +16 -12
- {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/METADATA +2 -1
- {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/RECORD +24 -24
- {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/WHEEL +0 -0
- {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/entry_points.txt +0 -0
- {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/licenses/LICENSE.txt +0 -0
thestage/__init__.py
CHANGED
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
import re
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Optional, List
|
|
5
|
+
from rich import print
|
|
5
6
|
|
|
6
7
|
from thestage.cli_command import CliCommand
|
|
7
8
|
from thestage.cli_command_helper import get_command_metadata, check_command_permission
|
|
9
|
+
from thestage.color_scheme.color_scheme import ColorScheme
|
|
10
|
+
from thestage.services.clients.thestage_api.api_client import TheStageApiClient
|
|
8
11
|
from thestage.services.clients.thestage_api.dtos.enums.container_pending_action import DockerContainerAction
|
|
9
12
|
from thestage.services.clients.thestage_api.dtos.container_response import DockerContainerDto
|
|
10
13
|
from thestage.i18n.translation import __
|
|
@@ -215,7 +218,7 @@ def container_connect(
|
|
|
215
218
|
@app.command(name="upload", no_args_is_help=True, help=__("Upload file to container"), **get_command_metadata(CliCommand.CONTAINER_UPLOAD))
|
|
216
219
|
def upload_file(
|
|
217
220
|
source_path: str = typer.Argument(help=__("Source file path"),),
|
|
218
|
-
destination: Optional[str] = typer.Argument(help=__("Destination directory path in container. Format:
|
|
221
|
+
destination: Optional[str] = typer.Argument(help=__("Destination directory path in container. Format: container_id_or_name:/path/to/file"),),
|
|
219
222
|
username: Optional[str] = typer.Option(
|
|
220
223
|
None,
|
|
221
224
|
'--username',
|
|
@@ -228,50 +231,22 @@ def upload_file(
|
|
|
228
231
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
229
232
|
check_command_permission(command_name)
|
|
230
233
|
|
|
231
|
-
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", destination)
|
|
232
|
-
|
|
233
|
-
if container_args is None:
|
|
234
|
-
typer.echo(__('Container name and source file path are required as the second argument'))
|
|
235
|
-
typer.echo(__('Example: container_uid:/path/to/file'))
|
|
236
|
-
raise typer.Exit(1)
|
|
237
|
-
container_slug = container_args.groups()[0]
|
|
238
|
-
destination_path = container_args.groups()[1].rstrip("/")
|
|
239
|
-
|
|
240
|
-
if not container_slug:
|
|
241
|
-
typer.echo(__('Container name is required'))
|
|
242
|
-
raise typer.Exit(1)
|
|
243
|
-
|
|
244
234
|
service_factory = validate_config_and_get_service_factory()
|
|
245
235
|
container_service: ContainerService = service_factory.get_container_service()
|
|
246
236
|
|
|
247
|
-
|
|
248
|
-
|
|
237
|
+
container_service.put_file_to_container(
|
|
238
|
+
source_path=source_path,
|
|
239
|
+
destination=destination,
|
|
240
|
+
username_param=username,
|
|
249
241
|
)
|
|
250
242
|
|
|
251
|
-
if container:
|
|
252
|
-
container_service.check_if_container_running(
|
|
253
|
-
container=container
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
typer.echo(f"Uploading file(s) to container '{container_slug}'")
|
|
257
|
-
|
|
258
|
-
container_service.put_file_to_container(
|
|
259
|
-
container=container,
|
|
260
|
-
src_path=source_path,
|
|
261
|
-
destination_path=destination_path,
|
|
262
|
-
username_param=username,
|
|
263
|
-
copy_only_folder_contents=source_path.endswith("/")
|
|
264
|
-
)
|
|
265
|
-
else:
|
|
266
|
-
typer.echo(__("Container not found: %container_item%", {'container_item': container_slug}))
|
|
267
|
-
|
|
268
243
|
app_logger.info(f'End send files to container')
|
|
269
244
|
raise typer.Exit(0)
|
|
270
245
|
|
|
271
246
|
|
|
272
247
|
@app.command(name="download", no_args_is_help=True, help=__("Download file from container"), **get_command_metadata(CliCommand.CONTAINER_DOWNLOAD))
|
|
273
248
|
def download_file(
|
|
274
|
-
|
|
249
|
+
source: str = typer.Argument(help=__("Source file path in container. Format: container_name:/path/to/file"),),
|
|
275
250
|
destination_path: str = typer.Argument(help=__("Destination directory path on local machine"),),
|
|
276
251
|
username: Optional[str] = typer.Option(
|
|
277
252
|
None,
|
|
@@ -285,43 +260,15 @@ def download_file(
|
|
|
285
260
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
286
261
|
check_command_permission(command_name)
|
|
287
262
|
|
|
288
|
-
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", source_path)
|
|
289
|
-
|
|
290
|
-
if container_args is None:
|
|
291
|
-
typer.echo(__('Container name and source directory path are required as the first argument'))
|
|
292
|
-
typer.echo(__('Example: container-uid:/path/to/file'))
|
|
293
|
-
raise typer.Exit(1)
|
|
294
|
-
container_slug = container_args.groups()[0]
|
|
295
|
-
source_path = container_args.groups()[1]
|
|
296
|
-
|
|
297
|
-
if not container_slug:
|
|
298
|
-
typer.echo(__('Container name is required'))
|
|
299
|
-
raise typer.Exit(1)
|
|
300
|
-
|
|
301
263
|
service_factory = validate_config_and_get_service_factory()
|
|
302
264
|
container_service: ContainerService = service_factory.get_container_service()
|
|
303
265
|
|
|
304
|
-
|
|
305
|
-
|
|
266
|
+
container_service.get_file_from_container(
|
|
267
|
+
source=source,
|
|
268
|
+
destination_path=destination_path.rstrip("/"),
|
|
269
|
+
username_param=username,
|
|
306
270
|
)
|
|
307
271
|
|
|
308
|
-
if container:
|
|
309
|
-
container_service.check_if_container_running(
|
|
310
|
-
container=container
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
typer.echo(f"Downloading files from container: '{container_slug}'")
|
|
314
|
-
|
|
315
|
-
container_service.get_file_from_container(
|
|
316
|
-
container=container,
|
|
317
|
-
src_path=source_path,
|
|
318
|
-
destination_path=destination_path.rstrip("/"),
|
|
319
|
-
username_param=username,
|
|
320
|
-
copy_only_folder_contents=source_path.endswith("/"),
|
|
321
|
-
)
|
|
322
|
-
else:
|
|
323
|
-
typer.echo(f"Container not found: {container_slug}")
|
|
324
|
-
|
|
325
272
|
app_logger.info(f'End download files from container')
|
|
326
273
|
raise typer.Exit(0)
|
|
327
274
|
|
|
@@ -66,14 +66,14 @@ def rented_list(
|
|
|
66
66
|
def instance_connect(
|
|
67
67
|
public_id: Optional[str] = typer.Option(
|
|
68
68
|
None,
|
|
69
|
-
'--id',
|
|
69
|
+
'--rented-instance-id',
|
|
70
70
|
'-rid',
|
|
71
71
|
help="Rented instance ID",
|
|
72
72
|
is_eager=False,
|
|
73
73
|
),
|
|
74
74
|
slug: Optional[str] = typer.Option(
|
|
75
75
|
None,
|
|
76
|
-
'--name',
|
|
76
|
+
'--rented-instance-name',
|
|
77
77
|
'-rn',
|
|
78
78
|
help="Rented instance name",
|
|
79
79
|
is_eager=False,
|
|
@@ -156,14 +156,14 @@ def self_hosted_list(
|
|
|
156
156
|
def self_hosted_connect(
|
|
157
157
|
public_id: Optional[str] = typer.Option(
|
|
158
158
|
None,
|
|
159
|
-
'--id',
|
|
159
|
+
'--self-hosted-instance-id',
|
|
160
160
|
'-sid',
|
|
161
161
|
help="Self-hosted instance ID",
|
|
162
162
|
is_eager=False,
|
|
163
163
|
),
|
|
164
164
|
slug: Optional[str] = typer.Option(
|
|
165
165
|
None,
|
|
166
|
-
'--name',
|
|
166
|
+
'--self-hosted-instance-name',
|
|
167
167
|
'-sn',
|
|
168
168
|
help="Self-hosted instance name",
|
|
169
169
|
is_eager=False,
|
|
@@ -63,7 +63,8 @@ def clone(
|
|
|
63
63
|
raise typer.Exit(1)
|
|
64
64
|
|
|
65
65
|
if not working_directory:
|
|
66
|
-
|
|
66
|
+
project_dir_name = project_public_id if project_slug is None else project_slug
|
|
67
|
+
working_directory = get_current_directory().joinpath(project_dir_name)
|
|
67
68
|
|
|
68
69
|
service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
|
|
69
70
|
project_service = service_factory.get_project_service()
|
|
@@ -842,7 +843,7 @@ def inference_simulator_logs(
|
|
|
842
843
|
),
|
|
843
844
|
slug: Optional[str] = typer.Option(
|
|
844
845
|
None,
|
|
845
|
-
'--name',
|
|
846
|
+
'--inference-simulator-name',
|
|
846
847
|
'-isn',
|
|
847
848
|
help="Inference simulator name",
|
|
848
849
|
is_eager=False,
|
|
@@ -952,17 +953,14 @@ def deploy_inference_simulator_model_to_instance(
|
|
|
952
953
|
check_command_permission(command_name)
|
|
953
954
|
|
|
954
955
|
if model_slug and not re.match(r"^[a-zA-Z0-9-]+$", model_slug):
|
|
955
|
-
raise typer.BadParameter(
|
|
956
|
-
|
|
957
|
-
new_inference_simulator_slug = f"{model_slug}-{int(time.time())}"
|
|
956
|
+
raise typer.BadParameter("Invalid name format. Name can only contain letters, numbers, and hyphens.")
|
|
958
957
|
|
|
959
958
|
service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
|
|
960
959
|
project_service = service_factory.get_project_service()
|
|
961
960
|
|
|
962
|
-
project_service.project_deploy_inference_simulator_model_to_instance(
|
|
961
|
+
inference_simulator_public_id = project_service.project_deploy_inference_simulator_model_to_instance(
|
|
963
962
|
model_public_id=model_public_id,
|
|
964
963
|
model_slug=model_slug,
|
|
965
|
-
new_inference_simulator_slug=new_inference_simulator_slug,
|
|
966
964
|
rented_instance_public_id=rented_instance_public_id,
|
|
967
965
|
rented_instance_slug=rented_instance_slug,
|
|
968
966
|
self_hosted_instance_public_id=self_hosted_instance_public_id,
|
|
@@ -973,7 +971,7 @@ def deploy_inference_simulator_model_to_instance(
|
|
|
973
971
|
logging_service: LoggingService = service_factory.get_logging_service()
|
|
974
972
|
|
|
975
973
|
logging_service.stream_inference_simulator_logs_with_controls(
|
|
976
|
-
|
|
974
|
+
public_id=inference_simulator_public_id
|
|
977
975
|
)
|
|
978
976
|
raise typer.Exit(0)
|
|
979
977
|
|
|
@@ -982,14 +980,14 @@ def deploy_inference_simulator_model_to_instance(
|
|
|
982
980
|
def deploy_inference_simulator_model_to_sagemaker(
|
|
983
981
|
model_public_id: Optional[str] = typer.Option(
|
|
984
982
|
None,
|
|
985
|
-
'--id',
|
|
983
|
+
'--model-id',
|
|
986
984
|
'-mid',
|
|
987
985
|
help="Inference simulator model ID",
|
|
988
986
|
is_eager=False,
|
|
989
987
|
),
|
|
990
988
|
model_slug: Optional[str] = typer.Option(
|
|
991
989
|
None,
|
|
992
|
-
'--name',
|
|
990
|
+
'--model-name',
|
|
993
991
|
'-mn',
|
|
994
992
|
help="Inference simulator model name",
|
|
995
993
|
is_eager=False,
|
|
@@ -11,7 +11,7 @@ class ProjectInferenceSimulatorModelEntity(BaseModel):
|
|
|
11
11
|
)
|
|
12
12
|
|
|
13
13
|
public_id: Optional[str] = Field(None, alias='ID')
|
|
14
|
-
slug: Optional[str] = Field(None, alias='
|
|
14
|
+
slug: Optional[str] = Field(None, alias='NAME')
|
|
15
15
|
status: Optional[str] = Field(None, alias='STATUS')
|
|
16
16
|
commit_hash: Optional[str] = Field(None, alias='COMMIT_HASH')
|
|
17
17
|
environment_metadata: Optional[Dict[str, Any]] = Field(None, alias='ENVIRONMENT_METADATA')
|
|
@@ -106,8 +106,8 @@ def error_handler() -> Callable:
|
|
|
106
106
|
raise e100
|
|
107
107
|
else:
|
|
108
108
|
typer.echo(__('Undefined error occurred'))
|
|
109
|
-
typer.echo(e100.__class__.__name__)
|
|
110
|
-
print(traceback.format_exc())
|
|
109
|
+
# typer.echo(e100.__class__.__name__)
|
|
110
|
+
# print(traceback.format_exc())
|
|
111
111
|
# TODO send all exceptions to backend?
|
|
112
112
|
app_logger.error(f'{traceback.format_exc()}')
|
|
113
113
|
raise typer.Exit(1)
|
thestage/main.py
CHANGED
|
@@ -19,7 +19,7 @@ def main():
|
|
|
19
19
|
config_provider.update_allowed_commands_and_is_token_valid(validate_token_response=token_info)
|
|
20
20
|
except Exception as e:
|
|
21
21
|
app_logger.error(f'{traceback.format_exc()}')
|
|
22
|
-
print('
|
|
22
|
+
print('Error connecting to TheStage servers') # TODO inquire what we want here if backend is offline
|
|
23
23
|
print(f'Application logs path: {str(get_log_path_from_os())}')
|
|
24
24
|
return
|
|
25
25
|
|
|
@@ -196,7 +196,7 @@ class GitLocalClient:
|
|
|
196
196
|
) -> Optional[str]:
|
|
197
197
|
repo = self.__get_repo(path=path)
|
|
198
198
|
if repo.head.is_detached:
|
|
199
|
-
line_color = ColorScheme.GIT_HEADLESS
|
|
199
|
+
line_color = ColorScheme.GIT_HEADLESS.value
|
|
200
200
|
print(f'[{line_color}]Committing in detached head state at {repo.head.commit.hexsha}[/{line_color}]')
|
|
201
201
|
commit_name = name if name else f"Auto commit {str(datetime.datetime.now().date())}"
|
|
202
202
|
commit = repo.git.commit('--allow-empty', '-m', commit_name, )
|
|
@@ -667,7 +667,6 @@ class TheStageApiClient(TheStageApiClientCore):
|
|
|
667
667
|
self,
|
|
668
668
|
model_public_id: str,
|
|
669
669
|
model_slug: str,
|
|
670
|
-
new_inference_simulator_slug: str,
|
|
671
670
|
rented_instance_public_id: Optional[str] = None,
|
|
672
671
|
rented_instance_slug: Optional[str] = None,
|
|
673
672
|
self_hosted_instance_public_id: Optional[str] = None,
|
|
@@ -675,10 +674,9 @@ class TheStageApiClient(TheStageApiClientCore):
|
|
|
675
674
|
|
|
676
675
|
) -> Optional[DeployInferenceModelToInstanceResponse]:
|
|
677
676
|
request = DeployInferenceModelToInstanceRequest(
|
|
678
|
-
inferenceSimulatorSlug=new_inference_simulator_slug,
|
|
679
677
|
modelPublicId=model_public_id,
|
|
680
678
|
modelSlug=model_slug,
|
|
681
|
-
|
|
679
|
+
instanceRentedPublicId=rented_instance_public_id,
|
|
682
680
|
instanceRentedSlug=rented_instance_slug,
|
|
683
681
|
selfhostedInstancePublicId=self_hosted_instance_public_id,
|
|
684
682
|
selfhostedInstanceSlug=self_hosted_instance_slug
|
|
@@ -735,7 +733,7 @@ class TheStageApiClient(TheStageApiClientCore):
|
|
|
735
733
|
return result
|
|
736
734
|
|
|
737
735
|
|
|
738
|
-
def
|
|
736
|
+
def resolve_user_input(
|
|
739
737
|
self,
|
|
740
738
|
entity_identifier: str
|
|
741
739
|
) -> Optional[ConnectResolveOptionsResponse]:
|
|
@@ -745,7 +743,7 @@ class TheStageApiClient(TheStageApiClientCore):
|
|
|
745
743
|
|
|
746
744
|
response = self._request(
|
|
747
745
|
method='POST',
|
|
748
|
-
url='/user-api/v1/
|
|
746
|
+
url='/user-api/v1/resolve-user-input',
|
|
749
747
|
data=data,
|
|
750
748
|
token=self.__config_provider.get_config().main.thestage_auth_token,
|
|
751
749
|
)
|
|
@@ -11,6 +11,7 @@ class EntityMatchData(BaseModel):
|
|
|
11
11
|
publicId: str = Field(alias='publicId')
|
|
12
12
|
frontendStatus: FrontendStatusDto = Field(alias='frontendStatus')
|
|
13
13
|
canConnect: bool = Field(alias='canConnect')
|
|
14
|
+
canDownloadUploadOnContainer: bool = Field(alias='canDownloadUploadOnContainer')
|
|
14
15
|
matchedField: Optional[str] = Field(None, alias='matchedField')
|
|
15
16
|
|
|
16
17
|
|
|
@@ -16,5 +16,3 @@ class DeployInferenceModelToInstanceRequest(BaseModel):
|
|
|
16
16
|
|
|
17
17
|
selfhostedInstancePublicId: Optional[str] = Field(None, alias='selfhostedInstancePublicId')
|
|
18
18
|
selfhostedInstanceSlug: Optional[str] = Field(None, alias='selfhostedInstanceSlug')
|
|
19
|
-
|
|
20
|
-
inferenceSimulatorSlug: Optional[str] = Field(None, alias='inferenceSimulatorSlug')
|
|
@@ -9,4 +9,6 @@ from thestage.services.project.dto.inference_simulator_model_dto import Inferenc
|
|
|
9
9
|
class DeployInferenceModelToInstanceResponse(TheStageBaseResponse):
|
|
10
10
|
model_config = ConfigDict(use_enum_values=True)
|
|
11
11
|
|
|
12
|
+
inferenceSimulatorPublicId: Optional[str] = Field(None, alias='inferenceSimulatorPublicId')
|
|
13
|
+
|
|
12
14
|
|
thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py
CHANGED
|
@@ -8,5 +8,5 @@ from thestage.services.clients.thestage_api.dtos.entity_filter_request import En
|
|
|
8
8
|
class GetInferenceSimulatorRequest(BaseModel):
|
|
9
9
|
model_config = ConfigDict(use_enum_values=True)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
publicId: Optional[str] = Field(None, alias='publicId')
|
|
12
12
|
slug: Optional[str] = Field(None, alias='slug')
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Optional, List
|
|
2
|
+
|
|
1
3
|
from pydantic import Field, ConfigDict
|
|
2
4
|
|
|
3
5
|
from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
|
|
@@ -8,3 +10,4 @@ class ProjectRunTaskResponse(TheStageBaseResponse):
|
|
|
8
10
|
model_config = ConfigDict(use_enum_values=True)
|
|
9
11
|
|
|
10
12
|
task: TaskDto = Field(None, alias='task')
|
|
13
|
+
tasksInQueue: Optional[List[TaskDto]] = Field(None, alias='tasksInQueue')
|
|
@@ -45,7 +45,7 @@ class ConnectService(AbstractService):
|
|
|
45
45
|
username: Optional[str],
|
|
46
46
|
private_key_path: Optional[str],
|
|
47
47
|
):
|
|
48
|
-
resolved_options = self.__thestage_api_client.
|
|
48
|
+
resolved_options = self.__thestage_api_client.resolve_user_input(entity_identifier=input_entity_identifier)
|
|
49
49
|
entities_available_for_connect_count = 0
|
|
50
50
|
task_presence = False
|
|
51
51
|
container_presence = False
|
|
@@ -56,7 +56,7 @@ class ConnectService(AbstractService):
|
|
|
56
56
|
if resolved_options.taskMatchData:
|
|
57
57
|
for task_item in resolved_options.taskMatchData:
|
|
58
58
|
message = f"Found a task with with matching {task_item.matchedField} in status: '{task_item.frontendStatus.status_translation}' (ID: {task_item.publicId})"
|
|
59
|
-
line_color = ColorScheme.SUCCESS if task_item.canConnect else 'default'
|
|
59
|
+
line_color = ColorScheme.SUCCESS.value if task_item.canConnect else 'default'
|
|
60
60
|
print(f"[{line_color}]{message}[{line_color}]")
|
|
61
61
|
if task_item.canConnect:
|
|
62
62
|
task_presence = True
|
|
@@ -66,7 +66,7 @@ class ConnectService(AbstractService):
|
|
|
66
66
|
if resolved_options.dockerContainerMatchData:
|
|
67
67
|
for container_item in resolved_options.dockerContainerMatchData:
|
|
68
68
|
message = f"Found a container with matching {container_item.matchedField} in status: '{container_item.frontendStatus.status_translation}' (ID: {container_item.publicId})"
|
|
69
|
-
line_color = ColorScheme.SUCCESS if container_item.canConnect else 'default'
|
|
69
|
+
line_color = ColorScheme.SUCCESS.value if container_item.canConnect else 'default'
|
|
70
70
|
print(f"[{line_color}]{message}[{line_color}]")
|
|
71
71
|
if container_item.canConnect:
|
|
72
72
|
container_presence = True
|
|
@@ -76,7 +76,7 @@ class ConnectService(AbstractService):
|
|
|
76
76
|
if resolved_options.instanceRentedMatchData:
|
|
77
77
|
for instance_rented_item in resolved_options.instanceRentedMatchData:
|
|
78
78
|
message = f"Found a rented instance with matching {instance_rented_item.matchedField} in status: '{instance_rented_item.frontendStatus.status_translation}' (ID: {instance_rented_item.publicId})"
|
|
79
|
-
line_color = ColorScheme.SUCCESS if instance_rented_item.canConnect else 'default'
|
|
79
|
+
line_color = ColorScheme.SUCCESS.value if instance_rented_item.canConnect else 'default'
|
|
80
80
|
print(f"[{line_color}]{message}[{line_color}]")
|
|
81
81
|
|
|
82
82
|
if instance_rented_item.canConnect:
|
|
@@ -87,7 +87,7 @@ class ConnectService(AbstractService):
|
|
|
87
87
|
if resolved_options.selfhostedInstanceMatchData:
|
|
88
88
|
for selfhosted_item in resolved_options.selfhostedInstanceMatchData:
|
|
89
89
|
message = f"Found a self-hosted instance with matching {selfhosted_item.matchedField} in status: '{selfhosted_item.frontendStatus.status_translation}' (ID: {selfhosted_item.publicId})"
|
|
90
|
-
line_color = ColorScheme.SUCCESS if selfhosted_item.canConnect else 'default'
|
|
90
|
+
line_color = ColorScheme.SUCCESS.value if selfhosted_item.canConnect else 'default'
|
|
91
91
|
print(f"[{line_color}]{message}[{line_color}]")
|
|
92
92
|
|
|
93
93
|
if selfhosted_item.canConnect:
|
|
@@ -153,7 +153,7 @@ class ConnectService(AbstractService):
|
|
|
153
153
|
|
|
154
154
|
# if no instances found - exit 1
|
|
155
155
|
if instance_rented is None:
|
|
156
|
-
typer.echo(f"No rented instance found with matching
|
|
156
|
+
typer.echo(f"No rented instance found with matching identifier")
|
|
157
157
|
raise typer.Exit(1)
|
|
158
158
|
|
|
159
159
|
note_to_send: Optional[str] = None
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
from typing import List, Tuple, Optional, Dict
|
|
4
|
+
from rich import print
|
|
3
5
|
|
|
4
6
|
import typer
|
|
7
|
+
|
|
8
|
+
from thestage.color_scheme.color_scheme import ColorScheme
|
|
5
9
|
from thestage.entities.container import DockerContainerEntity
|
|
6
10
|
from thestage.services.clients.thestage_api.dtos.container_param_request import DockerContainerActionRequestDto
|
|
7
11
|
from thestage.services.clients.thestage_api.dtos.enums.container_pending_action import DockerContainerAction
|
|
@@ -150,7 +154,7 @@ class ContainerService(AbstractService):
|
|
|
150
154
|
if private_key_path:
|
|
151
155
|
typer.echo(f'Using configured private key for {ip_address}: {private_key_path}')
|
|
152
156
|
else:
|
|
153
|
-
typer.echo(f'Using SSH agent to connect to {ip_address}')
|
|
157
|
+
typer.echo(f'Using SSH agent to connect to {ip_address} as {username}')
|
|
154
158
|
else:
|
|
155
159
|
self.__config_provider.update_remote_server_config_entry(ip_address, Path(private_key_path))
|
|
156
160
|
typer.echo(f'Updated private key path for {ip_address}: {private_key_path}')
|
|
@@ -267,22 +271,49 @@ class ContainerService(AbstractService):
|
|
|
267
271
|
@error_handler()
|
|
268
272
|
def put_file_to_container(
|
|
269
273
|
self,
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
destination_path: Optional[str] = None,
|
|
274
|
-
username_param: Optional[str] = None,
|
|
274
|
+
source_path: str,
|
|
275
|
+
destination: str,
|
|
276
|
+
username_param: Optional[str],
|
|
275
277
|
):
|
|
276
|
-
|
|
277
|
-
|
|
278
|
+
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", destination)
|
|
279
|
+
if container_args is None:
|
|
280
|
+
typer.echo(__('Container name and source file path are required as the second argument'))
|
|
281
|
+
typer.echo(__('Example: container_name:/path/to/file'))
|
|
278
282
|
raise typer.Exit(1)
|
|
283
|
+
container_identifier = container_args.groups()[0]
|
|
284
|
+
destination_path = container_args.groups()[1].rstrip("/")
|
|
279
285
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
286
|
+
if not container_identifier:
|
|
287
|
+
typer.echo('Container identifier (container_id_or_name) is required')
|
|
288
|
+
raise typer.Exit(1)
|
|
289
|
+
|
|
290
|
+
resolved_options = self.__thestage_api_client.resolve_user_input(entity_identifier=container_identifier)
|
|
291
|
+
container_public_id = None
|
|
292
|
+
valid_container_count = 0
|
|
293
|
+
for container_item in resolved_options.dockerContainerMatchData:
|
|
294
|
+
message = f"Found a container with matching {container_item.matchedField} in status: '{container_item.frontendStatus.status_translation}' (ID: {container_item.publicId})"
|
|
295
|
+
line_color = ColorScheme.SUCCESS.value if container_item.canDownloadUploadOnContainer else 'default'
|
|
296
|
+
print(f"[{line_color}]{message}[{line_color}]")
|
|
297
|
+
if container_item.canDownloadUploadOnContainer:
|
|
298
|
+
valid_container_count += 1
|
|
299
|
+
container_public_id = container_item.publicId
|
|
300
|
+
|
|
301
|
+
if valid_container_count != 1:
|
|
302
|
+
typer.echo(f"Failed to resolve the container by provided identifier, as total of {valid_container_count} containers are valid options")
|
|
303
|
+
raise typer.Exit(1)
|
|
304
|
+
|
|
305
|
+
container: Optional[DockerContainerDto] = self.__thestage_api_client.get_container(
|
|
306
|
+
container_public_id=container_public_id,
|
|
284
307
|
)
|
|
285
308
|
|
|
309
|
+
if not container:
|
|
310
|
+
typer.echo(f"Unexpected error: container '{container_public_id}' not found")
|
|
311
|
+
raise typer.Exit(1)
|
|
312
|
+
|
|
313
|
+
if not self.__file_system_service.check_if_path_exist(file=source_path):
|
|
314
|
+
typer.echo(__("File not found at specified path"))
|
|
315
|
+
raise typer.Exit(1)
|
|
316
|
+
|
|
286
317
|
if not container.mappings or not container.mappings.directory_mappings:
|
|
287
318
|
typer.echo(__("Mapping folders not found"))
|
|
288
319
|
raise typer.Exit(1)
|
|
@@ -296,10 +327,18 @@ class ContainerService(AbstractService):
|
|
|
296
327
|
typer.echo(__("Cannot find matching container volume mapping for specified file path"))
|
|
297
328
|
raise typer.Exit(1)
|
|
298
329
|
|
|
330
|
+
username, ip_address, private_key_path = self.get_server_auth(
|
|
331
|
+
container=container,
|
|
332
|
+
username_param=username_param,
|
|
333
|
+
private_key_path_override=None
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
copy_only_folder_contents = source_path.endswith("/")
|
|
337
|
+
|
|
299
338
|
self.__remote_server_service.upload_data_to_container(
|
|
300
339
|
ip_address=ip_address,
|
|
301
340
|
username=username,
|
|
302
|
-
src_path=
|
|
341
|
+
src_path=source_path,
|
|
303
342
|
dest_path=destination_path,
|
|
304
343
|
instance_path=instance_path,
|
|
305
344
|
container_path=container_path,
|
|
@@ -310,31 +349,67 @@ class ContainerService(AbstractService):
|
|
|
310
349
|
@error_handler()
|
|
311
350
|
def get_file_from_container(
|
|
312
351
|
self,
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
copy_only_folder_contents: bool,
|
|
316
|
-
destination_path: Optional[str] = None,
|
|
352
|
+
source: str,
|
|
353
|
+
destination_path: str,
|
|
317
354
|
username_param: Optional[str] = None,
|
|
318
355
|
):
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
356
|
+
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", source)
|
|
357
|
+
|
|
358
|
+
if container_args is None:
|
|
359
|
+
typer.echo(__('Container name and source directory path are required as the first argument'))
|
|
360
|
+
typer.echo(__('Example: container_name:/path/to/file'))
|
|
361
|
+
raise typer.Exit(1)
|
|
362
|
+
container_identifier = container_args.groups()[0]
|
|
363
|
+
source_path = container_args.groups()[1]
|
|
364
|
+
|
|
365
|
+
if not container_identifier:
|
|
366
|
+
typer.echo('Container identifier (container_id_or_name) is required')
|
|
367
|
+
raise typer.Exit(1)
|
|
368
|
+
|
|
369
|
+
resolved_options = self.__thestage_api_client.resolve_user_input(entity_identifier=container_identifier)
|
|
370
|
+
container_public_id = None
|
|
371
|
+
valid_container_count = 0
|
|
372
|
+
for container_item in resolved_options.dockerContainerMatchData:
|
|
373
|
+
message = f"Found a container with matching {container_item.matchedField} in status: '{container_item.frontendStatus.status_translation}' (ID: {container_item.publicId})"
|
|
374
|
+
line_color = ColorScheme.SUCCESS.value if container_item.canDownloadUploadOnContainer else 'default'
|
|
375
|
+
print(f"[{line_color}]{message}[{line_color}]")
|
|
376
|
+
if container_item.canDownloadUploadOnContainer:
|
|
377
|
+
valid_container_count += 1
|
|
378
|
+
container_public_id = container_item.publicId
|
|
379
|
+
|
|
380
|
+
if valid_container_count != 1:
|
|
381
|
+
typer.echo(f"Failed to resolve the container by provided identifier, as total of {valid_container_count} containers are valid options")
|
|
382
|
+
raise typer.Exit(1)
|
|
383
|
+
|
|
384
|
+
container: Optional[DockerContainerDto] = self.__thestage_api_client.get_container(
|
|
385
|
+
container_public_id=container_public_id,
|
|
323
386
|
)
|
|
324
387
|
|
|
388
|
+
if not container:
|
|
389
|
+
typer.echo(f"Unexpected error: container '{container_public_id}' not found")
|
|
390
|
+
raise typer.Exit(1)
|
|
391
|
+
|
|
325
392
|
if not container.mappings or not container.mappings.directory_mappings:
|
|
326
393
|
typer.echo(__("Mapping folders not found"))
|
|
327
394
|
raise typer.Exit(1)
|
|
328
395
|
|
|
329
396
|
instance_path, container_path = self._get_new_path_from_mapping(
|
|
330
397
|
directory_mapping=container.mappings.directory_mappings,
|
|
331
|
-
destination_path=
|
|
398
|
+
destination_path=source_path,
|
|
332
399
|
)
|
|
333
400
|
|
|
334
401
|
if not instance_path and not container_path:
|
|
335
402
|
typer.echo(__("Cannot find matching container volume mapping for specified file path"))
|
|
336
403
|
raise typer.Exit(1)
|
|
337
404
|
|
|
405
|
+
username, ip_address, private_key_path = self.get_server_auth(
|
|
406
|
+
container=container,
|
|
407
|
+
username_param=username_param,
|
|
408
|
+
private_key_path_override=None,
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
copy_only_folder_contents=source_path.endswith("/")
|
|
412
|
+
|
|
338
413
|
self.__remote_server_service.download_data_from_container(
|
|
339
414
|
ip_address=ip_address,
|
|
340
415
|
username=username,
|
|
@@ -162,15 +162,10 @@ class LoggingService:
|
|
|
162
162
|
}))
|
|
163
163
|
raise typer.Exit(1)
|
|
164
164
|
else:
|
|
165
|
-
typer.echo(
|
|
165
|
+
typer.echo("Inference simulator was not found")
|
|
166
166
|
raise typer.Exit(1)
|
|
167
167
|
|
|
168
|
-
typer.echo(
|
|
169
|
-
f"Log stream for inference simulator %slug% started",
|
|
170
|
-
{
|
|
171
|
-
'slug': str(inference_simulator.slug),
|
|
172
|
-
}
|
|
173
|
-
))
|
|
168
|
+
typer.echo(f"Log stream for inference simulator '{inference_simulator.public_id}' started")
|
|
174
169
|
|
|
175
170
|
typer.echo(__("CTRL+D to disconnect from log stream."))
|
|
176
171
|
|
|
@@ -184,7 +179,8 @@ class LoggingService:
|
|
|
184
179
|
|
|
185
180
|
if input_task in done:
|
|
186
181
|
print_task_or_inference_simulator_logs.cancel()
|
|
187
|
-
|
|
182
|
+
inference_logs_cmd_id = f"-isn {slug}" if slug else f"-isid {public_id}"
|
|
183
|
+
typer.echo(f"Disconnected from log stream. You can try to reconnect with 'thestage project inference-simulator logs {inference_logs_cmd_id}'")
|
|
188
184
|
|
|
189
185
|
|
|
190
186
|
@error_handler()
|
|
@@ -285,6 +281,7 @@ class LoggingService:
|
|
|
285
281
|
consecutive_error_count = 0
|
|
286
282
|
errors_started_at = None
|
|
287
283
|
log_wait_remaining_limit = 0 # no log delays after reconnect
|
|
284
|
+
print_nonblocking("Reconnected to log stream", writer, BytePrintStyle.GREEN)
|
|
288
285
|
|
|
289
286
|
last_iteration_log_timestamp = logs_response.lastLogTimestamp
|
|
290
287
|
last_log_id = logs_response.lastLogId
|
|
@@ -10,6 +10,5 @@ class ProjectConfig(BaseModel):
|
|
|
10
10
|
public_id: str = Field(None, alias='public_id')
|
|
11
11
|
git_repository_url: str = Field(None, alias='git_repository_url')
|
|
12
12
|
deploy_key_path: str = Field(None, alias='deploy_key_path')
|
|
13
|
-
|
|
14
|
-
default_container_public_id: Optional[str] = Field(None, alias='default_container_public_id') # TODO use
|
|
13
|
+
default_container_public_id: Optional[str] = Field(None, alias='default_container_public_id')
|
|
15
14
|
prompt_for_default_container: bool = Field(True, alias='prompt_for_default_container')
|
|
@@ -278,7 +278,7 @@ class ProjectService(AbstractService):
|
|
|
278
278
|
|
|
279
279
|
if (project_config.prompt_for_default_container is None or project_config.prompt_for_default_container) and (docker_container_slug or docker_container_public_id) and (project_config.default_container_public_id != container.public_id):
|
|
280
280
|
set_default_container_answer: str = typer.prompt(
|
|
281
|
-
text=f"Would you like to set '{
|
|
281
|
+
text=f"Would you like to set the container '{container.slug}' (ID: '{container.public_id}') as default for this project installation?",
|
|
282
282
|
show_choices=True,
|
|
283
283
|
default=YesOrNoResponse.YES.value,
|
|
284
284
|
type=click.Choice([r.value for r in YesOrNoResponse]),
|
|
@@ -415,6 +415,10 @@ class ProjectService(AbstractService):
|
|
|
415
415
|
print(f"[{ColorScheme.WARNING.value}]{run_task_response.message}[{ColorScheme.WARNING.value}]")
|
|
416
416
|
if run_task_response.is_success and run_task_response.task:
|
|
417
417
|
typer.echo(f"Task '{run_task_response.task.title}' has been scheduled successfully. Task ID: {run_task_response.task.public_id}")
|
|
418
|
+
if run_task_response.tasksInQueue:
|
|
419
|
+
typer.echo(f"There are tasks in queue ahead of this new task:")
|
|
420
|
+
for queued_task_item in run_task_response.tasksInQueue:
|
|
421
|
+
typer.echo(f"{queued_task_item.public_id} - {queued_task_item.frontend_status.status_translation}")
|
|
418
422
|
return run_task_response.task
|
|
419
423
|
else:
|
|
420
424
|
typer.echo(f'The task failed with an error: {run_task_response.message}')
|
|
@@ -630,14 +634,14 @@ class ProjectService(AbstractService):
|
|
|
630
634
|
|
|
631
635
|
if metadata:
|
|
632
636
|
typer.echo("qlip_serve_metadata:")
|
|
633
|
-
typer.echo(json.dumps(
|
|
637
|
+
typer.echo(json.dumps(metadata, indent=4))
|
|
634
638
|
|
|
635
639
|
if not file_path:
|
|
636
640
|
file_path = Path(os.getcwd()) / "metadata.json"
|
|
637
641
|
typer.echo(__("No file path provided. Saving metadata to %file_path%", {"file_path": str(file_path)}))
|
|
638
642
|
|
|
639
643
|
try:
|
|
640
|
-
parsed_metadata =
|
|
644
|
+
parsed_metadata = metadata
|
|
641
645
|
|
|
642
646
|
output_file = Path(file_path)
|
|
643
647
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -935,12 +939,11 @@ class ProjectService(AbstractService):
|
|
|
935
939
|
self,
|
|
936
940
|
model_public_id: Optional[str] = None,
|
|
937
941
|
model_slug: Optional[str] = None,
|
|
938
|
-
new_inference_simulator_slug: Optional[str] = None,
|
|
939
942
|
rented_instance_public_id: Optional[str] = None,
|
|
940
943
|
rented_instance_slug: Optional[str] = None,
|
|
941
944
|
self_hosted_instance_public_id: Optional[str] = None,
|
|
942
945
|
self_hosted_instance_slug: Optional[str] = None,
|
|
943
|
-
) ->
|
|
946
|
+
) -> str:
|
|
944
947
|
config = self.__config_provider.get_config()
|
|
945
948
|
project_config: ProjectConfig = self.__get_fixed_project_config()
|
|
946
949
|
if not project_config:
|
|
@@ -959,11 +962,10 @@ class ProjectService(AbstractService):
|
|
|
959
962
|
typer.echo("Please provide a single model identifier - name or ID.")
|
|
960
963
|
raise typer.Exit(1)
|
|
961
964
|
|
|
962
|
-
typer.echo(f"Creating inference simulator
|
|
965
|
+
typer.echo(f"Creating inference simulator")
|
|
963
966
|
deploy_model_to_instance_response: DeployInferenceModelToInstanceResponse = self.__thestage_api_client.deploy_inference_model_to_instance(
|
|
964
967
|
model_public_id=model_public_id,
|
|
965
968
|
model_slug=model_slug,
|
|
966
|
-
new_inference_simulator_slug=new_inference_simulator_slug,
|
|
967
969
|
rented_instance_public_id=rented_instance_public_id,
|
|
968
970
|
rented_instance_slug=rented_instance_slug,
|
|
969
971
|
self_hosted_instance_public_id=self_hosted_instance_public_id,
|
|
@@ -973,7 +975,7 @@ class ProjectService(AbstractService):
|
|
|
973
975
|
if deploy_model_to_instance_response.message:
|
|
974
976
|
typer.echo(deploy_model_to_instance_response.message)
|
|
975
977
|
if deploy_model_to_instance_response.is_success:
|
|
976
|
-
typer.echo("Inference simulator has been scheduled to run successfully.")
|
|
978
|
+
typer.echo(f"Inference simulator '{deploy_model_to_instance_response.inferenceSimulatorPublicId}' has been scheduled to run successfully.")
|
|
977
979
|
else:
|
|
978
980
|
typer.echo(__(
|
|
979
981
|
'Inference simulator failed to run with an error: %server_massage%',
|
|
@@ -984,6 +986,8 @@ class ProjectService(AbstractService):
|
|
|
984
986
|
typer.echo(__("Inference simulator failed to run with an error"))
|
|
985
987
|
raise typer.Exit(1)
|
|
986
988
|
|
|
989
|
+
return deploy_model_to_instance_response.inferenceSimulatorPublicId
|
|
990
|
+
|
|
987
991
|
|
|
988
992
|
@error_handler()
|
|
989
993
|
def project_deploy_inference_simulator_model_to_sagemaker(
|
|
@@ -1142,7 +1146,7 @@ class ProjectService(AbstractService):
|
|
|
1142
1146
|
if not project_public_id and not project_slug:
|
|
1143
1147
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
1144
1148
|
if not project_config:
|
|
1145
|
-
typer.echo(__("Provide the project
|
|
1149
|
+
typer.echo(__("Provide the project identifier or run this command from within an initialized project directory"))
|
|
1146
1150
|
raise typer.Exit(1)
|
|
1147
1151
|
project_public_id = project_config.public_id
|
|
1148
1152
|
|
|
@@ -1195,7 +1199,7 @@ class ProjectService(AbstractService):
|
|
|
1195
1199
|
if not project_public_id and not project_slug:
|
|
1196
1200
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
1197
1201
|
if not project_config:
|
|
1198
|
-
typer.echo(__("Provide the project
|
|
1202
|
+
typer.echo(__("Provide the project identifier or run this command from within an initialized project directory"))
|
|
1199
1203
|
raise typer.Exit(1)
|
|
1200
1204
|
project_public_id = project_config.public_id
|
|
1201
1205
|
|
|
@@ -1238,7 +1242,7 @@ class ProjectService(AbstractService):
|
|
|
1238
1242
|
headers=list(map(lambda x: x.alias, ProjectInferenceSimulatorModelEntity.model_fields.values())),
|
|
1239
1243
|
row=row,
|
|
1240
1244
|
page=page,
|
|
1241
|
-
max_col_width=[100, 100, 100, 100,
|
|
1245
|
+
max_col_width=[100, 100, 100, 100, 25],
|
|
1242
1246
|
show_index="never",
|
|
1243
1247
|
)
|
|
1244
1248
|
|
|
@@ -1247,7 +1251,7 @@ class ProjectService(AbstractService):
|
|
|
1247
1251
|
if not project_slug and not project_public_id:
|
|
1248
1252
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
1249
1253
|
if not project_config:
|
|
1250
|
-
typer.echo(__("Provide the project
|
|
1254
|
+
typer.echo(__("Provide the project identifier or run this command from within an initialized project directory"))
|
|
1251
1255
|
raise typer.Exit(1)
|
|
1252
1256
|
project_public_id = project_config.public_id
|
|
1253
1257
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thestage
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary:
|
|
5
5
|
License-File: LICENSE.txt
|
|
6
6
|
Author: TheStage AI team
|
|
@@ -21,6 +21,7 @@ Requires-Dist: pydantic (>=2.4.2,<3.0.0)
|
|
|
21
21
|
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
22
22
|
Requires-Dist: python-gettext-translations (>=1.1.0,<2.0.0)
|
|
23
23
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
24
|
+
Requires-Dist: rich (>=14.2.0,<15.0.0)
|
|
24
25
|
Requires-Dist: tabulate (>=0.9.0,<0.10.0)
|
|
25
26
|
Requires-Dist: typer[all] (>=0.15.2,<0.16.0)
|
|
26
27
|
Description-Content-Type: text/markdown
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
thestage/.env,sha256=lHeR-H4TiBp4z06bWt7oND9LMMVXP3WCKY7lQltDM3M,129
|
|
2
|
-
thestage/__init__.py,sha256=
|
|
2
|
+
thestage/__init__.py,sha256=h6612fk--j1jt0iLyVGKNfXLdDLrKmuH0Vay8qaYWMY,64
|
|
3
3
|
thestage/__main__.py,sha256=4ObdWrDRaIASaR06IxtFSsoMu58eyL0MnD64habvPj8,101
|
|
4
4
|
thestage/cli_command.py,sha256=P93LXDruJWecmF5xn-D2uhMOSD9iSJl-gP4oG9aD56k,2173
|
|
5
5
|
thestage/cli_command_helper.py,sha256=f5NZQ4MZJ7yyxPvkQW7ilIAxN_19Mx_zzSqedhZtd6g,1939
|
|
@@ -10,9 +10,9 @@ thestage/config/env_base.py,sha256=RNBQ17yk1ieu1kdUlM7Qe7mDCoxstgGUwwhe265o4dQ,3
|
|
|
10
10
|
thestage/controllers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
thestage/controllers/base_controller.py,sha256=BjTWHPynPrOcD0Jb3h6bqeIMSZxy6Elja3Rdgl93mXU,2508
|
|
12
12
|
thestage/controllers/config_controller.py,sha256=WEw4H5ZfJfUhfBimLa1Lava-h8zp2TZ4GyHVyzeTMdo,5964
|
|
13
|
-
thestage/controllers/container_controller.py,sha256=
|
|
14
|
-
thestage/controllers/instance_controller.py,sha256=
|
|
15
|
-
thestage/controllers/project_controller.py,sha256=
|
|
13
|
+
thestage/controllers/container_controller.py,sha256=nQCLBR4wqvNfXuxU-mdJYCvFSbAL4LweEzPTp0FKwbs,16337
|
|
14
|
+
thestage/controllers/instance_controller.py,sha256=EmXs5BLgvocSN7PuNPe3Yo4ZgZoARSh0aKmFMTbvsEc,7470
|
|
15
|
+
thestage/controllers/project_controller.py,sha256=00thKf4p_SDHYF9eRmipqzE7MHogp3DvgdxNAaMt_zg,40526
|
|
16
16
|
thestage/controllers/utils_controller.py,sha256=ac-TLWC2wrmxJYNFOltoQKCTpFaKB6p937odona64OI,912
|
|
17
17
|
thestage/debug_main.dist.py,sha256=UPIJ58yf-6FtXZj-FLAwxi7HononseuCYm9xb5KlxTs,783
|
|
18
18
|
thestage/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -24,7 +24,7 @@ thestage/entities/enums/tail_output_type.py,sha256=6S55VRRosrI3yZW8XeAGm4u12H4ha
|
|
|
24
24
|
thestage/entities/enums/yes_no_response.py,sha256=PXXkB7KMB-XCHvKOBRuX6NRKyq8UW0G228OICRr2ZTk,86
|
|
25
25
|
thestage/entities/file_item.py,sha256=hxUbdne6AYFHJfuQ8l0XQO86IuC8Pyx_OrPw_0lhN_o,828
|
|
26
26
|
thestage/entities/project_inference_simulator.py,sha256=Rgj5byZDq-uFI2ugOIMfW7CgJNYHfUyidhUbZ_kMoDk,647
|
|
27
|
-
thestage/entities/project_inference_simulator_model.py,sha256=
|
|
27
|
+
thestage/entities/project_inference_simulator_model.py,sha256=8xzC6pZZQzMAh6DASS2ecYzv9EQZCc-fTpl5nOtJXzY,570
|
|
28
28
|
thestage/entities/project_task.py,sha256=6UQaJMTuqDQJtbmbafD1iLjgE7CrlPL7AsGkIU91nNQ,594
|
|
29
29
|
thestage/entities/rented_instance.py,sha256=DyekXeui3YiiKZmqtvb40n6j6w4_ly80TSjcAbjWlcU,628
|
|
30
30
|
thestage/entities/self_hosted_instance.py,sha256=blsOdCMZPYM_xK4Zx4ZdGD43Ayy8j7ifX30O3fZ2XiM,630
|
|
@@ -38,14 +38,14 @@ thestage/exceptions/git_access_exception.py,sha256=ZyB5qrz6fok1jOEKtt3PXP9vq3vOm
|
|
|
38
38
|
thestage/exceptions/remote_server_exception.py,sha256=Z1R5Wjw3w7VdqURhjidGkNhJL9lsA76txkAZPA5Uv70,595
|
|
39
39
|
thestage/git/ProgressPrinter.py,sha256=z99BPq3KYycClL-7fmsERIIuZ03papdIYOhR8A7b9AA,573
|
|
40
40
|
thestage/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
-
thestage/helpers/error_handler.py,sha256
|
|
41
|
+
thestage/helpers/error_handler.py,sha256=dVwdFvqYnlg-tOtNKVisyZipn0N2u7ZyHt5qVV2a6Rg,5370
|
|
42
42
|
thestage/helpers/exception_hook.py,sha256=jekDs7smzI1UjXkuMut_uM725GL3c6Gr_zmyEYdDjV8,334
|
|
43
43
|
thestage/helpers/logger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
44
|
thestage/helpers/logger/app_logger.py,sha256=4dgZ_8k28R887rmIHmCTn2QVg0stqTk8hcXa5CF4VJc,1607
|
|
45
45
|
thestage/helpers/ssh_util.py,sha256=JuDwddHxEGcA24Y8a-jLv339cG-jq4hEaBAl5TSVVFw,1262
|
|
46
46
|
thestage/i18n/en_GB/messages.po,sha256=BuVIhd5TRQkgFkAbTGvbSRuO88lSJGpnk9TT2J9BC8E,32375
|
|
47
47
|
thestage/i18n/translation.py,sha256=c62OicQ4phSMuqDe7hqGebIsk0W2-8ZJUfgfdtjjqEc,284
|
|
48
|
-
thestage/main.py,sha256=
|
|
48
|
+
thestage/main.py,sha256=O3NpGl4UE8GfsrdgDP9KZ5Oxe3-EDtBH5IlL-eFdgJs,1800
|
|
49
49
|
thestage/services/.env,sha256=K2VpzFAVjD75XawAHZdR0HWmypryA_mXNY4WHNgR-wQ,184
|
|
50
50
|
thestage/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
51
|
thestage/services/abstract_mapper.py,sha256=_q7YLkPNRsNW5wOCqvZIu1KfpLkc7uVaAQKrMZtsGuY,218
|
|
@@ -53,13 +53,13 @@ thestage/services/abstract_service.py,sha256=fsGXb0plZ9SvGBWAY4y599BH196YoFP3BJ7
|
|
|
53
53
|
thestage/services/app_config_service.py,sha256=bbiXxcLoh_XC3mgsAo9ciksblPvUEcnG2oCIm1jMyo4,1679
|
|
54
54
|
thestage/services/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
55
|
thestage/services/clients/git/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
56
|
-
thestage/services/clients/git/git_client.py,sha256=
|
|
56
|
+
thestage/services/clients/git/git_client.py,sha256=nUCszU5ymWUcf7YqeEhZqBhR17hwyDgMg00DTXOWIOY,16449
|
|
57
57
|
thestage/services/clients/thestage_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
|
-
thestage/services/clients/thestage_api/api_client.py,sha256=
|
|
58
|
+
thestage/services/clients/thestage_api/api_client.py,sha256=pLxsHGqu3fEcPvmi9IRFeLCi7LalRUvM-gvo6GGLFF4,32141
|
|
59
59
|
thestage/services/clients/thestage_api/core/api_client_core.py,sha256=lEffuh30f6oV2lp90UuET90OUxnrMh2PHjquF6_sT6E,3453
|
|
60
60
|
thestage/services/clients/thestage_api/core/http_client_exception.py,sha256=JH-874Gu9T1b1_FpPBLqdyt9U0PyhpwRCe_oDc6c_jI,385
|
|
61
61
|
thestage/services/clients/thestage_api/dtos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
|
-
thestage/services/clients/thestage_api/dtos/base_controller/connect_resolve_response.py,sha256=
|
|
62
|
+
thestage/services/clients/thestage_api/dtos/base_controller/connect_resolve_response.py,sha256=mDSAq2gcmERAejnd8rXkAam39bH0WrTw5V4mQ_79hB8,1106
|
|
63
63
|
thestage/services/clients/thestage_api/dtos/base_response.py,sha256=R6jjhvv0U0XD8j5N5T36q-6liiEAUy7xINFA1H7CMB8,410
|
|
64
64
|
thestage/services/clients/thestage_api/dtos/container_param_request.py,sha256=Os3FTzbOIcEIFMpJFsFm0hhGV1ZfIyKrUw9OtwRw1Z0,449
|
|
65
65
|
thestage/services/clients/thestage_api/dtos/container_response.py,sha256=hMrQe6RvurGONfFweSTRHi44AP1HVvIFPRmAZ1g8RHY,2445
|
|
@@ -80,11 +80,11 @@ thestage/services/clients/thestage_api/dtos/enums/selfhosted_status.py,sha256=_O
|
|
|
80
80
|
thestage/services/clients/thestage_api/dtos/enums/task_execution_status.py,sha256=MU14K1PvkLEFnUizeVt8x_u1IP2OVkyf5pLFdrUUtYg,303
|
|
81
81
|
thestage/services/clients/thestage_api/dtos/enums/task_status.py,sha256=Zg4QkuHilWTC6D_lKsby7u4y1rSRs69_kzfeFWCWoFg,282
|
|
82
82
|
thestage/services/clients/thestage_api/dtos/frontend_status.py,sha256=MKrqCmFWVe-8InJqavkqz1w1N35OcT3ndBrXOu7mKdA,312
|
|
83
|
-
thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_request.py,sha256=
|
|
84
|
-
thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py,sha256=
|
|
83
|
+
thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_request.py,sha256=wNDn4QhNrLONBZsyDC1p5o6jsgd-CQb5JQrxNBh9QK8,781
|
|
84
|
+
thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py,sha256=62iS_Jq6D0FScLwjwj64CxJ6JlKWwcN4LM2R-AmaUqs,480
|
|
85
85
|
thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_request.py,sha256=CAEzVOlud8dR3ifZLu09LIKAxt2iwZnjq4HmD0a6HXg,478
|
|
86
86
|
thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_response.py,sha256=lis4effVtF39eW8gCkWzJKxMVhIMAg3_8JHub83JR6s,422
|
|
87
|
-
thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py,sha256=
|
|
87
|
+
thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py,sha256=FctVvLAvUfBm-kTwozowyblHPAHZbBO0PAMz4_BA_O4,398
|
|
88
88
|
thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_response.py,sha256=zTt5ewR3oh4qyL0pzt0QP2jANrUpA-5V8As1YqNy3hA,474
|
|
89
89
|
thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_request.py,sha256=JVpjCSfEHijhxojAFSu1d5jSeZX18xiTObUxnHbMs1Y,582
|
|
90
90
|
thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_response.py,sha256=KSPIabvvqDvpitMQElo3S37OQPRpTT-2tJWjelEZ1uM,544
|
|
@@ -108,7 +108,7 @@ thestage/services/clients/thestage_api/dtos/project_controller/project_get_deplo
|
|
|
108
108
|
thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_request.py,sha256=pt4qI8EKFWOPoKHKMdWBzrW7vB_mb2Gstm1dVsob05U,378
|
|
109
109
|
thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_response.py,sha256=aNaD4xVkhbwlD_rI3D0-2gp-F4L6CxxUkAOSLJZPl1I,249
|
|
110
110
|
thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_request.py,sha256=AkW-Gn2M8-NcRU0SWdmQ0vQ-LemPY4lh-UQBtB0Mka8,498
|
|
111
|
-
thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py,sha256=
|
|
111
|
+
thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py,sha256=cvwpZxb32614gFRzlTWWXQpUdDTrqHE5Gi4h3BV9q3g,453
|
|
112
112
|
thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_request.py,sha256=4PGvswsyz8lx-A0xFrZEBEHbw8pEKv7WrnuDi3nZgfY,819
|
|
113
113
|
thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_response.py,sha256=Q7XlbZ4vgk9QQL2z11BeUkKDn-5p8j06eNI0GmpZNjk,430
|
|
114
114
|
thestage/services/clients/thestage_api/dtos/project_response.py,sha256=Q3gDfuiuVXls2WwOVgmKT9MGfOoM2GyE4n9YtmYFiUU,810
|
|
@@ -128,10 +128,10 @@ thestage/services/clients/thestage_api/dtos/user_controller/user_profile.py,sha2
|
|
|
128
128
|
thestage/services/clients/thestage_api/dtos/validate_token_response.py,sha256=nmKbqRPkwtzhv37QheA_MO4CpEPmGM0VUC2gYckcrl8,418
|
|
129
129
|
thestage/services/config_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
130
130
|
thestage/services/config_provider/config_provider.py,sha256=CR2xSWRMIqsspek3iIs2qZ60ThHVNmTNTS6R4uheAuE,10238
|
|
131
|
-
thestage/services/connect/connect_service.py,sha256
|
|
131
|
+
thestage/services/connect/connect_service.py,sha256=w5Iq98HRZrfrUE5sfMMRAMPDZUh4jmeGDpXDXgAHBMs,9752
|
|
132
132
|
thestage/services/connect/dto/remote_server_config.py,sha256=yuO0tTAgUxCiQ-h1nVvWUMlCUtR-WB_eOH6KYspV7zQ,272
|
|
133
133
|
thestage/services/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
134
|
-
thestage/services/container/container_service.py,sha256=
|
|
134
|
+
thestage/services/container/container_service.py,sha256=vNBNVGYtDRQCBTSKWq8vN-j8XuFE5NfwzzoqT96J08Y,18189
|
|
135
135
|
thestage/services/container/mapper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
136
136
|
thestage/services/container/mapper/container_mapper.py,sha256=GXSQX3H69M0wlZvXzO2jZs-Pqq70gDBvNmLKNvw6axU,1164
|
|
137
137
|
thestage/services/core_files/config_entity.py,sha256=_55m8h2_KXIxl8Y71Yyk3wTj-q1mo918YU1yltzVqgQ,1075
|
|
@@ -146,22 +146,22 @@ thestage/services/logging/dto/log_message.py,sha256=k2clfz2fQnQ-ycFI8g8WYJ_XOjK0
|
|
|
146
146
|
thestage/services/logging/dto/log_type.py,sha256=a6JWnq0ZjJ-2BQrG-fKYYy3UeJS2U2ZzE5P_EXglBfE,95
|
|
147
147
|
thestage/services/logging/exception/log_polling_exception.py,sha256=rKQ7AtNCGKkk5OINIyyjvLT92PU5i_yJUH-Msr9hXQw,226
|
|
148
148
|
thestage/services/logging/logging_constants.py,sha256=4Gk2tglHW_-jnjB8uVIh-ds4fAVBqNW8igfQt8k7Quc,137
|
|
149
|
-
thestage/services/logging/logging_service.py,sha256=
|
|
149
|
+
thestage/services/logging/logging_service.py,sha256=44YjcsYo-C3i8R8wFoz0JdhnqY6Tl90aI3M6nWH2yyQ,17819
|
|
150
150
|
thestage/services/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
151
151
|
thestage/services/project/dto/inference_simulator_dto.py,sha256=skyxLgzwbR_EyVSCnojAwI3kZyJ5LJefP_0RpawlKa8,719
|
|
152
152
|
thestage/services/project/dto/inference_simulator_model_dto.py,sha256=jNIPwqX_A7jgkcdugdEUpjpjo0SZwlHPK2D4K7i0Nj0,642
|
|
153
|
-
thestage/services/project/dto/project_config.py,sha256=
|
|
153
|
+
thestage/services/project/dto/project_config.py,sha256=EdaW2qQsw9LVyRh0ktxFNT48d7qqdiaKYCW03uvDqKc,583
|
|
154
154
|
thestage/services/project/mapper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
155
155
|
thestage/services/project/mapper/project_inference_simulator_mapper.py,sha256=rXb0fhZVjkx8E3tSnB7B6CMC275_reDG8mlZscXz0zk,856
|
|
156
156
|
thestage/services/project/mapper/project_inference_simulator_model_mapper.py,sha256=JvCUVp7d4o2-CCxkA6aesSEz1iUJcIfBIkXdN_hHpT0,924
|
|
157
157
|
thestage/services/project/mapper/project_task_mapper.py,sha256=8y4IqZOVXJUrI-946sZn295hyZGVtws61aETrhA9b1s,727
|
|
158
|
-
thestage/services/project/project_service.py,sha256=
|
|
158
|
+
thestage/services/project/project_service.py,sha256=RtFN9eH_5_heTRs-P5-c5dpDEF7yWDep__rB9sTLse4,61824
|
|
159
159
|
thestage/services/remote_server_service.py,sha256=p_M0eL2Mtdz8_BCtNEhHXndaNDCFh_RgksQpWl0HDtE,23325
|
|
160
160
|
thestage/services/service_factory.py,sha256=WosSbicSvY9dHOkS2OqGCtHkmKdJE1f_K7uEnB3Auaw,4291
|
|
161
161
|
thestage/services/task/dto/task_dto.py,sha256=S1CzhCLW3B_ovSJA1pRBPerRvbnTk1c6yAHf_7RGZbc,1029
|
|
162
162
|
thestage/services/validation_service.py,sha256=iopaDKuC_V_4Z_Zly5BFaLL74wG66z9URE86_I-9Hi4,2243
|
|
163
|
-
thestage-0.6.
|
|
164
|
-
thestage-0.6.
|
|
165
|
-
thestage-0.6.
|
|
166
|
-
thestage-0.6.
|
|
167
|
-
thestage-0.6.
|
|
163
|
+
thestage-0.6.7.dist-info/METADATA,sha256=dyt0Kh8J-VQvPTX_ZKILOUkcTsWeowX0RRV5Xl9kJEQ,5622
|
|
164
|
+
thestage-0.6.7.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
165
|
+
thestage-0.6.7.dist-info/entry_points.txt,sha256=57pMhs8zaCM-jgeTffC0WVqCsh35Uq_dUDmzXR80CI4,47
|
|
166
|
+
thestage-0.6.7.dist-info/licenses/LICENSE.txt,sha256=U9QrxfdD7Ie7r8z1FleuvOGQvgCF1m0Mjd78cFvWaHE,572
|
|
167
|
+
thestage-0.6.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|