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.
Files changed (24) hide show
  1. thestage/__init__.py +1 -1
  2. thestage/controllers/container_controller.py +13 -66
  3. thestage/controllers/instance_controller.py +4 -4
  4. thestage/controllers/project_controller.py +8 -10
  5. thestage/entities/project_inference_simulator_model.py +1 -1
  6. thestage/helpers/error_handler.py +2 -2
  7. thestage/main.py +1 -1
  8. thestage/services/clients/git/git_client.py +1 -1
  9. thestage/services/clients/thestage_api/api_client.py +3 -5
  10. thestage/services/clients/thestage_api/dtos/base_controller/connect_resolve_response.py +1 -0
  11. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_request.py +0 -2
  12. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py +2 -0
  13. thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py +1 -1
  14. thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py +3 -0
  15. thestage/services/connect/connect_service.py +6 -6
  16. thestage/services/container/container_service.py +97 -22
  17. thestage/services/logging/logging_service.py +5 -8
  18. thestage/services/project/dto/project_config.py +1 -2
  19. thestage/services/project/project_service.py +16 -12
  20. {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/METADATA +2 -1
  21. {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/RECORD +24 -24
  22. {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/WHEEL +0 -0
  23. {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/entry_points.txt +0 -0
  24. {thestage-0.6.6.dist-info → thestage-0.6.7.dist-info}/licenses/LICENSE.txt +0 -0
thestage/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from . import *
2
2
  __app_name__ = "thestage"
3
- __version__ = "0.6.6"
3
+ __version__ = "0.6.7"
@@ -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: container_name:/path/to/file"),),
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
- container: Optional[DockerContainerDto] = container_service.get_container(
248
- container_slug=container_slug,
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
- source_path: str = typer.Argument(help=__("Source file path in container. Format: container_name:/path/to/file"),),
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
- container: Optional[DockerContainerDto] = container_service.get_container(
305
- container_slug=container_slug,
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
- working_directory = get_current_directory().joinpath(project_slug)
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(__("Invalid UID format. The UID can only contain letters, numbers, and hyphens."))
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
- slug=new_inference_simulator_slug
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='UNIQUE_ID')
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('Unexpected error occurred') # TODO inquire what we want here if backend is offline
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
- instancePublicId=rented_instance_public_id,
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 resolve_connect_options(
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/connect/resolve-options',
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
 
@@ -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
- public_id: Optional[str] = Field(None, alias='publicId')
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.resolve_connect_options(entity_identifier=input_entity_identifier)
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 unique ID '{instance_slug}'")
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
- container: DockerContainerDto,
271
- src_path: str,
272
- copy_only_folder_contents: bool,
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
- if not self.__file_system_service.check_if_path_exist(file=src_path):
277
- typer.echo(__("File not found at specified path"))
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
- username, ip_address, private_key_path = self.get_server_auth(
281
- container=container,
282
- username_param=username_param,
283
- private_key_path_override=None
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=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
- container: DockerContainerDto,
314
- src_path: str,
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
- username, ip_address, private_key_path = self.get_server_auth(
320
- container=container,
321
- username_param=username_param,
322
- private_key_path_override=None,
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=src_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(__("Inference simulator with unique ID %slug% was not found", {'slug': inference_simulator.slug}))
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
- typer.echo(__(f"Disconnected from log stream. You can try to reconnect with 'thestage project inference-simulator logs {slug}'."))
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
- default_container_uid: Optional[str] = Field(None, alias='default_container_uid') # TODO delete
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 '{docker_container_slug}' as a default container for this project installation?",
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(json.loads(metadata), indent=4))
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 = json.loads(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
- ) -> None:
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 with unique ID: {new_inference_simulator_slug}")
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 unique ID or run this command from within an initialized project directory"))
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 unique ID or run this command from within an initialized project directory"))
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, 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 unique ID or run this command from within an initialized project directory"))
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.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=IO0lPlZY3Ps8mQl7mW6sfOiw93IVvBGApb2QecBNa6U,64
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=oAFDWelChvRRIWTeeOMVufIOQXfqSS9NnF8kqEnhrNk,18244
14
- thestage/controllers/instance_controller.py,sha256=147zqteL_F8lhF4blgRLJHemFnhQ_EGsK2nbSxjV26c,7396
15
- thestage/controllers/project_controller.py,sha256=8rahTBA6Xt-nlSVBIyeMCOrsakDYgK6rM3KHjonQAr0,40509
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=bg0ZVkz5lCHvUYIT3F4Z2xkwIy1rYIrbWHKSW-T_yJA,575
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=-f4i11vca1kMjQNFfp3PU1qPaiLg-aq5j9VPgnPVSGA,5366
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=P59_DqDeb6metD6RBCmpp1crEh9VhsKTYPt4SUdPfS4,1789
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=BzfiGizn0rByUL8x-XNbzJ_Zs169CwvLJI7NZ6rp4kI,16443
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=VLH_-WSbX4n3AFlLgQHJcLMEu28rTCVX59L2zGyPW7M,32257
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=EvbEMdYYXhkfqWeU9kajBUO8yJcAM8y4CvA8GbaiM3c,1021
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=xOO4ky_2CEGWCnPuBtEhhZ8BxJArFKZR_WnGYcqV7b8,870
84
- thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py,sha256=mX_Parrm8ddTY9nqR4AYlI5WXAVpx1hI7yUEqJiiOFQ,383
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=63nSt4XucJHhHf99m-bdBTe8T6j-tLIQzs1XI71pd3U,399
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=iISmJTHbxSRJsXHT4qBTMP3-Co9fWCHI5s2UgB_-GV8,340
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=-La0JfVHEWu29zv9rP5TYUShJNErOVIpza0ysZIRFLk,9750
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=q-fArCJlOaNrQVfc87Kb5RMyHh3x55acn1dA7hPtYMc,14409
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=L4_vhPBz1ZG3X17U_9pnq9WV3EYKR4fiztC0s1au1PM,17770
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=E7ZuvYxWVJuPiK9SbiRbRSNv_FE_kCXvkXE9AkcnSRE,694
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=3Mbs1ghnUsd7p565bf5s7vmRFStmYUfXYEoVIvmuv9s,61541
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.6.dist-info/METADATA,sha256=KuzMtxjv2_kqNOkgwBkYyN-ybm3hHMzgLfBPbFd0BT8,5583
164
- thestage-0.6.6.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
165
- thestage-0.6.6.dist-info/entry_points.txt,sha256=57pMhs8zaCM-jgeTffC0WVqCsh35Uq_dUDmzXR80CI4,47
166
- thestage-0.6.6.dist-info/licenses/LICENSE.txt,sha256=U9QrxfdD7Ie7r8z1FleuvOGQvgCF1m0Mjd78cFvWaHE,572
167
- thestage-0.6.6.dist-info/RECORD,,
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,,