thestage 0.5.46__py3-none-any.whl → 0.5.471__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/.env +5 -0
- thestage/__init__.py +2 -1
- thestage/cli_command.py +56 -0
- thestage/cli_command_helper.py +51 -0
- thestage/config/config_storage.py +5 -0
- thestage/controllers/base_controller.py +19 -15
- thestage/controllers/config_controller.py +30 -38
- thestage/controllers/container_controller.py +43 -79
- thestage/controllers/instance_controller.py +23 -40
- thestage/controllers/project_controller.py +95 -184
- thestage/controllers/utils_controller.py +12 -8
- thestage/debug_tests.py +12 -0
- thestage/entities/container.py +0 -5
- thestage/entities/rented_instance.py +0 -5
- thestage/entities/self_hosted_instance.py +0 -2
- thestage/helpers/error_handler.py +14 -14
- thestage/helpers/exception_hook.py +14 -0
- thestage/helpers/logger/app_logger.py +3 -4
- thestage/main.py +25 -13
- thestage/services/abstract_service.py +0 -40
- thestage/services/app_config_service.py +7 -6
- thestage/services/clients/.DS_Store +0 -0
- thestage/services/clients/thestage_api/api_client.py +54 -68
- thestage/services/clients/thestage_api/core/api_client_core.py +92 -9
- thestage/services/clients/thestage_api/dtos/container_response.py +1 -1
- thestage/services/clients/thestage_api/dtos/inference_simulator_model_response.py +1 -1
- thestage/services/clients/thestage_api/dtos/inference_simulator_response.py +1 -1
- thestage/services/clients/thestage_api/dtos/instance_rented_response.py +1 -1
- thestage/services/clients/thestage_api/dtos/selfhosted_instance_response.py +1 -1
- thestage/services/clients/thestage_api/dtos/task_controller/task_status_localized_map_response.py +1 -1
- thestage/services/clients/thestage_api/dtos/validate_token_response.py +11 -0
- thestage/services/config_provider/config_provider.py +75 -47
- thestage/services/connect/connect_service.py +11 -22
- thestage/services/container/container_service.py +6 -23
- thestage/services/core_files/config_entity.py +7 -1
- thestage/services/filesystem_service.py +2 -2
- thestage/services/instance/instance_service.py +12 -26
- thestage/services/logging/logging_service.py +17 -45
- thestage/services/project/project_service.py +33 -72
- thestage/services/remote_server_service.py +3 -4
- thestage/services/service_factory.py +21 -27
- thestage/services/validation_service.py +14 -9
- {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/METADATA +3 -4
- {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/RECORD +47 -41
- {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/WHEEL +1 -1
- thestage/exceptions/http_error_exception.py +0 -12
- thestage/services/clients/thestage_api/core/api_client_abstract.py +0 -91
- {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/LICENSE.txt +0 -0
- {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/entry_points.txt +0 -0
|
@@ -18,7 +18,6 @@ from thestage.entities.project_task import ProjectTaskEntity
|
|
|
18
18
|
from thestage.services.clients.thestage_api.core.http_client_exception import HttpClientException
|
|
19
19
|
from thestage.services.clients.thestage_api.dtos.enums.inference_model_status import InferenceModelStatus
|
|
20
20
|
from thestage.services.clients.thestage_api.dtos.enums.inference_simulator_status import InferenceSimulatorStatus
|
|
21
|
-
from thestage.services.core_files.config_entity import ConfigEntity
|
|
22
21
|
from thestage.color_scheme.color_scheme import ColorScheme
|
|
23
22
|
from thestage.entities.enums.yes_no_response import YesOrNoResponse
|
|
24
23
|
from thestage.exceptions.git_access_exception import GitAccessException
|
|
@@ -60,6 +59,7 @@ from rich import print
|
|
|
60
59
|
|
|
61
60
|
class ProjectService(AbstractService):
|
|
62
61
|
__thestage_api_client: TheStageApiClient = None
|
|
62
|
+
__config_provider: ConfigProvider = None
|
|
63
63
|
|
|
64
64
|
def __init__(
|
|
65
65
|
self,
|
|
@@ -69,9 +69,6 @@ class ProjectService(AbstractService):
|
|
|
69
69
|
file_system_service: FileSystemService,
|
|
70
70
|
git_local_client: GitLocalClient,
|
|
71
71
|
):
|
|
72
|
-
super(ProjectService, self).__init__(
|
|
73
|
-
config_provider=config_provider
|
|
74
|
-
)
|
|
75
72
|
self.__thestage_api_client = thestage_api_client
|
|
76
73
|
self.__remote_server_service = remote_server_service
|
|
77
74
|
self.__file_system_service = file_system_service
|
|
@@ -83,12 +80,11 @@ class ProjectService(AbstractService):
|
|
|
83
80
|
@error_handler()
|
|
84
81
|
def init_project(
|
|
85
82
|
self,
|
|
86
|
-
config: ConfigEntity,
|
|
87
83
|
project_slug: str,
|
|
88
84
|
):
|
|
85
|
+
config = self.__config_provider.get_config()
|
|
89
86
|
project: Optional[ProjectDto] = self.__thestage_api_client.get_project_by_slug(
|
|
90
87
|
slug=project_slug,
|
|
91
|
-
token=config.main.thestage_auth_token,
|
|
92
88
|
)
|
|
93
89
|
|
|
94
90
|
if not project:
|
|
@@ -124,7 +120,6 @@ class ProjectService(AbstractService):
|
|
|
124
120
|
|
|
125
121
|
deploy_ssh_key = self.__thestage_api_client.get_project_deploy_ssh_key(
|
|
126
122
|
slug=project.slug,
|
|
127
|
-
token=config.main.thestage_auth_token
|
|
128
123
|
)
|
|
129
124
|
|
|
130
125
|
deploy_key_path = self.__config_provider.save_project_deploy_ssh_key(
|
|
@@ -167,16 +162,17 @@ class ProjectService(AbstractService):
|
|
|
167
162
|
project_config.deploy_key_path = str(deploy_key_path)
|
|
168
163
|
self.__config_provider.save_project_config(project_config=project_config)
|
|
169
164
|
|
|
165
|
+
typer.echo(__("Project successfully initialized at %path%", {"path": config.runtime.working_directory}))
|
|
166
|
+
|
|
170
167
|
|
|
171
168
|
@error_handler()
|
|
172
169
|
def clone_project(
|
|
173
170
|
self,
|
|
174
|
-
config: ConfigEntity,
|
|
175
171
|
project_slug: str,
|
|
176
172
|
):
|
|
173
|
+
config = self.__config_provider.get_config()
|
|
177
174
|
project: Optional[ProjectDto] = self.__thestage_api_client.get_project_by_slug(
|
|
178
175
|
slug=project_slug,
|
|
179
|
-
token=config.main.thestage_auth_token,
|
|
180
176
|
)
|
|
181
177
|
|
|
182
178
|
if not project:
|
|
@@ -199,7 +195,7 @@ class ProjectService(AbstractService):
|
|
|
199
195
|
typer.echo(__("Unexpected Project error, missing Repository"))
|
|
200
196
|
raise typer.Exit(1)
|
|
201
197
|
|
|
202
|
-
deploy_ssh_key = self.__thestage_api_client.get_project_deploy_ssh_key(slug=project.slug
|
|
198
|
+
deploy_ssh_key = self.__thestage_api_client.get_project_deploy_ssh_key(slug=project.slug)
|
|
203
199
|
deploy_key_path = self.__config_provider.save_project_deploy_ssh_key(deploy_ssh_key=deploy_ssh_key, project_slug=project.slug, project_id=project.id)
|
|
204
200
|
|
|
205
201
|
try:
|
|
@@ -226,18 +222,19 @@ class ProjectService(AbstractService):
|
|
|
226
222
|
project_config.git_repository_url = project.git_repository_url
|
|
227
223
|
project_config.deploy_key_path = str(deploy_key_path)
|
|
228
224
|
self.__config_provider.save_project_config(project_config=project_config)
|
|
225
|
+
typer.echo(__("Project successfully cloned to %path%", {"path": config.runtime.working_directory}))
|
|
229
226
|
|
|
230
227
|
|
|
231
228
|
@error_handler()
|
|
232
229
|
def project_run_task(
|
|
233
230
|
self,
|
|
234
|
-
config: ConfigEntity,
|
|
235
231
|
run_command: str,
|
|
236
232
|
task_title: Optional[str] = None,
|
|
237
233
|
commit_hash: Optional[str] = None,
|
|
238
234
|
docker_container_slug: Optional[str] = None,
|
|
239
235
|
) -> Optional[TaskDto]:
|
|
240
|
-
|
|
236
|
+
config = self.__config_provider.get_config()
|
|
237
|
+
project_config: ProjectConfig = self.__get_fixed_project_config()
|
|
241
238
|
if not project_config:
|
|
242
239
|
typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first.", {"path": config.runtime.working_directory}))
|
|
243
240
|
raise typer.Exit(1)
|
|
@@ -252,7 +249,6 @@ class ProjectService(AbstractService):
|
|
|
252
249
|
typer.echo(f"Using default docker container for this project: '{container_slug_for_task}'")
|
|
253
250
|
|
|
254
251
|
container: DockerContainerDto = self.__thestage_api_client.get_container(
|
|
255
|
-
token=config.main.thestage_auth_token,
|
|
256
252
|
container_slug=container_slug_for_task,
|
|
257
253
|
)
|
|
258
254
|
|
|
@@ -384,7 +380,6 @@ class ProjectService(AbstractService):
|
|
|
384
380
|
typer.echo(f'Commit message is empty. Task title is set to "{task_title}"')
|
|
385
381
|
|
|
386
382
|
run_task_response: ProjectRunTaskResponse = self.__thestage_api_client.execute_project_task(
|
|
387
|
-
token=config.main.thestage_auth_token,
|
|
388
383
|
project_slug=project_config.slug,
|
|
389
384
|
docker_container_slug=container_slug_for_task,
|
|
390
385
|
run_command=run_command,
|
|
@@ -405,9 +400,8 @@ class ProjectService(AbstractService):
|
|
|
405
400
|
raise typer.Exit(1)
|
|
406
401
|
|
|
407
402
|
@error_handler()
|
|
408
|
-
def cancel_task(self, task_id: int
|
|
403
|
+
def cancel_task(self, task_id: int):
|
|
409
404
|
cancel_result = self.__thestage_api_client.cancel_task(
|
|
410
|
-
token=config.main.thestage_auth_token,
|
|
411
405
|
task_id=task_id,
|
|
412
406
|
)
|
|
413
407
|
|
|
@@ -420,7 +414,6 @@ class ProjectService(AbstractService):
|
|
|
420
414
|
@error_handler()
|
|
421
415
|
def project_run_inference_simulator(
|
|
422
416
|
self,
|
|
423
|
-
config: ConfigEntity,
|
|
424
417
|
slug: Optional[str] = None,
|
|
425
418
|
commit_hash: Optional[str] = None,
|
|
426
419
|
rented_instance_unique_id: Optional[str] = None,
|
|
@@ -428,7 +421,8 @@ class ProjectService(AbstractService):
|
|
|
428
421
|
inference_dir: Optional[str] = None,
|
|
429
422
|
is_skip_installation: Optional[bool] = False,
|
|
430
423
|
) -> Optional[InferenceSimulatorDto]:
|
|
431
|
-
|
|
424
|
+
config = self.__config_provider.get_config()
|
|
425
|
+
project_config: ProjectConfig = self.__get_fixed_project_config()
|
|
432
426
|
if not project_config:
|
|
433
427
|
typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first. Or provide path to project using --working-directory option.",
|
|
434
428
|
{"path": config.runtime.working_directory}))
|
|
@@ -442,12 +436,6 @@ class ProjectService(AbstractService):
|
|
|
442
436
|
typer.echo(__("Error: Either a rented instance ID or a self-hosted instance unique ID must be provided."))
|
|
443
437
|
raise typer.Exit(1)
|
|
444
438
|
|
|
445
|
-
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
446
|
-
if not project_config:
|
|
447
|
-
typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first.",
|
|
448
|
-
{"path": config.runtime.working_directory}))
|
|
449
|
-
raise typer.Exit(1)
|
|
450
|
-
|
|
451
439
|
if not commit_hash:
|
|
452
440
|
is_git_folder = self.__git_local_client.is_present_local_git(path=config.runtime.working_directory)
|
|
453
441
|
if not is_git_folder:
|
|
@@ -555,7 +543,6 @@ class ProjectService(AbstractService):
|
|
|
555
543
|
slug = uid
|
|
556
544
|
|
|
557
545
|
start_inference_simulator_response: ProjectStartInferenceSimulatorResponse = self.__thestage_api_client.start_project_inference_simulator(
|
|
558
|
-
token=config.main.thestage_auth_token,
|
|
559
546
|
project_slug=project_config.slug,
|
|
560
547
|
commit_hash=commit_hash,
|
|
561
548
|
slug=slug,
|
|
@@ -584,12 +571,10 @@ class ProjectService(AbstractService):
|
|
|
584
571
|
@error_handler()
|
|
585
572
|
def project_push_inference_simulator(
|
|
586
573
|
self,
|
|
587
|
-
config: ConfigEntity,
|
|
588
574
|
slug: Optional[str] = None,
|
|
589
575
|
):
|
|
590
576
|
|
|
591
577
|
push_inference_simulator_model_response: ProjectPushInferenceSimulatorModelResponse = self.__thestage_api_client.push_project_inference_simulator_model(
|
|
592
|
-
token=config.main.thestage_auth_token,
|
|
593
578
|
slug=slug,
|
|
594
579
|
)
|
|
595
580
|
if push_inference_simulator_model_response:
|
|
@@ -610,12 +595,10 @@ class ProjectService(AbstractService):
|
|
|
610
595
|
@error_handler()
|
|
611
596
|
def project_get_and_save_inference_simulator_metadata(
|
|
612
597
|
self,
|
|
613
|
-
config: ConfigEntity,
|
|
614
598
|
slug: Optional[str] = None,
|
|
615
599
|
file_path: Optional[str] = None,
|
|
616
600
|
):
|
|
617
601
|
get_inference_metadata_response: GetInferenceSimulatorResponse = self.__thestage_api_client.get_inference_simulator(
|
|
618
|
-
token=config.main.thestage_auth_token,
|
|
619
602
|
slug=slug,
|
|
620
603
|
)
|
|
621
604
|
|
|
@@ -649,14 +632,12 @@ class ProjectService(AbstractService):
|
|
|
649
632
|
@error_handler()
|
|
650
633
|
def get_project_inference_simulator_list(
|
|
651
634
|
self,
|
|
652
|
-
config: ConfigEntity,
|
|
653
635
|
project_slug: str,
|
|
654
636
|
statuses: List[str],
|
|
655
637
|
row: int = 5,
|
|
656
638
|
page: int = 1,
|
|
657
639
|
) -> PaginatedEntityList[InferenceSimulatorDto]:
|
|
658
640
|
data: Optional[PaginatedEntityList[InferenceSimulatorDto]] = self.__thestage_api_client.get_inference_simulator_list_for_project(
|
|
659
|
-
token=config.main.thestage_auth_token,
|
|
660
641
|
statuses=statuses,
|
|
661
642
|
project_slug=project_slug,
|
|
662
643
|
page=page,
|
|
@@ -669,7 +650,6 @@ class ProjectService(AbstractService):
|
|
|
669
650
|
@error_handler()
|
|
670
651
|
def get_project_inference_simulator_model_list(
|
|
671
652
|
self,
|
|
672
|
-
config: ConfigEntity,
|
|
673
653
|
project_slug: str,
|
|
674
654
|
statuses: List[str],
|
|
675
655
|
row: int = 5,
|
|
@@ -677,7 +657,6 @@ class ProjectService(AbstractService):
|
|
|
677
657
|
) -> PaginatedEntityList[InferenceSimulatorModelDto]:
|
|
678
658
|
data: Optional[
|
|
679
659
|
PaginatedEntityList[InferenceSimulatorModelDto]] = self.__thestage_api_client.get_inference_simulator_model_list_for_project(
|
|
680
|
-
token=config.main.thestage_auth_token,
|
|
681
660
|
statuses=statuses,
|
|
682
661
|
project_slug=project_slug,
|
|
683
662
|
page=page,
|
|
@@ -690,13 +669,11 @@ class ProjectService(AbstractService):
|
|
|
690
669
|
@error_handler()
|
|
691
670
|
def get_project_task_list(
|
|
692
671
|
self,
|
|
693
|
-
config: ConfigEntity,
|
|
694
672
|
project_slug: str,
|
|
695
673
|
row: int = 5,
|
|
696
674
|
page: int = 1,
|
|
697
675
|
) -> PaginatedEntityList[TaskDto]:
|
|
698
676
|
data: Optional[PaginatedEntityList[TaskDto]] = self.__thestage_api_client.get_task_list_for_project(
|
|
699
|
-
token=config.main.thestage_auth_token,
|
|
700
677
|
project_slug=project_slug,
|
|
701
678
|
page=page,
|
|
702
679
|
limit=row,
|
|
@@ -708,11 +685,11 @@ class ProjectService(AbstractService):
|
|
|
708
685
|
@error_handler()
|
|
709
686
|
def checkout_project(
|
|
710
687
|
self,
|
|
711
|
-
config: ConfigEntity,
|
|
712
688
|
task_id: Optional[int],
|
|
713
689
|
branch_name: Optional[str],
|
|
714
690
|
):
|
|
715
|
-
|
|
691
|
+
config = self.__config_provider.get_config()
|
|
692
|
+
project_config: ProjectConfig = self.__get_fixed_project_config()
|
|
716
693
|
if not project_config:
|
|
717
694
|
typer.echo(__("This command is only allowed from within an initialized project directory"))
|
|
718
695
|
raise typer.Exit(1)
|
|
@@ -721,10 +698,7 @@ class ProjectService(AbstractService):
|
|
|
721
698
|
if task_id:
|
|
722
699
|
task_view_response: Optional[TaskViewResponse] = None
|
|
723
700
|
try:
|
|
724
|
-
task_view_response = self.__thestage_api_client.get_task(
|
|
725
|
-
token=config.main.thestage_auth_token,
|
|
726
|
-
task_id=task_id,
|
|
727
|
-
)
|
|
701
|
+
task_view_response = self.__thestage_api_client.get_task(task_id=task_id,)
|
|
728
702
|
except HttpClientException as e:
|
|
729
703
|
if e.get_status_code() == 400:
|
|
730
704
|
typer.echo(f"Task {task_id} was not found")
|
|
@@ -847,7 +821,7 @@ class ProjectService(AbstractService):
|
|
|
847
821
|
|
|
848
822
|
|
|
849
823
|
@error_handler()
|
|
850
|
-
def set_default_container(self,
|
|
824
|
+
def set_default_container(self, container_uid: Optional[str]):
|
|
851
825
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
852
826
|
|
|
853
827
|
if project_config is None:
|
|
@@ -856,7 +830,6 @@ class ProjectService(AbstractService):
|
|
|
856
830
|
|
|
857
831
|
if container_uid:
|
|
858
832
|
container: DockerContainerDto = self.__thestage_api_client.get_container(
|
|
859
|
-
token=config.main.thestage_auth_token,
|
|
860
833
|
container_slug=container_uid,
|
|
861
834
|
)
|
|
862
835
|
if container is None:
|
|
@@ -891,7 +864,7 @@ class ProjectService(AbstractService):
|
|
|
891
864
|
|
|
892
865
|
|
|
893
866
|
@error_handler()
|
|
894
|
-
def print_project_config(self
|
|
867
|
+
def print_project_config(self):
|
|
895
868
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
896
869
|
|
|
897
870
|
if project_config is None:
|
|
@@ -923,7 +896,7 @@ class ProjectService(AbstractService):
|
|
|
923
896
|
typer.echo(f"before any regular git command to manage your local Project repository directly")
|
|
924
897
|
|
|
925
898
|
@error_handler()
|
|
926
|
-
def __get_fixed_project_config(self
|
|
899
|
+
def __get_fixed_project_config(self) -> Optional[ProjectConfig]:
|
|
927
900
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
928
901
|
if project_config is None:
|
|
929
902
|
return None
|
|
@@ -931,7 +904,6 @@ class ProjectService(AbstractService):
|
|
|
931
904
|
if not Path(project_config.deploy_key_path).is_file():
|
|
932
905
|
deploy_ssh_key = self.__thestage_api_client.get_project_deploy_ssh_key(
|
|
933
906
|
slug=project_config.slug,
|
|
934
|
-
token=config.main.thestage_auth_token
|
|
935
907
|
)
|
|
936
908
|
|
|
937
909
|
deploy_key_path = self.__config_provider.save_project_deploy_ssh_key(
|
|
@@ -949,13 +921,13 @@ class ProjectService(AbstractService):
|
|
|
949
921
|
@error_handler()
|
|
950
922
|
def project_deploy_inference_simulator_model_to_instance(
|
|
951
923
|
self,
|
|
952
|
-
config: ConfigEntity,
|
|
953
924
|
unique_id: Optional[str] = None,
|
|
954
925
|
unique_id_with_timestamp: Optional[str] = None,
|
|
955
926
|
rented_instance_unique_id: Optional[str] = None,
|
|
956
927
|
self_hosted_instance_unique_id: Optional[str] = None,
|
|
957
928
|
) -> None:
|
|
958
|
-
|
|
929
|
+
config = self.__config_provider.get_config()
|
|
930
|
+
project_config: ProjectConfig = self.__get_fixed_project_config()
|
|
959
931
|
if not project_config:
|
|
960
932
|
typer.echo(
|
|
961
933
|
__("No project found at the path: %path%. Please initialize or clone a project first. Or provide path to project using --working-directory option.",
|
|
@@ -970,15 +942,8 @@ class ProjectService(AbstractService):
|
|
|
970
942
|
typer.echo(__("Error: Either a rented instance ID or a self-hosted instance unique ID must be provided."))
|
|
971
943
|
raise typer.Exit(1)
|
|
972
944
|
|
|
973
|
-
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
974
|
-
if not project_config:
|
|
975
|
-
typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first.",
|
|
976
|
-
{"path": config.runtime.working_directory}))
|
|
977
|
-
raise typer.Exit(1)
|
|
978
|
-
|
|
979
945
|
typer.echo(__("Creating inference simulator with unique ID: %unique_id_with_timestamp%", {"unique_id_with_timestamp": unique_id_with_timestamp}))
|
|
980
946
|
deploy_model_to_instance_response: DeployInferenceModelToInstanceResponse = self.__thestage_api_client.deploy_inference_model_to_instance(
|
|
981
|
-
token=config.main.thestage_auth_token,
|
|
982
947
|
unique_id=unique_id,
|
|
983
948
|
unique_id_with_timestamp=unique_id_with_timestamp,
|
|
984
949
|
rented_instance_unique_id=rented_instance_unique_id,
|
|
@@ -1003,14 +968,14 @@ class ProjectService(AbstractService):
|
|
|
1003
968
|
@error_handler()
|
|
1004
969
|
def project_deploy_inference_simulator_model_to_sagemaker(
|
|
1005
970
|
self,
|
|
1006
|
-
config: ConfigEntity,
|
|
1007
971
|
unique_id: Optional[str] = None,
|
|
1008
972
|
arn: Optional[str] = None,
|
|
1009
973
|
instance_type: Optional[str] = None,
|
|
1010
974
|
initial_variant_weight: Optional[float] = 1.0,
|
|
1011
975
|
initial_instance_count: Optional[int] = None,
|
|
1012
976
|
) -> None:
|
|
1013
|
-
|
|
977
|
+
config = self.__config_provider.get_config()
|
|
978
|
+
project_config: ProjectConfig = self.__get_fixed_project_config()
|
|
1014
979
|
if not project_config:
|
|
1015
980
|
typer.echo(
|
|
1016
981
|
__("No project found at the path: %path%. Please initialize or clone a project first. Or provide path to project using --working-directory option.",
|
|
@@ -1036,7 +1001,6 @@ class ProjectService(AbstractService):
|
|
|
1036
1001
|
raise typer.Exit(1)
|
|
1037
1002
|
|
|
1038
1003
|
deploy_model_to_sagemaker_response: DeployInferenceModelToSagemakerResponse = self.__thestage_api_client.deploy_inference_model_to_sagemaker(
|
|
1039
|
-
token=config.main.thestage_auth_token,
|
|
1040
1004
|
unique_id=unique_id,
|
|
1041
1005
|
arn=arn,
|
|
1042
1006
|
)
|
|
@@ -1116,8 +1080,9 @@ class ProjectService(AbstractService):
|
|
|
1116
1080
|
|
|
1117
1081
|
|
|
1118
1082
|
@error_handler()
|
|
1119
|
-
def pull_project(self
|
|
1120
|
-
|
|
1083
|
+
def pull_project(self):
|
|
1084
|
+
config = self.__config_provider.get_config()
|
|
1085
|
+
project_config: ProjectConfig = self.__get_fixed_project_config()
|
|
1121
1086
|
if not project_config:
|
|
1122
1087
|
typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first.", {"path": config.runtime.working_directory}))
|
|
1123
1088
|
raise typer.Exit(1)
|
|
@@ -1130,8 +1095,9 @@ class ProjectService(AbstractService):
|
|
|
1130
1095
|
|
|
1131
1096
|
|
|
1132
1097
|
@error_handler()
|
|
1133
|
-
def reset_project(self
|
|
1134
|
-
|
|
1098
|
+
def reset_project(self):
|
|
1099
|
+
config = self.__config_provider.get_config()
|
|
1100
|
+
project_config: ProjectConfig = self.__get_fixed_project_config()
|
|
1135
1101
|
if not project_config:
|
|
1136
1102
|
typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first.", {"path": config.runtime.working_directory}))
|
|
1137
1103
|
raise typer.Exit(1)
|
|
@@ -1150,7 +1116,7 @@ class ProjectService(AbstractService):
|
|
|
1150
1116
|
|
|
1151
1117
|
|
|
1152
1118
|
@error_handler()
|
|
1153
|
-
def print_inference_simulator_list(self,
|
|
1119
|
+
def print_inference_simulator_list(self, project_uid, statuses, row, page):
|
|
1154
1120
|
if not project_uid:
|
|
1155
1121
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
1156
1122
|
if not project_config:
|
|
@@ -1158,8 +1124,7 @@ class ProjectService(AbstractService):
|
|
|
1158
1124
|
raise typer.Exit(1)
|
|
1159
1125
|
project_uid = project_config.slug
|
|
1160
1126
|
|
|
1161
|
-
inference_simulator_status_map = self.__thestage_api_client.get_inference_simulator_business_status_map(
|
|
1162
|
-
config.main.thestage_auth_token)
|
|
1127
|
+
inference_simulator_status_map = self.__thestage_api_client.get_inference_simulator_business_status_map()
|
|
1163
1128
|
|
|
1164
1129
|
if not statuses:
|
|
1165
1130
|
statuses = ({key: inference_simulator_status_map[key] for key in [
|
|
@@ -1194,7 +1159,6 @@ class ProjectService(AbstractService):
|
|
|
1194
1159
|
'statuses': backend_statuses,
|
|
1195
1160
|
},
|
|
1196
1161
|
mapper=ProjectInferenceSimulatorMapper(),
|
|
1197
|
-
config=config,
|
|
1198
1162
|
headers=list(map(lambda x: x.alias, ProjectInferenceSimulatorEntity.model_fields.values())),
|
|
1199
1163
|
row=row,
|
|
1200
1164
|
page=page,
|
|
@@ -1204,7 +1168,7 @@ class ProjectService(AbstractService):
|
|
|
1204
1168
|
|
|
1205
1169
|
|
|
1206
1170
|
@error_handler()
|
|
1207
|
-
def print_inference_simulator_model_list(self,
|
|
1171
|
+
def print_inference_simulator_model_list(self, project_uid, statuses, row, page):
|
|
1208
1172
|
if not project_uid:
|
|
1209
1173
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
1210
1174
|
if not project_config:
|
|
@@ -1212,8 +1176,7 @@ class ProjectService(AbstractService):
|
|
|
1212
1176
|
raise typer.Exit(1)
|
|
1213
1177
|
project_uid = project_config.slug
|
|
1214
1178
|
|
|
1215
|
-
inference_simulator_model_status_map = self.__thestage_api_client.get_inference_simulator_model_business_status_map(
|
|
1216
|
-
config.main.thestage_auth_token)
|
|
1179
|
+
inference_simulator_model_status_map = self.__thestage_api_client.get_inference_simulator_model_business_status_map()
|
|
1217
1180
|
|
|
1218
1181
|
if not statuses:
|
|
1219
1182
|
statuses = ({key: inference_simulator_model_status_map[key] for key in [
|
|
@@ -1248,7 +1211,6 @@ class ProjectService(AbstractService):
|
|
|
1248
1211
|
'statuses': backend_statuses,
|
|
1249
1212
|
},
|
|
1250
1213
|
mapper=ProjectInferenceSimulatorModelMapper(),
|
|
1251
|
-
config=config,
|
|
1252
1214
|
headers=list(map(lambda x: x.alias, ProjectInferenceSimulatorModelEntity.model_fields.values())),
|
|
1253
1215
|
row=row,
|
|
1254
1216
|
page=page,
|
|
@@ -1257,7 +1219,7 @@ class ProjectService(AbstractService):
|
|
|
1257
1219
|
)
|
|
1258
1220
|
|
|
1259
1221
|
|
|
1260
|
-
def print_task_list(self,
|
|
1222
|
+
def print_task_list(self, project_uid, row, page):
|
|
1261
1223
|
if not project_uid:
|
|
1262
1224
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
1263
1225
|
if not project_config:
|
|
@@ -1271,7 +1233,6 @@ class ProjectService(AbstractService):
|
|
|
1271
1233
|
'project_slug': project_uid,
|
|
1272
1234
|
},
|
|
1273
1235
|
mapper=ProjectTaskMapper(),
|
|
1274
|
-
config=config,
|
|
1275
1236
|
headers=list(map(lambda x: x.alias, ProjectTaskEntity.model_fields.values())),
|
|
1276
1237
|
row=row,
|
|
1277
1238
|
page=page,
|
|
@@ -27,6 +27,8 @@ old_value: int = 0
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class RemoteServerService:
|
|
30
|
+
__config_provider: ConfigProvider = None
|
|
31
|
+
__file_system_service: FileSystemService = None
|
|
30
32
|
|
|
31
33
|
def __init__(
|
|
32
34
|
self,
|
|
@@ -490,9 +492,9 @@ class RemoteServerService:
|
|
|
490
492
|
dest_path: str,
|
|
491
493
|
instance_path: str,
|
|
492
494
|
copy_only_folder_contents: bool,
|
|
493
|
-
config: ConfigEntity,
|
|
494
495
|
depth: int = 0,
|
|
495
496
|
) -> List[SftpFileItemEntity]:
|
|
497
|
+
config = self.__config_provider.get_config()
|
|
496
498
|
path_items = []
|
|
497
499
|
try:
|
|
498
500
|
root_stat = sftp.stat(current_path)
|
|
@@ -547,7 +549,6 @@ class RemoteServerService:
|
|
|
547
549
|
instance_path=parent.instance_path,
|
|
548
550
|
depth=depth + 1,
|
|
549
551
|
copy_only_folder_contents=copy_only_folder_contents,
|
|
550
|
-
config=config,
|
|
551
552
|
))
|
|
552
553
|
return path_items
|
|
553
554
|
except FileNotFoundError as ex:
|
|
@@ -568,7 +569,6 @@ class RemoteServerService:
|
|
|
568
569
|
instance_path: str,
|
|
569
570
|
copy_only_folder_contents: bool,
|
|
570
571
|
private_key_path: Optional[str],
|
|
571
|
-
config: ConfigEntity,
|
|
572
572
|
):
|
|
573
573
|
has_error = False
|
|
574
574
|
|
|
@@ -581,7 +581,6 @@ class RemoteServerService:
|
|
|
581
581
|
instance_path=instance_path,
|
|
582
582
|
dest_path=dest_path,
|
|
583
583
|
copy_only_folder_contents=copy_only_folder_contents,
|
|
584
|
-
config=config,
|
|
585
584
|
)
|
|
586
585
|
|
|
587
586
|
if len(files) == 0:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
|
+
from thestage.services.config_provider.config_provider import ConfigProvider
|
|
3
4
|
from thestage.services.connect.connect_service import ConnectService
|
|
4
5
|
from thestage.services.filesystem_service import FileSystemService
|
|
5
6
|
from thestage.services.logging.logging_service import LoggingService
|
|
@@ -10,73 +11,63 @@ from thestage.services.instance.instance_service import InstanceService
|
|
|
10
11
|
from thestage.services.app_config_service import AppConfigService
|
|
11
12
|
from thestage.services.clients.git.git_client import GitLocalClient
|
|
12
13
|
from thestage.services.clients.thestage_api.api_client import TheStageApiClient
|
|
13
|
-
from thestage.services.config_provider.config_provider import ConfigProvider
|
|
14
14
|
from thestage.services.validation_service import ValidationService
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class ServiceFactory:
|
|
18
|
-
__config_provider: Optional[ConfigProvider] = None
|
|
19
18
|
__thestage_api_client: Optional[TheStageApiClient] = None
|
|
20
19
|
__git_local_client: Optional[GitLocalClient] = None
|
|
21
20
|
__file_system_service: Optional[FileSystemService] = None
|
|
21
|
+
__config_provider: Optional[ConfigProvider] = None
|
|
22
22
|
|
|
23
|
-
def __init__(
|
|
24
|
-
self,
|
|
25
|
-
config_provider: Optional[ConfigProvider] = None,
|
|
26
|
-
):
|
|
27
|
-
self.__config_provider = config_provider
|
|
28
|
-
|
|
29
|
-
def get_config_provider(self) -> ConfigProvider:
|
|
30
|
-
return self.__config_provider
|
|
31
23
|
|
|
32
|
-
def get_validation_service(self
|
|
24
|
+
def get_validation_service(self) -> ValidationService:
|
|
33
25
|
return ValidationService(
|
|
34
26
|
thestage_api_client=self.get_thestage_api_client(),
|
|
35
|
-
config_provider=
|
|
27
|
+
config_provider=self.get_config_provider(),
|
|
36
28
|
)
|
|
37
29
|
|
|
38
|
-
def get_instance_service(self
|
|
30
|
+
def get_instance_service(self) -> InstanceService:
|
|
39
31
|
return InstanceService(
|
|
40
32
|
thestage_api_client=self.get_thestage_api_client(),
|
|
41
|
-
config_provider=config_provider if config_provider else self.__config_provider,
|
|
42
33
|
remote_server_service=self.get_remote_server_service(),
|
|
34
|
+
config_provider=self.get_config_provider(),
|
|
43
35
|
)
|
|
44
36
|
|
|
45
|
-
def get_container_service(self
|
|
37
|
+
def get_container_service(self) -> ContainerService:
|
|
46
38
|
return ContainerService(
|
|
47
39
|
thestage_api_client=self.get_thestage_api_client(),
|
|
48
|
-
config_provider=config_provider if config_provider else self.__config_provider,
|
|
49
40
|
remote_server_service=self.get_remote_server_service(),
|
|
50
41
|
file_system_service=self.get_file_system_service(),
|
|
42
|
+
config_provider=self.get_config_provider(),
|
|
51
43
|
)
|
|
52
44
|
|
|
53
|
-
def get_connect_service(self
|
|
45
|
+
def get_connect_service(self) -> ConnectService:
|
|
54
46
|
return ConnectService(
|
|
55
|
-
config_provider=config_provider if config_provider else self.__config_provider,
|
|
56
47
|
thestage_api_client=self.get_thestage_api_client(),
|
|
57
48
|
instance_service=self.get_instance_service(),
|
|
58
49
|
container_service=self.get_container_service(),
|
|
59
50
|
logging_service=self.get_logging_service(),
|
|
60
51
|
)
|
|
61
52
|
|
|
62
|
-
def get_project_service(self
|
|
53
|
+
def get_project_service(self) -> ProjectService:
|
|
63
54
|
return ProjectService(
|
|
64
55
|
thestage_api_client=self.get_thestage_api_client(),
|
|
65
|
-
config_provider=config_provider if config_provider else self.__config_provider,
|
|
66
56
|
remote_server_service=self.get_remote_server_service(),
|
|
67
57
|
file_system_service=self.get_file_system_service(),
|
|
68
58
|
git_local_client=self.get_git_local_client(),
|
|
59
|
+
config_provider=self.get_config_provider(),
|
|
69
60
|
)
|
|
70
61
|
|
|
71
62
|
def get_remote_server_service(self) -> RemoteServerService:
|
|
72
63
|
return RemoteServerService(
|
|
73
|
-
config_provider=self.get_config_provider(),
|
|
74
64
|
file_system_service=self.get_file_system_service(),
|
|
65
|
+
config_provider=self.get_config_provider(),
|
|
75
66
|
)
|
|
76
67
|
|
|
77
68
|
def get_thestage_api_client(self) -> TheStageApiClient:
|
|
78
69
|
if not self.__thestage_api_client:
|
|
79
|
-
self.__thestage_api_client = TheStageApiClient(
|
|
70
|
+
self.__thestage_api_client = TheStageApiClient(config_provider=self.get_config_provider())
|
|
80
71
|
return self.__thestage_api_client
|
|
81
72
|
|
|
82
73
|
def get_git_local_client(self):
|
|
@@ -89,15 +80,18 @@ class ServiceFactory:
|
|
|
89
80
|
self.__file_system_service = FileSystemService()
|
|
90
81
|
return self.__file_system_service
|
|
91
82
|
|
|
92
|
-
def get_app_config_service(self
|
|
83
|
+
def get_app_config_service(self) -> AppConfigService:
|
|
93
84
|
return AppConfigService(
|
|
94
|
-
|
|
95
|
-
|
|
85
|
+
config_provider=self.get_config_provider(),
|
|
86
|
+
validation_service=self.get_validation_service(),
|
|
96
87
|
)
|
|
97
88
|
|
|
98
|
-
def get_logging_service(self
|
|
89
|
+
def get_logging_service(self) -> LoggingService:
|
|
99
90
|
return LoggingService(
|
|
100
91
|
thestage_api_client=self.get_thestage_api_client(),
|
|
101
|
-
config_provider=config_provider if config_provider else self.__config_provider,
|
|
102
92
|
)
|
|
103
93
|
|
|
94
|
+
def get_config_provider(self) -> ConfigProvider:
|
|
95
|
+
if not self.__config_provider:
|
|
96
|
+
self.__config_provider = ConfigProvider(self.get_file_system_service())
|
|
97
|
+
return self.__config_provider
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
|
|
3
3
|
from thestage.i18n.translation import __
|
|
4
|
-
from thestage.
|
|
4
|
+
# from thestage.main import update_allowed_commands
|
|
5
5
|
from thestage.services.clients.thestage_api.api_client import TheStageApiClient
|
|
6
|
+
from thestage.services.config_provider.config_provider import ConfigProvider
|
|
6
7
|
from thestage.services.core_files.config_entity import ConfigEntity
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class ValidationService:
|
|
10
11
|
_thestage_api_client: TheStageApiClient = None
|
|
12
|
+
_config_provider: ConfigProvider = None
|
|
11
13
|
|
|
12
14
|
def __init__(
|
|
13
15
|
self,
|
|
@@ -18,10 +20,8 @@ class ValidationService:
|
|
|
18
20
|
self._config_provider = config_provider
|
|
19
21
|
|
|
20
22
|
|
|
21
|
-
def check_token(
|
|
22
|
-
|
|
23
|
-
config: ConfigEntity,
|
|
24
|
-
):
|
|
23
|
+
def check_token(self):
|
|
24
|
+
config = self._config_provider.get_config()
|
|
25
25
|
token = config.main.thestage_auth_token
|
|
26
26
|
if not token:
|
|
27
27
|
token: str = typer.prompt(
|
|
@@ -32,16 +32,21 @@ class ValidationService:
|
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
# TODO this fails with 503 error - AttributeError("'bytes' object has no attribute 'text'") from _parse_api_response method in core
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
if not token:
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
token_validate_response = self._thestage_api_client.validate_token(token=token)
|
|
39
|
+
is_valid = token_validate_response.is_success if token_validate_response else False
|
|
38
40
|
if not is_valid:
|
|
39
41
|
typer.echo(__(
|
|
40
42
|
'API token is invalid: generate API token using TheStage AI WebApp'
|
|
41
43
|
))
|
|
42
44
|
raise typer.Exit(1)
|
|
43
45
|
|
|
44
|
-
config.main.thestage_auth_token
|
|
46
|
+
if config.main.thestage_auth_token != token:
|
|
47
|
+
config.main.thestage_auth_token = token
|
|
48
|
+
self._config_provider.update_config(updated_config=config)
|
|
49
|
+
self._config_provider.update_allowed_commands_and_is_token_valid(validate_token_response=token_validate_response)
|
|
45
50
|
|
|
46
51
|
|
|
47
52
|
@staticmethod
|