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.
Files changed (49) hide show
  1. thestage/.env +5 -0
  2. thestage/__init__.py +2 -1
  3. thestage/cli_command.py +56 -0
  4. thestage/cli_command_helper.py +51 -0
  5. thestage/config/config_storage.py +5 -0
  6. thestage/controllers/base_controller.py +19 -15
  7. thestage/controllers/config_controller.py +30 -38
  8. thestage/controllers/container_controller.py +43 -79
  9. thestage/controllers/instance_controller.py +23 -40
  10. thestage/controllers/project_controller.py +95 -184
  11. thestage/controllers/utils_controller.py +12 -8
  12. thestage/debug_tests.py +12 -0
  13. thestage/entities/container.py +0 -5
  14. thestage/entities/rented_instance.py +0 -5
  15. thestage/entities/self_hosted_instance.py +0 -2
  16. thestage/helpers/error_handler.py +14 -14
  17. thestage/helpers/exception_hook.py +14 -0
  18. thestage/helpers/logger/app_logger.py +3 -4
  19. thestage/main.py +25 -13
  20. thestage/services/abstract_service.py +0 -40
  21. thestage/services/app_config_service.py +7 -6
  22. thestage/services/clients/.DS_Store +0 -0
  23. thestage/services/clients/thestage_api/api_client.py +54 -68
  24. thestage/services/clients/thestage_api/core/api_client_core.py +92 -9
  25. thestage/services/clients/thestage_api/dtos/container_response.py +1 -1
  26. thestage/services/clients/thestage_api/dtos/inference_simulator_model_response.py +1 -1
  27. thestage/services/clients/thestage_api/dtos/inference_simulator_response.py +1 -1
  28. thestage/services/clients/thestage_api/dtos/instance_rented_response.py +1 -1
  29. thestage/services/clients/thestage_api/dtos/selfhosted_instance_response.py +1 -1
  30. thestage/services/clients/thestage_api/dtos/task_controller/task_status_localized_map_response.py +1 -1
  31. thestage/services/clients/thestage_api/dtos/validate_token_response.py +11 -0
  32. thestage/services/config_provider/config_provider.py +75 -47
  33. thestage/services/connect/connect_service.py +11 -22
  34. thestage/services/container/container_service.py +6 -23
  35. thestage/services/core_files/config_entity.py +7 -1
  36. thestage/services/filesystem_service.py +2 -2
  37. thestage/services/instance/instance_service.py +12 -26
  38. thestage/services/logging/logging_service.py +17 -45
  39. thestage/services/project/project_service.py +33 -72
  40. thestage/services/remote_server_service.py +3 -4
  41. thestage/services/service_factory.py +21 -27
  42. thestage/services/validation_service.py +14 -9
  43. {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/METADATA +3 -4
  44. {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/RECORD +47 -41
  45. {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/WHEEL +1 -1
  46. thestage/exceptions/http_error_exception.py +0 -12
  47. thestage/services/clients/thestage_api/core/api_client_abstract.py +0 -91
  48. {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/LICENSE.txt +0 -0
  49. {thestage-0.5.46.dist-info → thestage-0.5.471.dist-info}/entry_points.txt +0 -0
@@ -7,37 +7,30 @@ import re
7
7
  import typer
8
8
  from typing_extensions import Annotated
9
9
 
10
+ from thestage.cli_command import CliCommand
11
+ from thestage.cli_command_helper import get_command_group_help_panel, get_command_metadata, check_command_permission
10
12
  from thestage.controllers.utils_controller import validate_config_and_get_service_factory, get_current_directory
11
- from thestage.entities.project_inference_simulator import ProjectInferenceSimulatorEntity
12
- from thestage.entities.project_inference_simulator_model import ProjectInferenceSimulatorModelEntity
13
- from thestage.entities.project_task import ProjectTaskEntity
14
13
  from thestage.helpers.logger.app_logger import app_logger
15
14
  from thestage.i18n.translation import __
16
- from thestage.services.clients.thestage_api.dtos.enums.inference_model_status import InferenceModelStatus
17
- from thestage.services.clients.thestage_api.dtos.enums.inference_simulator_status import InferenceSimulatorStatus
18
15
  from thestage.services.clients.thestage_api.dtos.inference_controller.get_inference_simulator_response import \
19
16
  GetInferenceSimulatorResponse
20
17
  from thestage.services.logging.logging_service import LoggingService
21
- from thestage.services.project.dto.project_config import ProjectConfig
22
- from thestage.services.project.mapper.project_inference_simulator_mapper import ProjectInferenceSimulatorMapper
23
- from thestage.services.project.mapper.project_inference_simulator_model_mapper import \
24
- ProjectInferenceSimulatorModelMapper
25
- from thestage.services.project.mapper.project_task_mapper import ProjectTaskMapper
26
18
  from thestage.services.project.project_service import ProjectService
27
19
  from thestage.services.task.dto.task_dto import TaskDto
28
20
 
29
21
  app = typer.Typer(no_args_is_help=True, help=__("Manage projects"))
30
22
  inference_simulators_app = typer.Typer(no_args_is_help=True, help="Manage project inference simulators")
31
- app.add_typer(inference_simulators_app, name="inference-simulator")
32
23
  inference_simulator_model_app = typer.Typer(no_args_is_help=True, help="Manage project inference simulator models")
33
- app.add_typer(inference_simulator_model_app, name="model")
34
24
  task_app = typer.Typer(no_args_is_help=True, help=__("Manage project tasks"))
35
25
  config_app = typer.Typer(no_args_is_help=True, help=__("Manage project config"))
36
- app.add_typer(task_app, name="task")
37
- app.add_typer(config_app, name="config")
38
26
 
27
+ app.add_typer(inference_simulators_app, name="inference-simulator", rich_help_panel=get_command_group_help_panel())
28
+ app.add_typer(inference_simulator_model_app, name="model", rich_help_panel=get_command_group_help_panel())
29
+ app.add_typer(task_app, name="task", rich_help_panel=get_command_group_help_panel())
30
+ app.add_typer(config_app, name="config", rich_help_panel=get_command_group_help_panel())
39
31
 
40
- @app.command(name='clone', no_args_is_help=True, help=__("Clone project repository to empty directory"))
32
+
33
+ @app.command(name='clone', no_args_is_help=True, help=__("Clone project repository to empty directory"), **get_command_metadata(CliCommand.PROJECT_CLONE))
41
34
  def clone(
42
35
  project_uid: str = typer.Argument(
43
36
  help=__("Project unique ID"),
@@ -50,28 +43,24 @@ def clone(
50
43
  is_eager=False,
51
44
  ),
52
45
  ):
53
- """
54
- Clones project to current working directory
55
- """
56
- app_logger.info(f'Start project clone from {get_current_directory()}')
46
+ command_name = CliCommand.PROJECT_CLONE
47
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
48
+ check_command_permission(command_name)
49
+
57
50
  if not working_directory:
58
51
  working_directory = get_current_directory().joinpath(project_uid)
59
52
 
60
53
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
61
- config = service_factory.get_config_provider().get_full_config()
62
-
63
54
  project_service = service_factory.get_project_service()
64
55
 
65
56
  project_service.clone_project(
66
- config=config,
67
57
  project_slug=project_uid,
68
58
  )
69
59
 
70
- typer.echo(__("Project successfully cloned to %path%", {"path": config.runtime.working_directory}))
71
60
  raise typer.Exit(0)
72
61
 
73
62
 
74
- @app.command(name='init', no_args_is_help=True, help=__("Initialize project repository with existing files"))
63
+ @app.command(name='init', no_args_is_help=True, help=__("Initialize project repository with existing files"), **get_command_metadata(CliCommand.PROJECT_INIT))
75
64
  def init(
76
65
  project_uid: Optional[str] = typer.Argument(
77
66
  help=__("Project unique ID"),
@@ -84,14 +73,11 @@ def init(
84
73
  is_eager=False,
85
74
  ),
86
75
  ):
87
- """
88
- Initializes project in current working directory
89
- """
90
- app_logger.info(f'Start project init from {get_current_directory()}')
76
+ command_name = CliCommand.PROJECT_INIT
77
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
78
+ check_command_permission(command_name)
91
79
 
92
80
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
93
- config = service_factory.get_config_provider().get_full_config()
94
-
95
81
  project_service = service_factory.get_project_service()
96
82
  project_config = service_factory.get_config_provider().read_project_config()
97
83
 
@@ -101,14 +87,12 @@ def init(
101
87
 
102
88
  project_service.init_project(
103
89
  project_slug=project_uid,
104
- config=config,
105
90
  )
106
91
 
107
- typer.echo(__("Project successfully initialized at %path%", {"path": config.runtime.working_directory}))
108
92
  raise typer.Exit(0)
109
93
 
110
94
 
111
- @app.command(name='run', no_args_is_help=True, help=__("Run a task within the project. By default, it uses the latest commit from the main branch and streams real-time task logs."))
95
+ @app.command(name='run', no_args_is_help=True, help=__("Run a task within the project. By default, it uses the latest commit from the main branch and streams real-time task logs."), **get_command_metadata(CliCommand.PROJECT_RUN))
112
96
  def run(
113
97
  command: Annotated[List[str], typer.Argument(
114
98
  help=__("Command to run (required)"),
@@ -150,22 +134,18 @@ def run(
150
134
  is_eager=False,
151
135
  ),
152
136
  ):
153
- """
154
- Runs a task within a project
155
- """
156
- app_logger.info(f'Start project run from {get_current_directory()}')
137
+ command_name = CliCommand.PROJECT_RUN
138
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
139
+ check_command_permission(command_name)
157
140
 
158
141
  if not command:
159
142
  typer.echo(__('Command is required'))
160
143
  raise typer.Exit(1)
161
144
 
162
145
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
163
- config = service_factory.get_config_provider().get_full_config()
164
-
165
146
  project_service = service_factory.get_project_service()
166
147
 
167
148
  task: Optional[TaskDto] = project_service.project_run_task(
168
- config=config,
169
149
  run_command=" ".join(command),
170
150
  commit_hash=commit_hash,
171
151
  docker_container_slug=docker_container_slug,
@@ -174,44 +154,36 @@ def run(
174
154
 
175
155
  if enable_log_stream:
176
156
  logging_service: LoggingService = service_factory.get_logging_service()
177
-
178
- logging_service.stream_task_logs_with_controls(
179
- config=config,
180
- task_id=task.id
181
- )
157
+ logging_service.stream_task_logs_with_controls(task_id=task.id)
182
158
 
183
159
  raise typer.Exit(0)
184
160
 
185
161
 
186
- @task_app.command(name='cancel', no_args_is_help=True, help=__("Cancel a task by ID"))
162
+ @task_app.command(name='cancel', no_args_is_help=True, help=__("Cancel a task by ID"), **get_command_metadata(CliCommand.PROJECT_TASK_CANCEL))
187
163
  def cancel_task(
188
164
  task_id: Annotated[int, typer.Argument(
189
165
  help=__("Task ID (required)"),
190
166
  )],
191
167
  ):
192
- """
193
- Cancels a task
194
- """
195
- app_logger.info(f'Start cancel task from {get_current_directory()}')
168
+ command_name = CliCommand.PROJECT_TASK_CANCEL
169
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
170
+ check_command_permission(command_name)
196
171
 
197
172
  if not task_id:
198
173
  typer.echo(__('Task ID is required'))
199
174
  raise typer.Exit(1)
200
175
 
201
176
  service_factory = validate_config_and_get_service_factory()
202
- config = service_factory.get_config_provider().get_full_config()
203
-
204
177
  project_service = service_factory.get_project_service()
205
178
 
206
179
  project_service.cancel_task(
207
- config=config,
208
180
  task_id=task_id
209
181
  )
210
182
 
211
183
  raise typer.Exit(0)
212
184
 
213
185
 
214
- @task_app.command("ls", help=__("List tasks"))
186
+ @task_app.command("ls", help=__("List tasks"), **get_command_metadata(CliCommand.PROJECT_TASK_LS))
215
187
  def list_runs(
216
188
  project_uid: Annotated[str, typer.Argument(help=__("Project unique ID. By default, project info is taken from the current directory"), metavar="OPTIONAL")] = None,
217
189
  row: int = typer.Option(
@@ -229,22 +201,20 @@ def list_runs(
229
201
  is_eager=False,
230
202
  ),
231
203
  ):
232
- """
233
- Lists tasks for a project
234
- """
235
- app_logger.info(f'Start project list-runs from {get_current_directory()}')
204
+ command_name = CliCommand.PROJECT_TASK_LS
205
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
206
+ check_command_permission(command_name)
236
207
 
237
208
  service_factory = validate_config_and_get_service_factory()
238
- config = service_factory.get_config_provider().get_full_config()
239
209
  project_service: ProjectService = service_factory.get_project_service()
240
210
 
241
- project_service.print_task_list(config, project_uid, row, page)
211
+ project_service.print_task_list(project_uid, row, page)
242
212
 
243
213
  typer.echo(__("Tasks listing complete"))
244
214
  raise typer.Exit(0)
245
215
 
246
216
 
247
- @task_app.command(name="logs", no_args_is_help=True, help=__("Stream real-time task logs or view last logs for a task"))
217
+ @task_app.command(name="logs", no_args_is_help=True, help=__("Stream real-time task logs or view last logs for a task"), **get_command_metadata(CliCommand.PROJECT_TASK_LOGS))
248
218
  def task_logs(
249
219
  task_id: Optional[int] = typer.Argument(help=__("Task ID"),),
250
220
  logs_number: Optional[int] = typer.Option(
@@ -255,33 +225,27 @@ def task_logs(
255
225
  is_eager=False,
256
226
  ),
257
227
  ):
258
- """
259
- Streams real-time task logs
260
- """
261
- app_logger.info(f'View task logs')
228
+ command_name = CliCommand.PROJECT_TASK_LOGS
229
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
230
+ check_command_permission(command_name)
262
231
 
263
232
  if not task_id:
264
233
  typer.echo(__('Task ID is required'))
265
234
  raise typer.Exit(1)
266
235
 
267
236
  service_factory = validate_config_and_get_service_factory()
268
- config = service_factory.get_config_provider().get_full_config()
269
-
270
237
  logging_service: LoggingService = service_factory.get_logging_service()
271
238
 
272
239
  if logs_number is None:
273
- logging_service.stream_task_logs_with_controls(
274
- config=config,
275
- task_id=task_id
276
- )
240
+ logging_service.stream_task_logs_with_controls(task_id=task_id)
277
241
  else:
278
- logging_service.print_last_task_logs(config=config, task_id=task_id, logs_number=logs_number)
242
+ logging_service.print_last_task_logs(task_id=task_id, logs_number=logs_number)
279
243
 
280
244
  app_logger.info(f'Task logs - end')
281
245
  raise typer.Exit(0)
282
246
 
283
247
 
284
- @app.command(name='checkout', no_args_is_help=True, help=__("Checkout project repository to a specific reference"))
248
+ @app.command(name='checkout', no_args_is_help=True, help=__("Checkout project repository to a specific reference"), **get_command_metadata(CliCommand.PROJECT_CHECKOUT))
285
249
  def checkout_project(
286
250
  reference: Optional[str] = typer.Argument(
287
251
  help=__("Task ID or branch name to checkout. '/' will try to identify the main branch."),
@@ -294,14 +258,11 @@ def checkout_project(
294
258
  is_eager=False,
295
259
  ),
296
260
  ):
297
- """
298
- Checkout project in current working directory
299
- """
300
- app_logger.info(f'Start project checkout from {get_current_directory()}')
261
+ command_name = CliCommand.PROJECT_CHECKOUT
262
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
263
+ check_command_permission(command_name)
301
264
 
302
265
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
303
- config = service_factory.get_config_provider().get_full_config()
304
-
305
266
  project_service = service_factory.get_project_service()
306
267
 
307
268
  task_id: Optional[int] = None
@@ -315,7 +276,6 @@ def checkout_project(
315
276
  branch_name = reference
316
277
 
317
278
  project_service.checkout_project(
318
- config=config,
319
279
  task_id=task_id,
320
280
  branch_name=branch_name
321
281
  )
@@ -323,7 +283,7 @@ def checkout_project(
323
283
  raise typer.Exit(0)
324
284
 
325
285
 
326
- @app.command(name='pull', help=__("Pulls the changes from the remote project repository. Equivalent to 'git pull'."))
286
+ @app.command(name='pull', help=__("Pulls the changes from the remote project repository. Equivalent to 'git pull'."), **get_command_metadata(CliCommand.PROJECT_PULL))
327
287
  def pull_project(
328
288
  working_directory: Optional[str] = typer.Option(
329
289
  None,
@@ -333,24 +293,19 @@ def pull_project(
333
293
  is_eager=False,
334
294
  ),
335
295
  ):
336
- """
337
- Pull project in current working directory
338
- """
339
- app_logger.info(f'Start project pull from {get_current_directory()}')
296
+ command_name = CliCommand.PROJECT_PULL
297
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
298
+ check_command_permission(command_name)
340
299
 
341
300
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
342
- config = service_factory.get_config_provider().get_full_config()
343
-
344
301
  project_service = service_factory.get_project_service()
345
302
 
346
- project_service.pull_project(
347
- config=config,
348
- )
303
+ project_service.pull_project()
349
304
 
350
305
  raise typer.Exit(0)
351
306
 
352
307
 
353
- @app.command(name='reset', help=__("Resets the current project branch to remote counterpart. All working tree changes will be lost. Equivalent to 'git fetch && git reset --hard origin/{ref}'."))
308
+ @app.command(name='reset', help=__("Resets the current project branch to remote counterpart. All working tree changes will be lost. Equivalent to 'git fetch && git reset --hard origin/{ref}'."), **get_command_metadata(CliCommand.PROJECT_RESET))
354
309
  def reset_project(
355
310
  working_directory: Optional[str] = typer.Option(
356
311
  None,
@@ -360,24 +315,19 @@ def reset_project(
360
315
  is_eager=False,
361
316
  ),
362
317
  ):
363
- """
364
- Pull project in current working directory
365
- """
366
- app_logger.info(f'Start project pull from {get_current_directory()}')
318
+ command_name = CliCommand.PROJECT_RESET
319
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
320
+ check_command_permission(command_name)
367
321
 
368
322
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
369
- config = service_factory.get_config_provider().get_full_config()
370
-
371
323
  project_service = service_factory.get_project_service()
372
324
 
373
- project_service.reset_project(
374
- config=config
375
- )
325
+ project_service.reset_project()
376
326
 
377
327
  raise typer.Exit(0)
378
328
 
379
329
 
380
- @config_app.command(name='set-default-container', no_args_is_help=True, help=__("Set default docker container for a project installation"))
330
+ @config_app.command(name='set-default-container', no_args_is_help=True, help=__("Set default docker container for a project installation"), **get_command_metadata(CliCommand.PROJECT_CONFIG_SET_DEFAULT_CONTAINER))
381
331
  def set_default_container(
382
332
  container_uid: Annotated[Optional[str], typer.Argument(
383
333
  help=__("Unique ID of the container to use by default for running tasks"),
@@ -397,13 +347,11 @@ def set_default_container(
397
347
  is_eager=False,
398
348
  ),
399
349
  ):
400
- """
401
- Initializes project in current working directory
402
- """
403
- app_logger.info(f'Start project init from {get_current_directory()}')
350
+ command_name = CliCommand.PROJECT_CONFIG_SET_DEFAULT_CONTAINER
351
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
352
+ check_command_permission(command_name)
404
353
 
405
354
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
406
- config = service_factory.get_config_provider().get_full_config()
407
355
 
408
356
  if unset_default_container and container_uid:
409
357
  typer.echo("Container unique ID is provided along with unset flag. Please pick one.")
@@ -416,14 +364,13 @@ def set_default_container(
416
364
  project_service = service_factory.get_project_service()
417
365
 
418
366
  project_service.set_default_container(
419
- config=config,
420
367
  container_uid=container_uid,
421
368
  )
422
369
 
423
370
  raise typer.Exit(0)
424
371
 
425
372
 
426
- @config_app.command(name='get', no_args_is_help=False, help=__("View config for a local project installation"))
373
+ @config_app.command(name='get', no_args_is_help=False, help=__("View config for a local project installation"), **get_command_metadata(CliCommand.PROJECT_CONFIG_GET))
427
374
  def get_project_config(
428
375
  working_directory: Optional[str] = typer.Option(
429
376
  None,
@@ -433,24 +380,19 @@ def get_project_config(
433
380
  is_eager=False,
434
381
  ),
435
382
  ):
436
- """
437
- Initializes project in current working directory
438
- """
439
- app_logger.info(f'Start project init from {get_current_directory()}')
383
+ command_name = CliCommand.PROJECT_CONFIG_GET
384
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
385
+ check_command_permission(command_name)
440
386
 
441
387
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
442
- config = service_factory.get_config_provider().get_full_config()
443
-
444
388
  project_service = service_factory.get_project_service()
445
389
 
446
- project_service.print_project_config(
447
- config=config,
448
- )
390
+ project_service.print_project_config()
449
391
 
450
392
  raise typer.Exit(0)
451
393
 
452
394
 
453
- @inference_simulators_app.command(name='run', no_args_is_help=True, help="Run an inference simulator within the project")
395
+ @inference_simulators_app.command(name='run', no_args_is_help=True, help="Run an inference simulator within the project", **get_command_metadata(CliCommand.PROJECT_INFERENCE_SIMULATOR_RUN))
454
396
  def run_inference_simulator(
455
397
  unique_id: Optional[str] = typer.Argument(help=__("Inference simulator unique ID"), ),
456
398
  rented_instance_unique_id: Optional[str] = typer.Option(
@@ -497,17 +439,15 @@ def run_inference_simulator(
497
439
  is_eager=False,
498
440
  ),
499
441
  ):
500
- """
501
- Run an inference simulator within a project
502
- """
442
+ command_name = CliCommand.PROJECT_INFERENCE_SIMULATOR_RUN
443
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
444
+ check_command_permission(command_name)
503
445
 
504
446
  if unique_id and not re.match(r"^[a-zA-Z0-9-]+$", unique_id):
505
447
  raise typer.BadParameter(__("Invalid UID format. The UID can only contain letters, numbers, and hyphens."))
506
448
 
507
- app_logger.info(f'Running an inference simulator from {get_current_directory()}')
508
-
509
449
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
510
- config = service_factory.get_config_provider().get_full_config()
450
+ config = service_factory.get_config_provider().get_config()
511
451
 
512
452
  working_dir_path = Path(working_directory) if working_directory else Path(config.runtime.working_directory)
513
453
  inference_files = list(working_dir_path.rglob("inference.py"))
@@ -541,7 +481,6 @@ def run_inference_simulator(
541
481
  project_service = service_factory.get_project_service()
542
482
 
543
483
  project_service.project_run_inference_simulator(
544
- config=config,
545
484
  commit_hash=commit_hash,
546
485
  slug=unique_id,
547
486
  rented_instance_unique_id=rented_instance_unique_id,
@@ -554,13 +493,12 @@ def run_inference_simulator(
554
493
  logging_service: LoggingService = service_factory.get_logging_service()
555
494
 
556
495
  logging_service.stream_inference_simulator_logs_with_controls(
557
- config=config,
558
496
  slug=unique_id
559
497
  )
560
498
  raise typer.Exit(0)
561
499
 
562
500
 
563
- @inference_simulators_app.command(name='save-metadata', no_args_is_help=True, help="Get and save inference simulator metadata")
501
+ @inference_simulators_app.command(name='save-metadata', no_args_is_help=True, help="Get and save inference simulator metadata", **get_command_metadata(CliCommand.PROJECT_INFERENCE_SIMULATOR_SAVE_METADATA))
564
502
  def get_and_save_inference_simulator_metadata(
565
503
  unique_id: Optional[str] = typer.Argument(help=__("Inference simulator unique ID"),),
566
504
  file_path: Optional[str] = typer.Option(
@@ -572,17 +510,14 @@ def get_and_save_inference_simulator_metadata(
572
510
  is_eager=False,
573
511
  ),
574
512
  ):
575
- """
576
- Get and save inference simulator metadata
577
- """
513
+ command_name = CliCommand.PROJECT_INFERENCE_SIMULATOR_SAVE_METADATA
514
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
515
+ check_command_permission(command_name)
578
516
 
579
517
  service_factory = validate_config_and_get_service_factory()
580
- config = service_factory.get_config_provider().get_full_config()
581
-
582
518
  project_service = service_factory.get_project_service()
583
519
 
584
520
  project_service.project_get_and_save_inference_simulator_metadata(
585
- config=config,
586
521
  file_path=file_path,
587
522
  slug=unique_id,
588
523
  )
@@ -590,29 +525,25 @@ def get_and_save_inference_simulator_metadata(
590
525
  raise typer.Exit(0)
591
526
 
592
527
 
593
- @inference_simulators_app.command(name='push', no_args_is_help=True, help="Push an inference simulator within the project to model registry")
528
+ @inference_simulators_app.command(name='push', no_args_is_help=True, help="Push an inference simulator within the project to model registry", **get_command_metadata(CliCommand.PROJECT_INFERENCE_SIMULATOR_PUSH))
594
529
  def push_inference_simulator(
595
530
  unique_id: Optional[str] = typer.Argument(help=__("Inference simulator unique ID"),),
596
531
  ):
597
- """
598
- Push an inference simulator within a project to AWS
599
- """
600
- app_logger.info(f'Pushing an inference simulator')
532
+ command_name = CliCommand.PROJECT_INFERENCE_SIMULATOR_PUSH
533
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
534
+ check_command_permission(command_name)
601
535
 
602
536
  service_factory = validate_config_and_get_service_factory()
603
- config = service_factory.get_config_provider().get_full_config()
604
-
605
537
  project_service = service_factory.get_project_service()
606
538
 
607
539
  project_service.project_push_inference_simulator(
608
- config=config,
609
540
  slug=unique_id,
610
541
  )
611
542
 
612
543
  raise typer.Exit(0)
613
544
 
614
545
 
615
- @inference_simulators_app.command("ls", help=__("List inference simulators"))
546
+ @inference_simulators_app.command("ls", help=__("List inference simulators"), **get_command_metadata(CliCommand.PROJECT_INFERENCE_SIMULATOR_LS))
616
547
  def list_inference_simulators(
617
548
  project_uid: Annotated[str, typer.Argument(help=__("Project unique ID. By default, project info is taken from the current directory"), metavar="OPTIONAL")] = None,
618
549
  row: int = typer.Option(
@@ -637,22 +568,20 @@ def list_inference_simulators(
637
568
  is_eager=False,
638
569
  ),
639
570
  ):
640
- """
641
- Lists inference simulators for a project
642
- """
643
- app_logger.info(f'Start project list inference simulators from {get_current_directory()}')
571
+ command_name = CliCommand.PROJECT_INFERENCE_SIMULATOR_LS
572
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
573
+ check_command_permission(command_name)
644
574
 
645
575
  service_factory = validate_config_and_get_service_factory()
646
- config = service_factory.get_config_provider().get_full_config()
647
576
  project_service: ProjectService = service_factory.get_project_service()
648
577
 
649
- project_service.print_inference_simulator_list(config, project_uid, statuses, row, page)
578
+ project_service.print_inference_simulator_list(project_uid, statuses, row, page)
650
579
 
651
580
  typer.echo(__("Inference simulators listing complete"))
652
581
  raise typer.Exit(0)
653
582
 
654
583
 
655
- @inference_simulator_model_app.command("ls", help=__("List inference simulator models"))
584
+ @inference_simulator_model_app.command("ls", help=__("List inference simulator models"), **get_command_metadata(CliCommand.PROJECT_MODEL_LS))
656
585
  def list_inference_simulator_models(
657
586
  project_uid: Annotated[str, typer.Argument(help=__("Project unique ID. By default, project info is taken from the current directory"), metavar="OPTIONAL")] = None,
658
587
  row: int = typer.Option(
@@ -677,22 +606,20 @@ def list_inference_simulator_models(
677
606
  is_eager=False,
678
607
  ),
679
608
  ):
680
- """
681
- Lists inference simulator models for a project
682
- """
683
- app_logger.info(f'Start project list inference simulator models from {get_current_directory()}')
609
+ command_name = CliCommand.PROJECT_MODEL_LS
610
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
611
+ check_command_permission(command_name)
684
612
 
685
613
  service_factory = validate_config_and_get_service_factory()
686
- config = service_factory.get_config_provider().get_full_config()
687
614
  project_service: ProjectService = service_factory.get_project_service()
688
615
 
689
- project_service.print_inference_simulator_model_list(config, project_uid, statuses, row, page)
616
+ project_service.print_inference_simulator_model_list(project_uid, statuses, row, page)
690
617
 
691
618
  typer.echo(__("Inference simulator models listing complete"))
692
619
  raise typer.Exit(0)
693
620
 
694
621
 
695
- @inference_simulators_app.command(name="logs", no_args_is_help=True, help=__("Stream real-time task logs or view last logs for an inference simulator"))
622
+ @inference_simulators_app.command(name="logs", no_args_is_help=True, help=__("Stream real-time task logs or view last logs for an inference simulator"), **get_command_metadata(CliCommand.PROJECT_INFERENCE_SIMULATOR_LOGS))
696
623
  def inference_simulator_logs(
697
624
  unique_id: Optional[str] = typer.Argument(help=__("Inference simulator unique ID"),),
698
625
  logs_number: Optional[int] = typer.Option(
@@ -703,28 +630,23 @@ def inference_simulator_logs(
703
630
  is_eager=False,
704
631
  ),
705
632
  ):
706
- """
707
- Streams real-time inference simulator logs
708
- """
709
- app_logger.info(f'View inference simulator logs')
633
+ command_name = CliCommand.PROJECT_INFERENCE_SIMULATOR_LOGS
634
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
635
+ check_command_permission(command_name)
710
636
 
711
637
  if not unique_id:
712
638
  typer.echo(__('Inference simulator UID is required'))
713
639
  raise typer.Exit(1)
714
640
 
715
641
  service_factory = validate_config_and_get_service_factory()
716
- config = service_factory.get_config_provider().get_full_config()
717
-
718
642
  logging_service: LoggingService = service_factory.get_logging_service()
719
643
 
720
644
  if logs_number is None:
721
645
  logging_service.stream_inference_simulator_logs_with_controls(
722
- config=config,
723
646
  slug=unique_id
724
647
  )
725
648
  else:
726
649
  get_inference_simulator_response: Optional[GetInferenceSimulatorResponse] = service_factory.get_thestage_api_client().get_inference_simulator(
727
- token=config.main.thestage_auth_token,
728
650
  slug=unique_id,
729
651
  )
730
652
  if not get_inference_simulator_response:
@@ -732,13 +654,13 @@ def inference_simulator_logs(
732
654
  raise typer.Exit(1)
733
655
  else:
734
656
  inference_simulator_id = get_inference_simulator_response.inferenceSimulator.id
735
- logging_service.print_last_inference_simulator_logs(config=config, inference_simulator_id=inference_simulator_id, logs_number=logs_number)
657
+ logging_service.print_last_inference_simulator_logs(inference_simulator_id=inference_simulator_id, logs_number=logs_number)
736
658
 
737
659
  app_logger.info(f'Inference simulator logs - end')
738
660
  raise typer.Exit(0)
739
661
 
740
662
 
741
- @inference_simulator_model_app.command("deploy-instance", no_args_is_help=True, help=__("Deploy an inference simulator model to an instance"))
663
+ @inference_simulator_model_app.command("deploy-instance", no_args_is_help=True, help=__("Deploy an inference simulator model to an instance"), **get_command_metadata(CliCommand.PROJECT_MODEL_DEPLOY_INSTANCE))
742
664
  def deploy_inference_simulator_model_to_instance(
743
665
  unique_id: Optional[str] = typer.Argument(help=__("Inference simulator model unique ID"), ),
744
666
  rented_instance_unique_id: Optional[str] = typer.Option(
@@ -771,24 +693,19 @@ def deploy_inference_simulator_model_to_instance(
771
693
  is_eager=False,
772
694
  ),
773
695
  ):
774
- """
775
- Deploy an inference simulator model to an instance
776
- """
696
+ command_name = CliCommand.PROJECT_MODEL_DEPLOY_INSTANCE
697
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
698
+ check_command_permission(command_name)
777
699
 
778
700
  if unique_id and not re.match(r"^[a-zA-Z0-9-]+$", unique_id):
779
701
  raise typer.BadParameter(__("Invalid UID format. The UID can only contain letters, numbers, and hyphens."))
780
702
 
781
703
  unique_id_with_timestamp = f"{unique_id}-{int(time.time())}"
782
704
 
783
- app_logger.info(f'Deploying an inference simulator model')
784
-
785
705
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
786
- config = service_factory.get_config_provider().get_full_config()
787
-
788
706
  project_service = service_factory.get_project_service()
789
707
 
790
708
  project_service.project_deploy_inference_simulator_model_to_instance(
791
- config=config,
792
709
  unique_id=unique_id,
793
710
  unique_id_with_timestamp=unique_id_with_timestamp,
794
711
  rented_instance_unique_id=rented_instance_unique_id,
@@ -799,13 +716,12 @@ def deploy_inference_simulator_model_to_instance(
799
716
  logging_service: LoggingService = service_factory.get_logging_service()
800
717
 
801
718
  logging_service.stream_inference_simulator_logs_with_controls(
802
- config=config,
803
719
  slug=unique_id_with_timestamp
804
720
  )
805
721
  raise typer.Exit(0)
806
722
 
807
723
 
808
- @inference_simulator_model_app.command("deploy-sagemaker", no_args_is_help=True, help=__("Deploy an inference simulator model to SageMaker"))
724
+ @inference_simulator_model_app.command("deploy-sagemaker", no_args_is_help=True, help=__("Deploy an inference simulator model to SageMaker"), **get_command_metadata(CliCommand.PROJECT_MODEL_DEPLOY_SAGEMAKER))
809
725
  def deploy_inference_simulator_model_to_sagemaker(
810
726
  unique_id: Optional[str] = typer.Argument(help=__("Inference simulator model unique ID"), ),
811
727
  arn: Optional[str] = typer.Option(
@@ -848,22 +764,17 @@ def deploy_inference_simulator_model_to_sagemaker(
848
764
  ),
849
765
 
850
766
  ):
851
- """
852
- Deploy an inference simulator model to SageMaker
853
- """
767
+ command_name = CliCommand.PROJECT_MODEL_DEPLOY_SAGEMAKER
768
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
769
+ check_command_permission(command_name)
854
770
 
855
771
  if unique_id and not re.match(r"^[a-zA-Z0-9-]+$", unique_id):
856
772
  raise typer.BadParameter(__("Invalid UID format. The UID can only contain letters, numbers, and hyphens."))
857
773
 
858
- app_logger.info(f'Deploying an inference simulator model')
859
-
860
774
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
861
- config = service_factory.get_config_provider().get_full_config()
862
-
863
775
  project_service = service_factory.get_project_service()
864
776
 
865
777
  project_service.project_deploy_inference_simulator_model_to_sagemaker(
866
- config=config,
867
778
  unique_id=unique_id,
868
779
  arn=arn,
869
780
  instance_type=instance_type,