thestage 0.5.44__py3-none-any.whl → 0.5.45__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 CHANGED
@@ -1,3 +1,3 @@
1
1
  from . import *
2
2
  __app_name__ = "thestage"
3
- __version__ = "0.5.44"
3
+ __version__ = "0.5.45"
@@ -3,13 +3,10 @@ import re
3
3
  from pathlib import Path
4
4
  from typing import Optional, List
5
5
 
6
- from thestage.entities.container import DockerContainerEntity
7
6
  from thestage.services.clients.thestage_api.dtos.enums.container_pending_action import DockerContainerAction
8
7
  from thestage.services.clients.thestage_api.dtos.container_response import DockerContainerDto
9
8
  from thestage.i18n.translation import __
10
- from thestage.services.clients.thestage_api.dtos.enums.container_status import DockerContainerStatus
11
9
  from thestage.services.container.container_service import ContainerService
12
- from thestage.services.container.mapper.container_mapper import ContainerMapper
13
10
  from thestage.helpers.logger.app_logger import app_logger
14
11
  from thestage.controllers.utils_controller import validate_config_and_get_service_factory, get_current_directory
15
12
 
@@ -57,46 +57,12 @@ def rented_list(
57
57
  config = service_factory.get_config_provider().get_full_config()
58
58
 
59
59
  instance_service: InstanceService = service_factory.get_instance_service()
60
- instance_rented_status_map = service_factory.get_thestage_api_client().get_rented_business_status_map(config.main.thestage_auth_token)
61
-
62
- if not statuses:
63
- statuses = ({key: instance_rented_status_map[key] for key in [
64
- InstanceRentedBusinessStatus.ONLINE,
65
- InstanceRentedBusinessStatus.CREATING,
66
- InstanceRentedBusinessStatus.TERMINATING,
67
- InstanceRentedBusinessStatus.REBOOTING,
68
- ]}).values()
69
-
70
- if "all" in statuses:
71
- statuses = instance_rented_status_map.values()
72
-
73
- for input_status_item in statuses:
74
- if input_status_item not in instance_rented_status_map.values():
75
- typer.echo(__("'%invalid_status%' is not one of %valid_statuses%", {
76
- 'invalid_status': input_status_item,
77
- 'valid_statuses': str(list(instance_rented_status_map.values()))
78
- }))
79
- raise typer.Exit(1)
80
-
81
- typer.echo(__(
82
- "Listing rented server instances with the following statuses: %statuses%, to view all rented server instances, use --status all",
83
- placeholders={
84
- 'statuses': ', '.join([status_item for status_item in statuses])
85
- }))
86
-
87
- backend_statuses: List[str] = [key for key, value in instance_rented_status_map.items() if value in statuses]
88
-
89
- instance_service.print(
90
- func_get_data=instance_service.get_rented_list,
91
- func_special_params={
92
- 'statuses': backend_statuses,
93
- },
94
- mapper=InstanceMapper(),
60
+
61
+ instance_service.print_rented_instance_list(
95
62
  config=config,
96
- headers=list(map(lambda x: x.alias, RentedInstanceEntity.model_fields.values())),
63
+ statuses=statuses,
97
64
  row=row,
98
- page=page,
99
- show_index="never",
65
+ page=page
100
66
  )
101
67
 
102
68
  typer.echo(__("Rented server instances listing complete"))
@@ -175,45 +141,12 @@ def self_hosted_list(
175
141
  config = service_factory.get_config_provider().get_full_config()
176
142
 
177
143
  instance_service: InstanceService = service_factory.get_instance_service()
178
- selfhosted_instance_status_map = service_factory.get_thestage_api_client().get_selfhosted_business_status_map(config.main.thestage_auth_token)
179
-
180
- if not statuses:
181
- statuses = ({key: selfhosted_instance_status_map[key] for key in [
182
- SelfhostedBusinessStatus.AWAITING_CONFIGURATION,
183
- SelfhostedBusinessStatus.RUNNING,
184
- SelfhostedBusinessStatus.TERMINATED,
185
- ]}).values()
186
-
187
- if "all" in statuses:
188
- statuses = selfhosted_instance_status_map.values()
189
-
190
- for input_status_item in statuses:
191
- if input_status_item not in selfhosted_instance_status_map.values():
192
- typer.echo(__("'%invalid_status%' is not one of %valid_statuses%", {
193
- 'invalid_status': input_status_item,
194
- 'valid_statuses': str(list(selfhosted_instance_status_map.values()))
195
- }))
196
- raise typer.Exit(1)
197
-
198
- typer.echo(__(
199
- "Listing self-hosted instances with the following statuses: %statuses%, to view all self-hosted instances, use --status all",
200
- placeholders={
201
- 'statuses': ', '.join([status_item for status_item in statuses])
202
- }))
203
-
204
- backend_statuses: List[str] = [key for key, value in selfhosted_instance_status_map.items() if value in statuses]
205
-
206
- instance_service.print(
207
- func_get_data=instance_service.get_self_hosted_list,
208
- func_special_params={
209
- 'statuses': backend_statuses,
210
- },
211
- mapper=SelfHostedMapper(),
144
+
145
+ instance_service.print_self_hosted_instance_list(
212
146
  config=config,
213
- headers=list(map(lambda x: x.alias, SelfHostedInstanceEntity.model_fields.values())),
147
+ statuses=statuses,
214
148
  row=row,
215
- page=page,
216
- show_index="never",
149
+ page=page
217
150
  )
218
151
 
219
152
  typer.echo(__("Self-hosted instances listing complete"))
@@ -236,29 +236,9 @@ def list_runs(
236
236
 
237
237
  service_factory = validate_config_and_get_service_factory()
238
238
  config = service_factory.get_config_provider().get_full_config()
239
-
240
239
  project_service: ProjectService = service_factory.get_project_service()
241
240
 
242
- if not project_uid:
243
- project_config: ProjectConfig = service_factory.get_config_provider().read_project_config()
244
- if not project_config:
245
- typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
246
- raise typer.Exit(1)
247
- project_uid = project_config.slug
248
-
249
- project_service.print(
250
- func_get_data=project_service.get_project_task_list,
251
- func_special_params={
252
- 'project_slug': project_uid,
253
- },
254
- mapper=ProjectTaskMapper(),
255
- config=config,
256
- headers=list(map(lambda x: x.alias, ProjectTaskEntity.model_fields.values())),
257
- row=row,
258
- page=page,
259
- max_col_width=[100, 100, 100, 100, 100, 100, 100, 100],
260
- show_index="never",
261
- )
241
+ project_service.print_task_list(config, project_uid, row, page)
262
242
 
263
243
  typer.echo(__("Tasks listing complete"))
264
244
  raise typer.Exit(0)
@@ -664,58 +644,9 @@ def list_inference_simulators(
664
644
 
665
645
  service_factory = validate_config_and_get_service_factory()
666
646
  config = service_factory.get_config_provider().get_full_config()
667
-
668
647
  project_service: ProjectService = service_factory.get_project_service()
669
- if not project_uid:
670
- project_config: ProjectConfig = service_factory.get_config_provider().read_project_config()
671
- if not project_config:
672
- typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
673
- raise typer.Exit(1)
674
- project_uid = project_config.slug
675
-
676
- inference_simulator_status_map = service_factory.get_thestage_api_client().get_inference_simulator_business_status_map(
677
- config.main.thestage_auth_token)
678
-
679
- if not statuses:
680
- statuses = ({key: inference_simulator_status_map[key] for key in [
681
- InferenceSimulatorStatus.SCHEDULED,
682
- InferenceSimulatorStatus.CREATING,
683
- InferenceSimulatorStatus.RUNNING,
684
- ]}).values()
685
-
686
- if "all" in statuses:
687
- statuses = inference_simulator_status_map.values()
688
-
689
- for input_status_item in statuses:
690
- if input_status_item not in inference_simulator_status_map.values():
691
- typer.echo(__("'%invalid_status%' is not one of %valid_statuses%", {
692
- 'invalid_status': input_status_item,
693
- 'valid_statuses': str(list(inference_simulator_status_map.values()))
694
- }))
695
- raise typer.Exit(1)
696
648
 
697
- typer.echo(__(
698
- "Listing inference simulators with the following statuses: %statuses%, to view all inference simulators, use --status all",
699
- placeholders={
700
- 'statuses': ', '.join([status_item for status_item in statuses])
701
- }))
702
-
703
- backend_statuses: List[str] = [key for key, value in inference_simulator_status_map.items() if value in statuses]
704
-
705
- project_service.print(
706
- func_get_data=project_service.get_project_inference_simulator_list,
707
- func_special_params={
708
- 'project_slug': project_uid,
709
- 'statuses': backend_statuses,
710
- },
711
- mapper=ProjectInferenceSimulatorMapper(),
712
- config=config,
713
- headers=list(map(lambda x: x.alias, ProjectInferenceSimulatorEntity.model_fields.values())),
714
- row=row,
715
- page=page,
716
- max_col_width=[100, 100, 100, 100, 100, 100, 100, 100],
717
- show_index="never",
718
- )
649
+ project_service.print_inference_simulator_list(config, project_uid, statuses, row, page)
719
650
 
720
651
  typer.echo(__("Inference simulators listing complete"))
721
652
  raise typer.Exit(0)
@@ -753,58 +684,9 @@ def list_inference_simulator_models(
753
684
 
754
685
  service_factory = validate_config_and_get_service_factory()
755
686
  config = service_factory.get_config_provider().get_full_config()
756
-
757
687
  project_service: ProjectService = service_factory.get_project_service()
758
- if not project_uid:
759
- project_config: ProjectConfig = service_factory.get_config_provider().read_project_config()
760
- if not project_config:
761
- typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
762
- raise typer.Exit(1)
763
- project_uid = project_config.slug
764
-
765
- inference_simulator_model_status_map = service_factory.get_thestage_api_client().get_inference_simulator_model_business_status_map(
766
- config.main.thestage_auth_token)
767
-
768
- if not statuses:
769
- statuses = ({key: inference_simulator_model_status_map[key] for key in [
770
- InferenceModelStatus.SCHEDULED,
771
- InferenceModelStatus.PROCESSING,
772
- InferenceModelStatus.PUSH_SUCCEED,
773
- ]}).values()
774
-
775
- if "all" in statuses:
776
- statuses = inference_simulator_model_status_map.values()
777
-
778
- for input_status_item in statuses:
779
- if input_status_item not in inference_simulator_model_status_map.values():
780
- typer.echo(__("'%invalid_status%' is not one of %valid_statuses%", {
781
- 'invalid_status': input_status_item,
782
- 'valid_statuses': str(list(inference_simulator_model_status_map.values()))
783
- }))
784
- raise typer.Exit(1)
785
688
 
786
- typer.echo(__(
787
- "Listing inference simulator models with the following statuses: %statuses%, to view all inference simulator models, use --status all",
788
- placeholders={
789
- 'statuses': ', '.join([status_item for status_item in statuses])
790
- }))
791
-
792
- backend_statuses: List[str] = [key for key, value in inference_simulator_model_status_map.items() if value in statuses]
793
-
794
- project_service.print(
795
- func_get_data=project_service.get_project_inference_simulator_model_list,
796
- func_special_params={
797
- 'project_slug': project_uid,
798
- 'statuses': backend_statuses,
799
- },
800
- mapper=ProjectInferenceSimulatorModelMapper(),
801
- config=config,
802
- headers=list(map(lambda x: x.alias, ProjectInferenceSimulatorModelEntity.model_fields.values())),
803
- row=row,
804
- page=page,
805
- max_col_width=[100, 100, 100, 100, 100, 100, 100, 100],
806
- show_index="never",
807
- )
689
+ project_service.print_inference_simulator_model_list(config, project_uid, statuses, row, page)
808
690
 
809
691
  typer.echo(__("Inference simulator models listing complete"))
810
692
  raise typer.Exit(0)
thestage/main.py CHANGED
@@ -1,3 +1,8 @@
1
+ from thestage.services.core_files.config_entity import ConfigEntity
2
+
3
+ # TODO use this in config_provider
4
+ initial_config: ConfigEntity = ConfigEntity()
5
+
1
6
  def main():
2
7
  try:
3
8
  import warnings
@@ -8,9 +13,9 @@ def main():
8
13
  from thestage.controllers import base_controller, container_controller, instance_controller, project_controller, \
9
14
  config_controller
10
15
 
16
+ base_controller.app.add_typer(project_controller.app, name="project")
11
17
  base_controller.app.add_typer(container_controller.app, name="container")
12
18
  base_controller.app.add_typer(instance_controller.app, name="instance")
13
- base_controller.app.add_typer(project_controller.app, name="project")
14
19
  base_controller.app.add_typer(config_controller.app, name="config")
15
20
 
16
21
  import thestage.config
@@ -13,7 +13,7 @@ from thestage.color_scheme.color_scheme import ColorScheme
13
13
  from thestage.config import THESTAGE_CONFIG_DIR
14
14
  from thestage.exceptions.git_access_exception import GitAccessException
15
15
  from thestage.git.ProgressPrinter import ProgressPrinter
16
- from thestage.services.filesystem_service import FileSystemServiceCore
16
+ from thestage.services.filesystem_service import FileSystemService
17
17
 
18
18
 
19
19
  class GitLocalClient:
@@ -27,7 +27,7 @@ class GitLocalClient:
27
27
 
28
28
  def __init__(
29
29
  self,
30
- file_system_service: FileSystemServiceCore,
30
+ file_system_service: FileSystemService,
31
31
  ):
32
32
  self.__file_system_service = file_system_service
33
33
 
@@ -85,12 +85,11 @@ from thestage.services.clients.thestage_api.dtos.task_controller.task_list_for_p
85
85
  from thestage.services.clients.thestage_api.dtos.task_controller.task_status_localized_map_response import \
86
86
  TaskStatusLocalizedMapResponse
87
87
  from thestage.services.clients.thestage_api.dtos.task_controller.task_view_response import TaskViewResponse
88
- from thestage.services.clients.thestage_api.dtos.user_profile import UserProfileResponse
89
88
  from thestage.services.clients.thestage_api.dtos.instance_rented_response import InstanceRentedListResponse, \
90
89
  InstanceRentedDto, InstanceRentedItemResponse, InstanceRentedBusinessStatusMapperResponse
91
90
 
92
- from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse, \
93
- TheStageBasePaginatedResponse
91
+ from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
92
+ from thestage.services.clients.thestage_api.dtos.user_controller.user_profile import UserProfileResponse
94
93
  from thestage.services.project.dto.inference_simulator_dto import InferenceSimulatorDto
95
94
  from thestage.services.project.dto.inference_simulator_model_dto import InferenceSimulatorModelDto
96
95
  from thestage.services.task.dto.task_dto import TaskDto
@@ -146,7 +145,6 @@ class TheStageApiClient(TheStageApiClientCore):
146
145
  result = TaskListForProjectResponse.model_validate(response) if response else None
147
146
  return result.tasks if result and result.is_success else None
148
147
 
149
-
150
148
  def get_inference_simulator_list_for_project(
151
149
  self,
152
150
  token: str,
@@ -203,7 +201,6 @@ class TheStageApiClient(TheStageApiClientCore):
203
201
  result = InferenceSimulatorModelListForProjectResponse.model_validate(response) if response else None
204
202
  return result.inferenceSimulatorModels if result and result.is_success else None
205
203
 
206
-
207
204
  def get_rented_instance_list(
208
205
  self,
209
206
  token: str,
@@ -260,7 +257,7 @@ class TheStageApiClient(TheStageApiClientCore):
260
257
 
261
258
  return data.taskStatusMap if data else None
262
259
 
263
- def get_rented_item(
260
+ def get_rented_instance(
264
261
  self,
265
262
  token: str,
266
263
  instance_slug: Optional[str] = None,
@@ -282,7 +279,7 @@ class TheStageApiClient(TheStageApiClientCore):
282
279
 
283
280
  return InstanceRentedItemResponse.model_validate(response).instance_rented if response else None
284
281
 
285
- def get_selfhosted_item(
282
+ def get_selfhosted_instance(
286
283
  self,
287
284
  token: str,
288
285
  instance_slug: Optional[str] = None,
@@ -347,19 +344,6 @@ class TheStageApiClient(TheStageApiClientCore):
347
344
  data = SelfHostedRentedRentedBusinessStatusMapperResponse.model_validate(response) if response else None
348
345
  return data.selfhosted_instance_business_status_map if data else None
349
346
 
350
- def get_profile(
351
- self,
352
- token: str,
353
- ) -> Optional[UserProfileResponse]:
354
-
355
- response = self._request(
356
- method='GET',
357
- url='/frontend-api/user/my-profile',
358
- token=token,
359
- )
360
-
361
- result = UserProfileResponse.model_validate(response) if response else None
362
- return result if result else None
363
347
 
364
348
  def cancel_task(
365
349
  self,
@@ -521,8 +505,9 @@ class TheStageApiClient(TheStageApiClientCore):
521
505
 
522
506
  return ProjectRunTaskResponse.model_validate(response) if response else None
523
507
 
524
-
525
- async def poll_logs_httpx(self, token: str, docker_container_id: Optional[int], last_log_timestamp: str, last_log_id: str, task_id: Optional[int] = None, inference_simulator_id: Optional[int] = None) -> Optional[LogPollingResponse]:
508
+ async def poll_logs_httpx(self, token: str, docker_container_id: Optional[int], last_log_timestamp: str,
509
+ last_log_id: str, task_id: Optional[int] = None,
510
+ inference_simulator_id: Optional[int] = None) -> Optional[LogPollingResponse]:
526
511
  request_headers = {'Content-Type': 'application/json'}
527
512
  if token: request_headers['Authorization'] = f"Bearer {token}"
528
513
 
@@ -544,7 +529,6 @@ class TheStageApiClient(TheStageApiClientCore):
544
529
 
545
530
  return LogPollingResponse.model_validate(response.json()) if response else None
546
531
 
547
-
548
532
  def add_public_ssh_key_to_user(self, token: str, public_key: str, note: str) -> AddSshKeyToUserResponse:
549
533
  request = AddSshKeyToUserRequest(
550
534
  sshKey=public_key,
@@ -561,7 +545,6 @@ class TheStageApiClient(TheStageApiClientCore):
561
545
  result = AddSshKeyToUserResponse.model_validate(response) if response else None
562
546
  return result
563
547
 
564
-
565
548
  def is_user_has_ssh_public_key(self, token: str, public_key: str) -> IsUserHasSshPublicKeyResponse:
566
549
  request = IsUserHasSshPublicKeyRequest(
567
550
  sshKey=public_key,
@@ -577,8 +560,8 @@ class TheStageApiClient(TheStageApiClientCore):
577
560
  result = IsUserHasSshPublicKeyResponse.model_validate(response) if response else None
578
561
  return result
579
562
 
580
-
581
- def add_public_ssh_key_to_instance_rented(self, token: str, instance_rented_id: int, ssh_key_pair_id: int) -> AddSshPublicKeyToInstanceResponse:
563
+ def add_public_ssh_key_to_instance_rented(self, token: str, instance_rented_id: int,
564
+ ssh_key_pair_id: int) -> AddSshPublicKeyToInstanceResponse:
582
565
  request = AddSshPublicKeyToInstanceRequest(
583
566
  instanceRentedId=instance_rented_id,
584
567
  sshPublicKeyId=ssh_key_pair_id,
@@ -594,7 +577,6 @@ class TheStageApiClient(TheStageApiClientCore):
594
577
  result = AddSshPublicKeyToInstanceResponse.model_validate(response) if response else None
595
578
  return result
596
579
 
597
-
598
580
  def start_project_inference_simulator(
599
581
  self,
600
582
  token: str,
@@ -625,7 +607,6 @@ class TheStageApiClient(TheStageApiClientCore):
625
607
 
626
608
  return ProjectStartInferenceSimulatorResponse.model_validate(response) if response else None
627
609
 
628
-
629
610
  def push_project_inference_simulator_model(
630
611
  self,
631
612
  token: str,
@@ -644,7 +625,6 @@ class TheStageApiClient(TheStageApiClientCore):
644
625
 
645
626
  return ProjectPushInferenceSimulatorModelResponse.model_validate(response) if response else None
646
627
 
647
-
648
628
  def get_inference_simulator_business_status_map(self, token: str, ) -> Optional[Dict[str, str]]:
649
629
  response = self._request(
650
630
  method='POST',
@@ -657,7 +637,6 @@ class TheStageApiClient(TheStageApiClientCore):
657
637
 
658
638
  return data.inference_simulator_status_map if data else None
659
639
 
660
-
661
640
  def get_inference_simulator_model_business_status_map(self, token: str, ) -> Optional[Dict[str, str]]:
662
641
  response = self._request(
663
642
  method='POST',
@@ -688,7 +667,6 @@ class TheStageApiClient(TheStageApiClientCore):
688
667
  )
689
668
  return GetInferenceSimulatorResponse.model_validate(response) if response else None
690
669
 
691
-
692
670
  @error_handler()
693
671
  def deploy_inference_model_to_instance(
694
672
  self,
@@ -702,8 +680,8 @@ class TheStageApiClient(TheStageApiClientCore):
702
680
  request = DeployInferenceModelToInstanceRequest(
703
681
  inferenceSimulatorSlug=unique_id_with_timestamp,
704
682
  modelSlug=unique_id,
705
- instanceRentedSlug = rented_instance_unique_id,
706
- selfhostedInstanceSlug = self_hosted_instance_unique_id
683
+ instanceRentedSlug=rented_instance_unique_id,
684
+ selfhostedInstanceSlug=self_hosted_instance_unique_id
707
685
  )
708
686
 
709
687
  response = self._request(
@@ -714,7 +692,6 @@ class TheStageApiClient(TheStageApiClientCore):
714
692
  )
715
693
  return DeployInferenceModelToInstanceResponse.model_validate(response) if response else None
716
694
 
717
-
718
695
  @error_handler()
719
696
  def deploy_inference_model_to_sagemaker(
720
697
  self,
@@ -735,8 +712,9 @@ class TheStageApiClient(TheStageApiClientCore):
735
712
  )
736
713
  return DeployInferenceModelToSagemakerResponse.model_validate(response) if response else None
737
714
 
738
-
739
- def query_user_logs(self, token: str, limit: int, task_id: Optional[int] = None, inference_simulator_id: Optional[int] = None, container_id: Optional[int] = None) -> UserLogsQueryResponse:
715
+ def query_user_logs(self, token: str, limit: int, task_id: Optional[int] = None,
716
+ inference_simulator_id: Optional[int] = None,
717
+ container_id: Optional[int] = None) -> UserLogsQueryResponse:
740
718
  request = UserLogsQueryRequest(
741
719
  inferenceSimulatorId=inference_simulator_id,
742
720
  taskId=task_id,
@@ -753,4 +731,4 @@ class TheStageApiClient(TheStageApiClientCore):
753
731
  )
754
732
 
755
733
  result = UserLogsQueryResponse.model_validate(response) if response else None
756
- return result
734
+ return result
@@ -3,7 +3,10 @@ from typing import Optional
3
3
  from pydantic import BaseModel, Field
4
4
 
5
5
 
6
- class UserProfileResponse(BaseModel):
7
- name: Optional[str] = Field(None, alias='name')
6
+ class UserProfile(BaseModel):
8
7
  email: Optional[str] = Field(None, alias='email')
9
- metamask_wallet: Optional[str] = Field(None, alias='metamaskWallet')
8
+
9
+
10
+
11
+ class UserProfileResponse(BaseModel):
12
+ userProfile: Optional[UserProfile] = Field(None, alias='userProfile')
@@ -10,7 +10,7 @@ from thestage.exceptions.file_system_exception import FileSystemException
10
10
  from thestage.services.core_files.config_entity import ConfigEntity
11
11
  from thestage.helpers.ssh_util import parse_private_key
12
12
  from thestage.services.connect.dto.remote_server_config import RemoteServerConfig
13
- from thestage.services.filesystem_service import FileSystemServiceCore
13
+ from thestage.services.filesystem_service import FileSystemService
14
14
  from thestage.services.project.dto.project_config import ProjectConfig
15
15
  from thestage.config import THESTAGE_CONFIG_DIR, THESTAGE_CONFIG_FILE, THESTAGE_AUTH_TOKEN, THESTAGE_API_URL
16
16
 
@@ -20,30 +20,27 @@ class ConfigProvider():
20
20
  _local_config_path: Optional[Path] = None
21
21
  _global_config_path: Optional[Path] = None
22
22
  _global_config_file: Optional[Path] = None
23
- _file_system_service = FileSystemServiceCore
23
+ _file_system_service = FileSystemService
24
24
 
25
25
 
26
26
  def __init__(
27
27
  self,
28
28
  local_path: Optional[str] = None,
29
29
  ):
30
- self._file_system_service = FileSystemServiceCore()
30
+ self._file_system_service = FileSystemService()
31
31
  if local_path:
32
32
  self._local_path = self._file_system_service.get_path(directory=local_path, auto_create=False)
33
33
 
34
- config_folder_name = self._file_system_service.get_path(f"{THESTAGE_CONFIG_DIR}", False)
35
- self._local_config_path = self._local_path.joinpath(config_folder_name)
34
+ self._local_config_path = self._local_path.joinpath(THESTAGE_CONFIG_DIR)
36
35
 
37
36
  home_dir = self._file_system_service.get_home_path()
38
- self._global_config_path = home_dir.joinpath(config_folder_name)
37
+ self._global_config_path = home_dir.joinpath(THESTAGE_CONFIG_DIR)
39
38
 
40
39
  if self._global_config_path:
41
40
  if not self._global_config_path.exists():
42
41
  self._file_system_service.create_if_not_exists_dir(self._global_config_path)
43
42
 
44
- self._global_config_file = self._global_config_path.joinpath(
45
- self._file_system_service.get_path(f"{THESTAGE_CONFIG_FILE}", False)
46
- )
43
+ self._global_config_file = self._global_config_path.joinpath(THESTAGE_CONFIG_FILE)
47
44
  if not self._global_config_file.exists():
48
45
  self._file_system_service.create_if_not_exists_file(self._global_config_file)
49
46
 
@@ -61,7 +58,7 @@ class ConfigProvider():
61
58
  if config_from_env:
62
59
  self.__update_config_values_dict(values_to_update=config_values, new_values=config_from_env)
63
60
 
64
- config_from_file = self.__read_config_file(self._global_config_file)
61
+ config_from_file = self._file_system_service.read_config_file(self._global_config_file)
65
62
  if config_from_file:
66
63
  self.__update_config_values_dict(values_to_update=config_values, new_values=config_from_file)
67
64
 
@@ -112,7 +109,7 @@ class ConfigProvider():
112
109
  if not project_data_filepath.exists():
113
110
  return None
114
111
 
115
- config_data = self.__read_config_file(project_data_filepath) if project_data_filepath and project_data_filepath.exists() else {}
112
+ config_data = self._file_system_service.read_config_file(project_data_filepath) if project_data_filepath and project_data_filepath.exists() else {}
116
113
  return ProjectConfig.model_validate(config_data)
117
114
 
118
115
 
@@ -165,7 +162,7 @@ class ConfigProvider():
165
162
  if not config_filepath.is_file():
166
163
  return None
167
164
 
168
- config_data = self.__read_config_file(config_filepath) if config_filepath and config_filepath.exists() else {}
165
+ config_data = self._file_system_service.read_config_file(config_filepath) if config_filepath and config_filepath.exists() else {}
169
166
  return RemoteServerConfig.model_validate(config_data)
170
167
 
171
168
 
@@ -188,22 +185,6 @@ class ConfigProvider():
188
185
  else:
189
186
  values_to_update['main'] = new_values['main']
190
187
 
191
-
192
- def __read_config_file(self, path: Path) -> Dict[str, Any]:
193
- result = {}
194
- try:
195
- if path and path.exists():
196
- with path.open("r") as file:
197
- try:
198
- if os.stat(path).st_size != 0:
199
- result = json.load(file)
200
- except JSONDecodeError:
201
- pass
202
- except OSError:
203
- raise FileSystemException(f"Could not open config file: {path}")
204
- return result
205
-
206
-
207
188
  @staticmethod
208
189
  def __save_config_file(data: Dict, file_path: Path):
209
190
  with open(file_path, 'w') as configfile:
@@ -211,7 +192,7 @@ class ConfigProvider():
211
192
 
212
193
 
213
194
  def save_config(self, config: ConfigEntity):
214
- data: Dict[str, Any] = self.__read_config_file(self._global_config_file)
195
+ data: Dict[str, Any] = self._file_system_service.read_config_file(self._global_config_file)
215
196
  data.update(config.model_dump(exclude_none=True, by_alias=True, exclude={'runtime', 'RUNTIME', 'daemon', 'DAEMON'}))
216
197
  self.__save_config_file(data=data, file_path=self._global_config_file)
217
198
 
@@ -50,20 +50,25 @@ class ConnectService(AbstractService):
50
50
  ):
51
51
  config = self._config_provider.get_full_config()
52
52
 
53
- # TODO make a single separate method that will return all needed info
54
53
  try:
55
- instance_selfhosted = self.__thestage_api_client.get_selfhosted_item(token=config.main.thestage_auth_token, instance_slug=uid)
54
+ instance_selfhosted = self.__thestage_api_client.get_selfhosted_instance(token=config.main.thestage_auth_token, instance_slug=uid)
56
55
  except HttpClientException as e:
56
+ if e.get_status_code() == 403:
57
+ typer.echo("Missing permission to view self-hosted instances")
57
58
  instance_selfhosted = None
58
59
 
59
60
  try:
60
- instance_rented = self.__thestage_api_client.get_rented_item(token=config.main.thestage_auth_token, instance_slug=uid)
61
+ instance_rented = self.__thestage_api_client.get_rented_instance(token=config.main.thestage_auth_token, instance_slug=uid)
61
62
  except HttpClientException as e:
63
+ if e.get_status_code() == 403:
64
+ typer.echo("Missing permission to view rented instances")
62
65
  instance_rented = None
63
66
 
64
67
  try:
65
68
  container = self.__thestage_api_client.get_container(token=config.main.thestage_auth_token, container_slug=uid, )
66
- except Exception as e:
69
+ except HttpClientException as e:
70
+ if e.get_status_code() == 403:
71
+ typer.echo("Missing permission to view containers")
67
72
  container = None
68
73
 
69
74
  task: Optional[TaskDto] = None
@@ -71,6 +76,8 @@ class ConnectService(AbstractService):
71
76
  try:
72
77
  task_view_response = self.__thestage_api_client.get_task(token=config.main.thestage_auth_token, task_id=int(uid))
73
78
  except HttpClientException as e:
79
+ if e.get_status_code() == 403:
80
+ typer.echo("Missing permission to view tasks")
74
81
  task_view_response = None
75
82
  if task_view_response and task_view_response.task:
76
83
  task = task_view_response.task
@@ -148,7 +155,7 @@ class ConnectService(AbstractService):
148
155
  instance_rented: Optional[InstanceRentedDto] = None
149
156
  if instance_slug:
150
157
  try:
151
- instance_rented = self.__thestage_api_client.get_rented_item(token=config.main.thestage_auth_token, instance_slug=instance_slug)
158
+ instance_rented = self.__thestage_api_client.get_rented_instance(token=config.main.thestage_auth_token, instance_slug=instance_slug)
152
159
  except HttpClientException as e:
153
160
  instance_rented = None
154
161
 
@@ -10,7 +10,7 @@ from thestage.services.clients.thestage_api.dtos.enums.container_status import D
10
10
  from thestage.entities.enums.shell_type import ShellType
11
11
  from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
12
12
  from thestage.services.container.mapper.container_mapper import ContainerMapper
13
- from thestage.services.filesystem_service import FileSystemServiceCore
13
+ from thestage.services.filesystem_service import FileSystemService
14
14
  from thestage.services.remote_server_service import RemoteServerService
15
15
  from thestage.i18n.translation import __
16
16
  from thestage.services.abstract_service import AbstractService
@@ -29,7 +29,7 @@ class ContainerService(AbstractService):
29
29
  thestage_api_client: TheStageApiClient,
30
30
  config_provider: ConfigProvider,
31
31
  remote_server_service: RemoteServerService,
32
- file_system_service: FileSystemServiceCore,
32
+ file_system_service: FileSystemService,
33
33
  ):
34
34
  super(ContainerService, self).__init__(
35
35
  config_provider=config_provider
@@ -7,11 +7,6 @@ class MainConfigEntity(BaseModel):
7
7
  thestage_auth_token: Optional[str] = Field(None, alias='thestage_auth_token')
8
8
  thestage_api_url: Optional[str] = Field(None, alias='thestage_api_url')
9
9
 
10
-
11
- class DaemonConfigEntity(BaseModel):
12
- daemon_token: Optional[str] = Field(None, alias='daemon_token')
13
- backend_api_url: Optional[str] = Field(None, alias='backend_api_url')
14
-
15
10
  # not saved to file
16
11
  class RuntimeConfigEntity(BaseModel):
17
12
  working_directory: Optional[str] = Field(None, alias='working_directory')
@@ -19,7 +14,7 @@ class RuntimeConfigEntity(BaseModel):
19
14
 
20
15
 
21
16
  class ConfigEntity(BaseModel):
17
+ global_config_path: str = Field(None, alias='global_config_path')
18
+ can_use_inference: bool = Field(None, alias='can_use_inference')
22
19
  main: MainConfigEntity = Field(default_factory=MainConfigEntity, alias='main')
23
20
  runtime: RuntimeConfigEntity = Field(default_factory=RuntimeConfigEntity, alias="runtime") # TODO merge with main
24
- daemon: DaemonConfigEntity = Field(default_factory=DaemonConfigEntity, alias="daemon") # TODO this should not be in core package
25
- start_on_daemon: bool = Field(False, alias='start_on_daemon') # TODO this should not be in core package
@@ -1,13 +1,15 @@
1
+ import json
1
2
  import os
2
3
  import shutil
4
+ from json import JSONDecodeError
3
5
  from pathlib import Path
4
- from typing import Optional, List
6
+ from typing import Optional, List, Dict, Any
5
7
 
6
8
  from thestage.entities.file_item import FileItemEntity
7
9
  from thestage.exceptions.file_system_exception import FileSystemException
8
10
 
9
11
 
10
- class FileSystemServiceCore:
12
+ class FileSystemService:
11
13
 
12
14
  def get_ssh_path(self) -> Optional[Path]:
13
15
  home_path = self.get_home_path()
@@ -114,3 +116,18 @@ class FileSystemServiceCore:
114
116
  real_path = self.get_path(directory=path, auto_create=False)
115
117
  if real_path and real_path.exists():
116
118
  shutil.rmtree(real_path)
119
+
120
+
121
+ def read_config_file(self, path: Path) -> Dict[str, Any]:
122
+ result = {}
123
+ try:
124
+ if path and path.exists():
125
+ with path.open("r") as file:
126
+ try:
127
+ if os.stat(path).st_size != 0:
128
+ result = json.load(file)
129
+ except JSONDecodeError:
130
+ pass
131
+ except OSError:
132
+ raise FileSystemException(f"Could not open config file: {path}")
133
+ return result
@@ -2,6 +2,9 @@ from pathlib import Path
2
2
  from typing import List, Optional, Dict
3
3
 
4
4
  import typer
5
+
6
+ from thestage.entities.rented_instance import RentedInstanceEntity
7
+ from thestage.entities.self_hosted_instance import SelfHostedInstanceEntity
5
8
  from thestage.services.core_files.config_entity import ConfigEntity
6
9
  from thestage.i18n.translation import __
7
10
  from thestage.services.clients.thestage_api.dtos.enums.selfhosted_status import SelfhostedBusinessStatus
@@ -13,6 +16,8 @@ from thestage.services.clients.thestage_api.dtos.instance_rented_response import
13
16
  from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
14
17
  from thestage.services.clients.thestage_api.dtos.selfhosted_instance_response import SelfHostedInstanceDto
15
18
  from thestage.services.config_provider.config_provider import ConfigProvider
19
+ from thestage.services.instance.mapper.instance_mapper import InstanceMapper
20
+ from thestage.services.instance.mapper.selfhosted_mapper import SelfHostedMapper
16
21
  from thestage.services.remote_server_service import RemoteServerService
17
22
 
18
23
 
@@ -32,22 +37,22 @@ class InstanceService(AbstractService):
32
37
  self.__thestage_api_client = thestage_api_client
33
38
  self.__remote_server_service = remote_server_service
34
39
 
35
- def get_rented_item(
40
+ def get_rented_instance(
36
41
  self,
37
42
  config: ConfigEntity,
38
43
  instance_slug: str,
39
44
  ) -> Optional[InstanceRentedDto]:
40
- return self.__thestage_api_client.get_rented_item(
45
+ return self.__thestage_api_client.get_rented_instance(
41
46
  token=config.main.thestage_auth_token,
42
47
  instance_slug=instance_slug,
43
48
  )
44
49
 
45
- def get_self_hosted_item(
50
+ def get_self_hosted_instance(
46
51
  self,
47
52
  config: ConfigEntity,
48
53
  instance_slug: str,
49
54
  ) -> Optional[SelfHostedInstanceDto]:
50
- return self.__thestage_api_client.get_selfhosted_item(
55
+ return self.__thestage_api_client.get_selfhosted_instance(
51
56
  token=config.main.thestage_auth_token,
52
57
  instance_slug=instance_slug,
53
58
  )
@@ -121,7 +126,7 @@ class InstanceService(AbstractService):
121
126
  config: ConfigEntity,
122
127
  input_ssh_key_path: Optional[str]
123
128
  ):
124
- instance = self.get_rented_item(config=config, instance_slug=instance_rented_slug)
129
+ instance = self.get_rented_instance(config=config, instance_slug=instance_rented_slug)
125
130
 
126
131
  if instance:
127
132
  self.check_instance_status_to_connect(
@@ -162,7 +167,7 @@ class InstanceService(AbstractService):
162
167
  username = 'root'
163
168
  typer.echo(__("No remote server username provided, using 'root' as username"))
164
169
 
165
- instance = self.get_self_hosted_item(config=config, instance_slug=selfhosted_instance_slug)
170
+ instance = self.get_self_hosted_instance(config=config, instance_slug=selfhosted_instance_slug)
166
171
 
167
172
  if instance:
168
173
  self.check_selfhosted_status_to_connect(
@@ -222,3 +227,92 @@ class InstanceService(AbstractService):
222
227
  limit=row,
223
228
  )
224
229
  return data
230
+
231
+
232
+ @error_handler()
233
+ def print_self_hosted_instance_list(self, config: ConfigEntity, statuses, row, page):
234
+ selfhosted_instance_status_map = self.__thestage_api_client.get_selfhosted_business_status_map(config.main.thestage_auth_token)
235
+
236
+ if not statuses:
237
+ statuses = ({key: selfhosted_instance_status_map[key] for key in [
238
+ SelfhostedBusinessStatus.AWAITING_CONFIGURATION,
239
+ SelfhostedBusinessStatus.RUNNING,
240
+ SelfhostedBusinessStatus.TERMINATED,
241
+ ]}).values()
242
+
243
+ if "all" in statuses:
244
+ statuses = selfhosted_instance_status_map.values()
245
+
246
+ for input_status_item in statuses:
247
+ if input_status_item not in selfhosted_instance_status_map.values():
248
+ typer.echo(__("'%invalid_status%' is not one of %valid_statuses%", {
249
+ 'invalid_status': input_status_item,
250
+ 'valid_statuses': str(list(selfhosted_instance_status_map.values()))
251
+ }))
252
+ raise typer.Exit(1)
253
+
254
+ typer.echo(__(
255
+ "Listing self-hosted instances with the following statuses: %statuses%, to view all self-hosted instances, use --status all",
256
+ placeholders={
257
+ 'statuses': ', '.join([status_item for status_item in statuses])
258
+ }))
259
+
260
+ backend_statuses: List[str] = [key for key, value in selfhosted_instance_status_map.items() if value in statuses]
261
+
262
+ self.print(
263
+ func_get_data=self.get_self_hosted_list,
264
+ func_special_params={
265
+ 'statuses': backend_statuses,
266
+ },
267
+ mapper=SelfHostedMapper(),
268
+ config=config,
269
+ headers=list(map(lambda x: x.alias, SelfHostedInstanceEntity.model_fields.values())),
270
+ row=row,
271
+ page=page,
272
+ show_index="never",
273
+ )
274
+
275
+
276
+ @error_handler()
277
+ def print_rented_instance_list(self, config: ConfigEntity, statuses, row, page):
278
+ instance_rented_status_map = self.__thestage_api_client.get_rented_business_status_map(config.main.thestage_auth_token)
279
+
280
+ if not statuses:
281
+ statuses = ({key: instance_rented_status_map[key] for key in [
282
+ InstanceRentedBusinessStatus.ONLINE,
283
+ InstanceRentedBusinessStatus.CREATING,
284
+ InstanceRentedBusinessStatus.TERMINATING,
285
+ InstanceRentedBusinessStatus.REBOOTING,
286
+ ]}).values()
287
+
288
+ if "all" in statuses:
289
+ statuses = instance_rented_status_map.values()
290
+
291
+ for input_status_item in statuses:
292
+ if input_status_item not in instance_rented_status_map.values():
293
+ typer.echo(__("'%invalid_status%' is not one of %valid_statuses%", {
294
+ 'invalid_status': input_status_item,
295
+ 'valid_statuses': str(list(instance_rented_status_map.values()))
296
+ }))
297
+ raise typer.Exit(1)
298
+
299
+ typer.echo(__(
300
+ "Listing rented server instances with the following statuses: %statuses%, to view all rented server instances, use --status all",
301
+ placeholders={
302
+ 'statuses': ', '.join([status_item for status_item in statuses])
303
+ }))
304
+
305
+ backend_statuses: List[str] = [key for key, value in instance_rented_status_map.items() if value in statuses]
306
+
307
+ self.print(
308
+ func_get_data=self.get_rented_list,
309
+ func_special_params={
310
+ 'statuses': backend_statuses,
311
+ },
312
+ mapper=InstanceMapper(),
313
+ config=config,
314
+ headers=list(map(lambda x: x.alias, RentedInstanceEntity.model_fields.values())),
315
+ row=row,
316
+ page=page,
317
+ show_index="never",
318
+ )
@@ -12,7 +12,12 @@ import typer
12
12
  from git import Commit
13
13
  from tabulate import tabulate
14
14
 
15
+ from thestage.entities.project_inference_simulator import ProjectInferenceSimulatorEntity
16
+ from thestage.entities.project_inference_simulator_model import ProjectInferenceSimulatorModelEntity
17
+ from thestage.entities.project_task import ProjectTaskEntity
15
18
  from thestage.services.clients.thestage_api.core.http_client_exception import HttpClientException
19
+ from thestage.services.clients.thestage_api.dtos.enums.inference_model_status import InferenceModelStatus
20
+ from thestage.services.clients.thestage_api.dtos.enums.inference_simulator_status import InferenceSimulatorStatus
16
21
  from thestage.services.core_files.config_entity import ConfigEntity
17
22
  from thestage.color_scheme.color_scheme import ColorScheme
18
23
  from thestage.entities.enums.yes_no_response import YesOrNoResponse
@@ -36,9 +41,12 @@ from thestage.services.clients.thestage_api.dtos.project_controller.project_star
36
41
  ProjectStartInferenceSimulatorResponse
37
42
  from thestage.services.clients.thestage_api.dtos.project_response import ProjectDto
38
43
  from thestage.services.clients.thestage_api.dtos.task_controller.task_view_response import TaskViewResponse
39
- from thestage.services.filesystem_service import FileSystemServiceCore
44
+ from thestage.services.filesystem_service import FileSystemService
40
45
  from thestage.services.project.dto.inference_simulator_dto import InferenceSimulatorDto
41
46
  from thestage.services.project.dto.inference_simulator_model_dto import InferenceSimulatorModelDto
47
+ from thestage.services.project.mapper.project_inference_simulator_mapper import ProjectInferenceSimulatorMapper
48
+ from thestage.services.project.mapper.project_inference_simulator_model_mapper import \
49
+ ProjectInferenceSimulatorModelMapper
42
50
  from thestage.services.task.dto.task_dto import TaskDto
43
51
  from thestage.services.project.dto.project_config import ProjectConfig
44
52
  from thestage.services.project.mapper.project_task_mapper import ProjectTaskMapper
@@ -58,7 +66,7 @@ class ProjectService(AbstractService):
58
66
  thestage_api_client: TheStageApiClient,
59
67
  config_provider: ConfigProvider,
60
68
  remote_server_service: RemoteServerService,
61
- file_system_service: FileSystemServiceCore,
69
+ file_system_service: FileSystemService,
62
70
  git_local_client: GitLocalClient,
63
71
  ):
64
72
  super(ProjectService, self).__init__(
@@ -1139,3 +1147,134 @@ class ProjectService(AbstractService):
1139
1147
  deploy_key_path=project_config.deploy_key_path,
1140
1148
  reset_to_origin=True
1141
1149
  )
1150
+
1151
+
1152
+ @error_handler()
1153
+ def print_inference_simulator_list(self, config, project_uid, statuses, row, page):
1154
+ if not project_uid:
1155
+ project_config: ProjectConfig = self.__config_provider.read_project_config()
1156
+ if not project_config:
1157
+ typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
1158
+ raise typer.Exit(1)
1159
+ project_uid = project_config.slug
1160
+
1161
+ inference_simulator_status_map = self.__thestage_api_client.get_inference_simulator_business_status_map(
1162
+ config.main.thestage_auth_token)
1163
+
1164
+ if not statuses:
1165
+ statuses = ({key: inference_simulator_status_map[key] for key in [
1166
+ InferenceSimulatorStatus.SCHEDULED,
1167
+ InferenceSimulatorStatus.CREATING,
1168
+ InferenceSimulatorStatus.RUNNING,
1169
+ ]}).values()
1170
+
1171
+ if "all" in statuses:
1172
+ statuses = inference_simulator_status_map.values()
1173
+
1174
+ for input_status_item in statuses:
1175
+ if input_status_item not in inference_simulator_status_map.values():
1176
+ typer.echo(__("'%invalid_status%' is not one of %valid_statuses%", {
1177
+ 'invalid_status': input_status_item,
1178
+ 'valid_statuses': str(list(inference_simulator_status_map.values()))
1179
+ }))
1180
+ raise typer.Exit(1)
1181
+
1182
+ typer.echo(__(
1183
+ "Listing inference simulators with the following statuses: %statuses%, to view all inference simulators, use --status all",
1184
+ placeholders={
1185
+ 'statuses': ', '.join([status_item for status_item in statuses])
1186
+ }))
1187
+
1188
+ backend_statuses: List[str] = [key for key, value in inference_simulator_status_map.items() if value in statuses]
1189
+
1190
+ self.print(
1191
+ func_get_data=self.get_project_inference_simulator_list,
1192
+ func_special_params={
1193
+ 'project_slug': project_uid,
1194
+ 'statuses': backend_statuses,
1195
+ },
1196
+ mapper=ProjectInferenceSimulatorMapper(),
1197
+ config=config,
1198
+ headers=list(map(lambda x: x.alias, ProjectInferenceSimulatorEntity.model_fields.values())),
1199
+ row=row,
1200
+ page=page,
1201
+ max_col_width=[100, 100, 100, 100, 100, 100, 100, 100],
1202
+ show_index="never",
1203
+ )
1204
+
1205
+
1206
+ @error_handler()
1207
+ def print_inference_simulator_model_list(self, config, project_uid, statuses, row, page):
1208
+ if not project_uid:
1209
+ project_config: ProjectConfig = self.__config_provider.read_project_config()
1210
+ if not project_config:
1211
+ typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
1212
+ raise typer.Exit(1)
1213
+ project_uid = project_config.slug
1214
+
1215
+ inference_simulator_model_status_map = self.__thestage_api_client.get_inference_simulator_model_business_status_map(
1216
+ config.main.thestage_auth_token)
1217
+
1218
+ if not statuses:
1219
+ statuses = ({key: inference_simulator_model_status_map[key] for key in [
1220
+ InferenceModelStatus.SCHEDULED,
1221
+ InferenceModelStatus.PROCESSING,
1222
+ InferenceModelStatus.PUSH_SUCCEED,
1223
+ ]}).values()
1224
+
1225
+ if "all" in statuses:
1226
+ statuses = inference_simulator_model_status_map.values()
1227
+
1228
+ for input_status_item in statuses:
1229
+ if input_status_item not in inference_simulator_model_status_map.values():
1230
+ typer.echo(__("'%invalid_status%' is not one of %valid_statuses%", {
1231
+ 'invalid_status': input_status_item,
1232
+ 'valid_statuses': str(list(inference_simulator_model_status_map.values()))
1233
+ }))
1234
+ raise typer.Exit(1)
1235
+
1236
+ typer.echo(__(
1237
+ "Listing inference simulator models with the following statuses: %statuses%, to view all inference simulator models, use --status all",
1238
+ placeholders={
1239
+ 'statuses': ', '.join([status_item for status_item in statuses])
1240
+ }))
1241
+
1242
+ backend_statuses: List[str] = [key for key, value in inference_simulator_model_status_map.items() if value in statuses]
1243
+
1244
+ self.print(
1245
+ func_get_data=self.get_project_inference_simulator_model_list,
1246
+ func_special_params={
1247
+ 'project_slug': project_uid,
1248
+ 'statuses': backend_statuses,
1249
+ },
1250
+ mapper=ProjectInferenceSimulatorModelMapper(),
1251
+ config=config,
1252
+ headers=list(map(lambda x: x.alias, ProjectInferenceSimulatorModelEntity.model_fields.values())),
1253
+ row=row,
1254
+ page=page,
1255
+ max_col_width=[100, 100, 100, 100, 100, 100, 100, 100],
1256
+ show_index="never",
1257
+ )
1258
+
1259
+
1260
+ def print_task_list(self, config: ConfigEntity, project_uid, row, page):
1261
+ if not project_uid:
1262
+ project_config: ProjectConfig = self.__config_provider.read_project_config()
1263
+ if not project_config:
1264
+ typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
1265
+ raise typer.Exit(1)
1266
+ project_uid = project_config.slug
1267
+
1268
+ self.print(
1269
+ func_get_data=self.get_project_task_list,
1270
+ func_special_params={
1271
+ 'project_slug': project_uid,
1272
+ },
1273
+ mapper=ProjectTaskMapper(),
1274
+ config=config,
1275
+ headers=list(map(lambda x: x.alias, ProjectTaskEntity.model_fields.values())),
1276
+ row=row,
1277
+ page=page,
1278
+ max_col_width=[100, 100, 100, 100, 100, 100, 100, 100],
1279
+ show_index="never",
1280
+ )
@@ -21,7 +21,7 @@ from thestage.helpers.ssh_util import parse_private_key
21
21
  from thestage.i18n.translation import __
22
22
  from thestage.services.clients.thestage_api.dtos.sftp_path_helper import SftpFileItemEntity
23
23
  from thestage.services.config_provider.config_provider import ConfigProvider
24
- from thestage.services.filesystem_service import FileSystemServiceCore
24
+ from thestage.services.filesystem_service import FileSystemService
25
25
 
26
26
  old_value: int = 0
27
27
 
@@ -30,7 +30,7 @@ class RemoteServerService:
30
30
 
31
31
  def __init__(
32
32
  self,
33
- file_system_service: FileSystemServiceCore,
33
+ file_system_service: FileSystemService,
34
34
  config_provider: ConfigProvider,
35
35
  ):
36
36
  self.__file_system_service = file_system_service
@@ -1,7 +1,7 @@
1
1
  from typing import Optional
2
2
 
3
3
  from thestage.services.connect.connect_service import ConnectService
4
- from thestage.services.filesystem_service import FileSystemServiceCore
4
+ from thestage.services.filesystem_service import FileSystemService
5
5
  from thestage.services.logging.logging_service import LoggingService
6
6
  from thestage.services.project.project_service import ProjectService
7
7
  from thestage.services.remote_server_service import RemoteServerService
@@ -18,7 +18,7 @@ class ServiceFactory:
18
18
  __config_provider: Optional[ConfigProvider] = None
19
19
  __thestage_api_client: Optional[TheStageApiClient] = None
20
20
  __git_local_client: Optional[GitLocalClient] = None
21
- __file_system_service: Optional[FileSystemServiceCore] = None
21
+ __file_system_service: Optional[FileSystemService] = None
22
22
 
23
23
  def __init__(
24
24
  self,
@@ -84,9 +84,9 @@ class ServiceFactory:
84
84
  self.__git_local_client = GitLocalClient(file_system_service=self.get_file_system_service())
85
85
  return self.__git_local_client
86
86
 
87
- def get_file_system_service(self) -> FileSystemServiceCore:
87
+ def get_file_system_service(self) -> FileSystemService:
88
88
  if not self.__file_system_service:
89
- self.__file_system_service = FileSystemServiceCore()
89
+ self.__file_system_service = FileSystemService()
90
90
  return self.__file_system_service
91
91
 
92
92
  def get_app_config_service(self, config_provider: Optional[ConfigProvider] = None,) -> AppConfigService:
@@ -53,10 +53,4 @@ class ValidationService:
53
53
  if not config.main.thestage_auth_token:
54
54
  present_token = False
55
55
 
56
- if config.start_on_daemon:
57
- if config.daemon and config.daemon.daemon_token:
58
- present_token = True
59
- else:
60
- present_token = False
61
-
62
56
  return present_token
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: thestage
3
- Version: 0.5.44
3
+ Version: 0.5.45
4
4
  Summary:
5
5
  Author: TheStage AI team
6
6
  Author-email: hello@thestage.ai
@@ -21,7 +21,7 @@ Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
21
21
  Requires-Dist: python-gettext-translations (>=1.1.0,<2.0.0)
22
22
  Requires-Dist: requests (>=2.31.0,<3.0.0)
23
23
  Requires-Dist: tabulate (>=0.9.0,<0.10.0)
24
- Requires-Dist: typer[all] (>=0.9.0,<0.10.0)
24
+ Requires-Dist: typer[all] (>=0.15.2,<0.16.0)
25
25
  Description-Content-Type: text/markdown
26
26
 
27
27
  # Introduction
@@ -1,4 +1,4 @@
1
- thestage/__init__.py,sha256=DhlhvDK-7GKoSl3QZHDW8oTMV7AnpgXhIye7Rw0LV10,65
1
+ thestage/__init__.py,sha256=jF3zpsm_hT2fThFl_9xh6OFpHhG5nMHLJtncxIQBu1A,65
2
2
  thestage/__main__.py,sha256=4ObdWrDRaIASaR06IxtFSsoMu58eyL0MnD64habvPj8,101
3
3
  thestage/color_scheme/color_scheme.py,sha256=qaSSS_OzPsqI7yV1TC3Ne0PnsWDWo5xqU8j_7JYG-TI,210
4
4
  thestage/config/__init__.py,sha256=RNobilYVK1WAM1utcQ8ZuATKc9Zh9M9BAjCLZTnR_TA,428
@@ -6,9 +6,9 @@ thestage/config/env_base.py,sha256=RNBQ17yk1ieu1kdUlM7Qe7mDCoxstgGUwwhe265o4dQ,3
6
6
  thestage/controllers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  thestage/controllers/base_controller.py,sha256=lX0XsBc7ZEPD_I56cN8IBAVuWGIkOkr7JHvist3_FEM,2135
8
8
  thestage/controllers/config_controller.py,sha256=Gzd61UeU1igFT4QUyrZ4dOo_QaNEuXuSEIroXpbBhPA,5365
9
- thestage/controllers/container_controller.py,sha256=C3WC-Ypeg-vpC8LyCcPZVszbiaDYf2aQzTxYC2PPG8g,15210
10
- thestage/controllers/instance_controller.py,sha256=pFhkO7U2Ta0_1dzskEj8hbE7Izw_7I4SDbq5O5-bfIY,9757
11
- thestage/controllers/project_controller.py,sha256=GcfwJfn7_AfVBeGcm3jOVr38SOUT26yyyv91MyDX-YU,36725
9
+ thestage/controllers/container_controller.py,sha256=sSjrkjCQtn-DQJTeUCYYdzwOoGIGniA-MQ3y3BleVsE,14967
10
+ thestage/controllers/instance_controller.py,sha256=3jaM7bYICviAl9_rgkt4S1v9S-bEAAJ18qKDzuMpZlQ,6687
11
+ thestage/controllers/project_controller.py,sha256=ueQJI7lAwwPMJa7evVg_unUnAsTmgz204veOQIxFWSU,31778
12
12
  thestage/controllers/utils_controller.py,sha256=FV35yte7jTZRzy2DaL3OZCNzmlVrsNKxksC8P0FD7hM,1030
13
13
  thestage/debug_main.dist.py,sha256=UPIJ58yf-6FtXZj-FLAwxi7HononseuCYm9xb5KlxTs,783
14
14
  thestage/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -41,7 +41,7 @@ thestage/helpers/logger/app_logger.py,sha256=hUuxgUsj4pl9Ogjt1xJePTf71iVxKzyx46d
41
41
  thestage/helpers/ssh_util.py,sha256=JuDwddHxEGcA24Y8a-jLv339cG-jq4hEaBAl5TSVVFw,1262
42
42
  thestage/i18n/en_GB/messages.po,sha256=BuVIhd5TRQkgFkAbTGvbSRuO88lSJGpnk9TT2J9BC8E,32375
43
43
  thestage/i18n/translation.py,sha256=c62OicQ4phSMuqDe7hqGebIsk0W2-8ZJUfgfdtjjqEc,284
44
- thestage/main.py,sha256=3gHKEbOmpUTT5byvD9gPgT2uoaijAJUoa7G5dSnVlbs,784
44
+ thestage/main.py,sha256=qjlm4kSgT4Gnr4kyjYmHypj0RTk90JYHscP1w8P1Zwg,935
45
45
  thestage/services/.env,sha256=K2VpzFAVjD75XawAHZdR0HWmypryA_mXNY4WHNgR-wQ,184
46
46
  thestage/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  thestage/services/abstract_mapper.py,sha256=_q7YLkPNRsNW5wOCqvZIu1KfpLkc7uVaAQKrMZtsGuY,218
@@ -50,9 +50,9 @@ thestage/services/app_config_service.py,sha256=a7zrbVCJx6XCSRCMv346AYQ_gV3fzw8g7
50
50
  thestage/services/clients/.DS_Store,sha256=EYALnKLNXhZ-2jJTMck8Fo1bIxlFCvaXGUUUf-lgHxM,6148
51
51
  thestage/services/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
52
  thestage/services/clients/git/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
- thestage/services/clients/git/git_client.py,sha256=2qARWz1VQBKZTG4Spdkx0wBf5oGyU3d9Hnqmeuz8Bbs,12724
53
+ thestage/services/clients/git/git_client.py,sha256=y1ZHgFu5l6tQ3l7SCJVLP81VDGTkCWofhOsVruZwJHo,12716
54
54
  thestage/services/clients/thestage_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
- thestage/services/clients/thestage_api/api_client.py,sha256=ZkEbYOg79-RkG9on64tWTto1zXKnG38eKgIy7aS-2lc,29586
55
+ thestage/services/clients/thestage_api/api_client.py,sha256=W28SETPflYnOQgb0WoGaleqYtR8EtiOYllcOqUbK-pE,29336
56
56
  thestage/services/clients/thestage_api/core/api_client_abstract.py,sha256=nJ0OiT4Ecexp-3HHK332pvyzrf1JsZ1WQYdvn-aeIL8,2984
57
57
  thestage/services/clients/thestage_api/core/api_client_core.py,sha256=WwtzdTAxog-l2UU8Up40BxepgM7OTXn-XHgzlHorXT0,908
58
58
  thestage/services/clients/thestage_api/core/http_client_exception.py,sha256=JH-874Gu9T1b1_FpPBLqdyt9U0PyhpwRCe_oDc6c_jI,385
@@ -131,19 +131,19 @@ thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_projec
131
131
  thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_response.py,sha256=r2R2efDZmaAyfiNs_kuftpgaP-j6VWpKnA1qkHDQfII,466
132
132
  thestage/services/clients/thestage_api/dtos/task_controller/task_status_localized_map_response.py,sha256=Q0YahAKtlWIV0l2XXEwzjjyORchPlBolA2xXZ8c3zpw,285
133
133
  thestage/services/clients/thestage_api/dtos/task_controller/task_view_response.py,sha256=30P19Fipas4wzHguvzmxsAoDkKcGNbcKQ_SjJOQVsq8,462
134
- thestage/services/clients/thestage_api/dtos/user_profile.py,sha256=kWnGeYKe4umMzWBqzk0y0aWx8czZ-zs2WRvVRSopcFA,286
134
+ thestage/services/clients/thestage_api/dtos/user_controller/user_profile.py,sha256=cDH5azyVBXi3V7kIOEuzsF1aKONQnxcI7YsDwXjRmuE,268
135
135
  thestage/services/config_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
- thestage/services/config_provider/config_provider.py,sha256=7vVCwQO-LsY4erkOcl6PG5A-ZrZx7HulFCz7Ncv9OCo,9729
137
- thestage/services/connect/connect_service.py,sha256=6XK2ttKSAly3Vh0SOwM2FVY0OHyjp61XUpTKagX51NI,9508
136
+ thestage/services/config_provider/config_provider.py,sha256=_BNP_pAw40deKyMzDuTR6ze3on-NCxR_yKwl8ZcoUEU,9115
137
+ thestage/services/connect/connect_service.py,sha256=bVUqHh3-AdEhNmh0iRmgBIuR3z7k7rAkE5ldH9dHA5U,9916
138
138
  thestage/services/connect/dto/remote_server_config.py,sha256=yuO0tTAgUxCiQ-h1nVvWUMlCUtR-WB_eOH6KYspV7zQ,272
139
139
  thestage/services/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
140
- thestage/services/container/container_service.py,sha256=1ZVoGpdxQqU0dRuL-Zxh3Y6h8CPcymVEK8CqfyCuCw0,14767
140
+ thestage/services/container/container_service.py,sha256=wqgteC2fVue0rCKnZIRPyhGH3Is1L2E2nMt8i0wYlyA,14759
141
141
  thestage/services/container/mapper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
142
  thestage/services/container/mapper/container_mapper.py,sha256=ymIjBLGZnpodh0W2KwNUqRxT0VgM1hsCViNza1nhWHk,1088
143
- thestage/services/core_files/config_entity.py,sha256=RlTNEWEgKs7WvI7291tAXhKHb2XROgoilIR4eImqM60,1150
144
- thestage/services/filesystem_service.py,sha256=UN5b5jtxeSAGM1yIDIyj3_Gfjixt_KsfqKSWG-gD49w,4270
143
+ thestage/services/core_files/config_entity.py,sha256=qMMjqQrTQmlts93r_NunR5na5uScc526NV9_a3SgPVQ,867
144
+ thestage/services/filesystem_service.py,sha256=U_-U7UcTMFwJeYu-iD8OVYQgcKjTnnrENKVqfDqQwY4,4832
145
145
  thestage/services/instance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
146
- thestage/services/instance/instance_service.py,sha256=AuhU__G1iBvxiHTp7OadgiRCpuOHbzcVW6ZlcsIw4ME,9270
146
+ thestage/services/instance/instance_service.py,sha256=cAuyDozqVNy9FkyQqMu037LghqaUeFfmR9kGbUxLhY4,13371
147
147
  thestage/services/instance/mapper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
148
148
  thestage/services/instance/mapper/instance_mapper.py,sha256=OA0-Z6ODfAK1yBjf7nF-JDKERr8lZUm5vYKk_TFw-v8,1132
149
149
  thestage/services/instance/mapper/selfhosted_mapper.py,sha256=KpkvsDV0OWzHhN53md4mgo3xc8siM5idDwL_pSRTouE,1286
@@ -161,13 +161,13 @@ thestage/services/project/mapper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRk
161
161
  thestage/services/project/mapper/project_inference_simulator_mapper.py,sha256=UdOu9IIF5rlNPoWSaaeSKU3ODe8E5uSMgm2V5ywMWKE,812
162
162
  thestage/services/project/mapper/project_inference_simulator_model_mapper.py,sha256=PWY0iWbXhvD-G0X0_aQZAFY2bqc0lvRJcQAyC8Y-88Q,869
163
163
  thestage/services/project/mapper/project_task_mapper.py,sha256=SHIEXjYwt4vm2B1X2QiI4sCPbBarum0bTOnmTWPOlto,813
164
- thestage/services/project/project_service.py,sha256=q8j3JE2RhzBa1NiJ6PSfgClOSbpJhzGUN4Alv2Y_7FE,53246
165
- thestage/services/remote_server_service.py,sha256=3VPgd9ckxXOxXGGvb3JeJ0LwuZx2gd2jWn3Pf-CxqVk,23264
166
- thestage/services/service_factory.py,sha256=tWbFFDO6TeOz5jSYbe-OabqTmsjR9Xs1OZmd49Aj3g0,5098
164
+ thestage/services/project/project_service.py,sha256=dvWKLV0M5LieO4v0Kye4wQbs-kQmGhifomCsmpxhEBM,59743
165
+ thestage/services/remote_server_service.py,sha256=AsTzlI7mvlJpqFqrhn4o9l3CYliLgeq3GQdyaZ17m9c,23256
166
+ thestage/services/service_factory.py,sha256=Hx9DeFP3x3FDj2g9FCuUnAQSUEfZbJGli_WD805wg40,5082
167
167
  thestage/services/task/dto/task_dto.py,sha256=PJwrUsLLAoO2uA9xvzb27b9iYAoNiBcsHSxKERh2VFo,2335
168
- thestage/services/validation_service.py,sha256=ABb-ok-SGITE6jm8AR1hiYHYgGZL7ri02Yi0OCXbofo,2008
169
- thestage-0.5.44.dist-info/LICENSE.txt,sha256=U9QrxfdD7Ie7r8z1FleuvOGQvgCF1m0Mjd78cFvWaHE,572
170
- thestage-0.5.44.dist-info/METADATA,sha256=ZFWB66Hr0zToO8AHTYEn-EibANQG09L_dBpBh0o-yaw,5557
171
- thestage-0.5.44.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
172
- thestage-0.5.44.dist-info/entry_points.txt,sha256=57pMhs8zaCM-jgeTffC0WVqCsh35Uq_dUDmzXR80CI4,47
173
- thestage-0.5.44.dist-info/RECORD,,
168
+ thestage/services/validation_service.py,sha256=RFVZA_Ri2bzOBKGz6qs5WHK8Z7wVNUMjuj8uRz38YbU,1798
169
+ thestage-0.5.45.dist-info/LICENSE.txt,sha256=U9QrxfdD7Ie7r8z1FleuvOGQvgCF1m0Mjd78cFvWaHE,572
170
+ thestage-0.5.45.dist-info/METADATA,sha256=nrVxlmjYX1TjrTIIAjbQFWLwLvoH4XaJuUSptgY6yFk,5558
171
+ thestage-0.5.45.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
172
+ thestage-0.5.45.dist-info/entry_points.txt,sha256=57pMhs8zaCM-jgeTffC0WVqCsh35Uq_dUDmzXR80CI4,47
173
+ thestage-0.5.45.dist-info/RECORD,,