thestage 0.5.43__tar.gz → 0.5.44__tar.gz

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 (173) hide show
  1. {thestage-0.5.43 → thestage-0.5.44}/PKG-INFO +1 -1
  2. {thestage-0.5.43 → thestage-0.5.44}/pyproject.toml +1 -1
  3. {thestage-0.5.43 → thestage-0.5.44}/thestage/__init__.py +1 -1
  4. {thestage-0.5.43 → thestage-0.5.44}/thestage/color_scheme/color_scheme.py +2 -1
  5. {thestage-0.5.43 → thestage-0.5.44}/thestage/controllers/project_controller.py +89 -7
  6. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/git/git_client.py +40 -22
  7. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/api_client.py +1 -1
  8. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/filesystem_service.py +1 -0
  9. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/logging/logging_service.py +1 -1
  10. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/project/project_service.py +61 -6
  11. {thestage-0.5.43 → thestage-0.5.44}/LICENSE.txt +0 -0
  12. {thestage-0.5.43 → thestage-0.5.44}/README.md +0 -0
  13. {thestage-0.5.43 → thestage-0.5.44}/thestage/.env +0 -0
  14. {thestage-0.5.43 → thestage-0.5.44}/thestage/__main__.py +0 -0
  15. {thestage-0.5.43 → thestage-0.5.44}/thestage/config/__init__.py +0 -0
  16. {thestage-0.5.43 → thestage-0.5.44}/thestage/config/env_base.py +0 -0
  17. {thestage-0.5.43 → thestage-0.5.44}/thestage/controllers/__init__.py +0 -0
  18. {thestage-0.5.43 → thestage-0.5.44}/thestage/controllers/base_controller.py +0 -0
  19. {thestage-0.5.43 → thestage-0.5.44}/thestage/controllers/config_controller.py +0 -0
  20. {thestage-0.5.43 → thestage-0.5.44}/thestage/controllers/container_controller.py +0 -0
  21. {thestage-0.5.43 → thestage-0.5.44}/thestage/controllers/instance_controller.py +0 -0
  22. {thestage-0.5.43 → thestage-0.5.44}/thestage/controllers/utils_controller.py +0 -0
  23. {thestage-0.5.43 → thestage-0.5.44}/thestage/debug_main.dist.py +0 -0
  24. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/__init__.py +0 -0
  25. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/container.py +0 -0
  26. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/enums/__init__.py +0 -0
  27. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/enums/order_direction_type.py +0 -0
  28. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/enums/shell_type.py +0 -0
  29. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/enums/tail_output_type.py +0 -0
  30. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/enums/yes_no_response.py +0 -0
  31. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/file_item.py +0 -0
  32. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/project_inference_simulator.py +0 -0
  33. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/project_inference_simulator_model.py +0 -0
  34. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/project_task.py +0 -0
  35. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/rented_instance.py +0 -0
  36. {thestage-0.5.43 → thestage-0.5.44}/thestage/entities/self_hosted_instance.py +0 -0
  37. {thestage-0.5.43 → thestage-0.5.44}/thestage/exceptions/__init__.py +0 -0
  38. {thestage-0.5.43 → thestage-0.5.44}/thestage/exceptions/auth_exception.py +0 -0
  39. {thestage-0.5.43 → thestage-0.5.44}/thestage/exceptions/base_exception.py +0 -0
  40. {thestage-0.5.43 → thestage-0.5.44}/thestage/exceptions/business_logic_exception.py +0 -0
  41. {thestage-0.5.43 → thestage-0.5.44}/thestage/exceptions/config_exception.py +0 -0
  42. {thestage-0.5.43 → thestage-0.5.44}/thestage/exceptions/file_system_exception.py +0 -0
  43. {thestage-0.5.43 → thestage-0.5.44}/thestage/exceptions/git_access_exception.py +0 -0
  44. {thestage-0.5.43 → thestage-0.5.44}/thestage/exceptions/http_error_exception.py +0 -0
  45. {thestage-0.5.43 → thestage-0.5.44}/thestage/exceptions/remote_server_exception.py +0 -0
  46. {thestage-0.5.43 → thestage-0.5.44}/thestage/git/ProgressPrinter.py +0 -0
  47. {thestage-0.5.43 → thestage-0.5.44}/thestage/helpers/__init__.py +0 -0
  48. {thestage-0.5.43 → thestage-0.5.44}/thestage/helpers/error_handler.py +0 -0
  49. {thestage-0.5.43 → thestage-0.5.44}/thestage/helpers/logger/__init__.py +0 -0
  50. {thestage-0.5.43 → thestage-0.5.44}/thestage/helpers/logger/app_logger.py +0 -0
  51. {thestage-0.5.43 → thestage-0.5.44}/thestage/helpers/ssh_util.py +0 -0
  52. {thestage-0.5.43 → thestage-0.5.44}/thestage/i18n/en_GB/messages.po +0 -0
  53. {thestage-0.5.43 → thestage-0.5.44}/thestage/i18n/translation.py +0 -0
  54. {thestage-0.5.43 → thestage-0.5.44}/thestage/main.py +0 -0
  55. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/.env +0 -0
  56. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/__init__.py +0 -0
  57. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/abstract_mapper.py +0 -0
  58. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/abstract_service.py +0 -0
  59. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/app_config_service.py +0 -0
  60. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/.DS_Store +0 -0
  61. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/__init__.py +0 -0
  62. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/git/__init__.py +0 -0
  63. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/__init__.py +0 -0
  64. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/core/api_client_abstract.py +0 -0
  65. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/core/api_client_core.py +0 -0
  66. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/core/http_client_exception.py +0 -0
  67. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/__init__.py +0 -0
  68. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/base_response.py +0 -0
  69. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/cloud_provider_region.py +0 -0
  70. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/container_param_request.py +0 -0
  71. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/container_response.py +0 -0
  72. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/docker_container_assigned_device.py +0 -0
  73. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/docker_container_controller/docker_container_list_request.py +0 -0
  74. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/docker_container_controller/docker_container_list_response.py +0 -0
  75. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/docker_container_mapping.py +0 -0
  76. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/entity_filter_request.py +0 -0
  77. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/__init__.py +0 -0
  78. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/container_pending_action.py +0 -0
  79. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/container_status.py +0 -0
  80. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/cpu_type.py +0 -0
  81. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/currency_type.py +0 -0
  82. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/daemon_status.py +0 -0
  83. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/disk_type.py +0 -0
  84. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/drive_type.py +0 -0
  85. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/gpu_name.py +0 -0
  86. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/inference_model_status.py +0 -0
  87. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/inference_simulator_status.py +0 -0
  88. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/instance_rented_status.py +0 -0
  89. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/instance_type.py +0 -0
  90. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/location_region.py +0 -0
  91. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/power_status.py +0 -0
  92. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/provider_name.py +0 -0
  93. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/selfhosted_status.py +0 -0
  94. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/task_execution_status.py +0 -0
  95. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/enums/task_status.py +0 -0
  96. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/frontend_status.py +0 -0
  97. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_request.py +0 -0
  98. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py +0 -0
  99. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_request.py +0 -0
  100. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_response.py +0 -0
  101. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py +0 -0
  102. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_response.py +0 -0
  103. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_for_project_request.py +0 -0
  104. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_for_project_response.py +0 -0
  105. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_model_list_for_project_request.py +0 -0
  106. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_model_list_for_project_response.py +0 -0
  107. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_simulator_model_response.py +0 -0
  108. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/inference_simulator_response.py +0 -0
  109. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/installed_service.py +0 -0
  110. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/instance_detected_gpus.py +0 -0
  111. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/instance_rented_response.py +0 -0
  112. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/logging_controller/docker_container_log_stream_request.py +0 -0
  113. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/logging_controller/log_polling_request.py +0 -0
  114. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/logging_controller/log_polling_response.py +0 -0
  115. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/logging_controller/task_log_stream_request.py +0 -0
  116. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_request.py +0 -0
  117. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_response.py +0 -0
  118. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/paginated_entity_list.py +0 -0
  119. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/pagination_data.py +0 -0
  120. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/price_definition.py +0 -0
  121. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_request.py +0 -0
  122. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_response.py +0 -0
  123. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_request.py +0 -0
  124. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_response.py +0 -0
  125. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_request.py +0 -0
  126. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py +0 -0
  127. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_request.py +0 -0
  128. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_response.py +0 -0
  129. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/project_response.py +0 -0
  130. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/selfhosted_instance_response.py +0 -0
  131. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/sftp_path_helper.py +0 -0
  132. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_key_to_user_request.py +0 -0
  133. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_key_to_user_response.py +0 -0
  134. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_request.py +0 -0
  135. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_response.py +0 -0
  136. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/is_user_has_public_ssh_key_request.py +0 -0
  137. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/is_user_has_public_ssh_key_response.py +0 -0
  138. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_request.py +0 -0
  139. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_response.py +0 -0
  140. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/task_controller/task_status_localized_map_response.py +0 -0
  141. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/task_controller/task_view_response.py +0 -0
  142. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/clients/thestage_api/dtos/user_profile.py +0 -0
  143. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/config_provider/__init__.py +0 -0
  144. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/config_provider/config_provider.py +0 -0
  145. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/connect/connect_service.py +0 -0
  146. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/connect/dto/remote_server_config.py +0 -0
  147. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/container/__init__.py +0 -0
  148. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/container/container_service.py +0 -0
  149. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/container/mapper/__init__.py +0 -0
  150. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/container/mapper/container_mapper.py +0 -0
  151. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/core_files/config_entity.py +0 -0
  152. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/instance/__init__.py +0 -0
  153. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/instance/instance_service.py +0 -0
  154. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/instance/mapper/__init__.py +0 -0
  155. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/instance/mapper/instance_mapper.py +0 -0
  156. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/instance/mapper/selfhosted_mapper.py +0 -0
  157. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/logging/byte_print_style.py +0 -0
  158. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/logging/dto/log_message.py +0 -0
  159. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/logging/dto/log_type.py +0 -0
  160. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/logging/exception/log_polling_exception.py +0 -0
  161. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/logging/logging_constants.py +0 -0
  162. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/project/__init__.py +0 -0
  163. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/project/dto/inference_simulator_dto.py +0 -0
  164. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/project/dto/inference_simulator_model_dto.py +0 -0
  165. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/project/dto/project_config.py +0 -0
  166. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/project/mapper/__init__.py +0 -0
  167. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/project/mapper/project_inference_simulator_mapper.py +0 -0
  168. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/project/mapper/project_inference_simulator_model_mapper.py +0 -0
  169. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/project/mapper/project_task_mapper.py +0 -0
  170. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/remote_server_service.py +0 -0
  171. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/service_factory.py +0 -0
  172. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/task/dto/task_dto.py +0 -0
  173. {thestage-0.5.43 → thestage-0.5.44}/thestage/services/validation_service.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: thestage
3
- Version: 0.5.43
3
+ Version: 0.5.44
4
4
  Summary:
5
5
  Author: TheStage AI team
6
6
  Author-email: hello@thestage.ai
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "thestage"
3
- version = "0.5.43"
3
+ version = "0.5.44"
4
4
  description = ""
5
5
  authors = ["TheStage AI team <hello@thestage.ai>"]
6
6
  readme = "README.md"
@@ -1,3 +1,3 @@
1
1
  from . import *
2
2
  __app_name__ = "thestage"
3
- __version__ = "0.5.43"
3
+ __version__ = "0.5.44"
@@ -1,6 +1,7 @@
1
1
  from enum import Enum
2
2
 
3
-
3
+ # https://rich.readthedocs.io/en/stable/appendix/colors.html
4
4
  class ColorScheme(str, Enum):
5
5
  GIT_HEADLESS = "orange_red1"
6
6
  WARNING = "orange_red1"
7
+ USEFUL_INFO = "deep_sky_blue1"
@@ -183,6 +183,34 @@ def run(
183
183
  raise typer.Exit(0)
184
184
 
185
185
 
186
+ @task_app.command(name='cancel', no_args_is_help=True, help=__("Cancel a task by ID"))
187
+ def cancel_task(
188
+ task_id: Annotated[int, typer.Argument(
189
+ help=__("Task ID (required)"),
190
+ )],
191
+ ):
192
+ """
193
+ Cancels a task
194
+ """
195
+ app_logger.info(f'Start cancel task from {get_current_directory()}')
196
+
197
+ if not task_id:
198
+ typer.echo(__('Task ID is required'))
199
+ raise typer.Exit(1)
200
+
201
+ service_factory = validate_config_and_get_service_factory()
202
+ config = service_factory.get_config_provider().get_full_config()
203
+
204
+ project_service = service_factory.get_project_service()
205
+
206
+ project_service.cancel_task(
207
+ config=config,
208
+ task_id=task_id
209
+ )
210
+
211
+ raise typer.Exit(0)
212
+
213
+
186
214
  @task_app.command("ls", help=__("List tasks"))
187
215
  def list_runs(
188
216
  project_uid: Annotated[str, typer.Argument(help=__("Project unique ID. By default, project info is taken from the current directory"), metavar="OPTIONAL")] = None,
@@ -287,9 +315,9 @@ def checkout_project(
287
315
  ),
288
316
  ):
289
317
  """
290
- Initializes project in current working directory
318
+ Checkout project in current working directory
291
319
  """
292
- app_logger.info(f'Start project init from {get_current_directory()}')
320
+ app_logger.info(f'Start project checkout from {get_current_directory()}')
293
321
 
294
322
  service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
295
323
  config = service_factory.get_config_provider().get_full_config()
@@ -315,11 +343,8 @@ def checkout_project(
315
343
  raise typer.Exit(0)
316
344
 
317
345
 
318
- @config_app.command(name='set-default-container', no_args_is_help=True, help=__("Set default docker container for a project installation"))
319
- def set_default_container(
320
- container_uid: Annotated[Optional[str], typer.Argument(
321
- help=__("Unique ID of the container to use by default for running tasks"),
322
- )] = None,
346
+ @app.command(name='pull', help=__("Pulls the changes from the remote project repository. Equivalent to 'git pull'."))
347
+ def pull_project(
323
348
  working_directory: Optional[str] = typer.Option(
324
349
  None,
325
350
  "--working-directory",
@@ -327,6 +352,56 @@ def set_default_container(
327
352
  help=__("Full path to working directory"),
328
353
  is_eager=False,
329
354
  ),
355
+ ):
356
+ """
357
+ Pull project in current working directory
358
+ """
359
+ app_logger.info(f'Start project pull from {get_current_directory()}')
360
+
361
+ service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
362
+ config = service_factory.get_config_provider().get_full_config()
363
+
364
+ project_service = service_factory.get_project_service()
365
+
366
+ project_service.pull_project(
367
+ config=config,
368
+ )
369
+
370
+ raise typer.Exit(0)
371
+
372
+
373
+ @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}'."))
374
+ def reset_project(
375
+ working_directory: Optional[str] = typer.Option(
376
+ None,
377
+ "--working-directory",
378
+ "-wd",
379
+ help=__("Full path to working directory"),
380
+ is_eager=False,
381
+ ),
382
+ ):
383
+ """
384
+ Pull project in current working directory
385
+ """
386
+ app_logger.info(f'Start project pull from {get_current_directory()}')
387
+
388
+ service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
389
+ config = service_factory.get_config_provider().get_full_config()
390
+
391
+ project_service = service_factory.get_project_service()
392
+
393
+ project_service.reset_project(
394
+ config=config
395
+ )
396
+
397
+ raise typer.Exit(0)
398
+
399
+
400
+ @config_app.command(name='set-default-container', no_args_is_help=True, help=__("Set default docker container for a project installation"))
401
+ def set_default_container(
402
+ container_uid: Annotated[Optional[str], typer.Argument(
403
+ help=__("Unique ID of the container to use by default for running tasks"),
404
+ )] = None,
330
405
  unset_default_container: Optional[bool] = typer.Option(
331
406
  False,
332
407
  "--unset",
@@ -334,6 +409,13 @@ def set_default_container(
334
409
  help=__("Unsets the default docker container"),
335
410
  is_eager=False,
336
411
  ),
412
+ working_directory: Optional[str] = typer.Option(
413
+ None,
414
+ "--working-directory",
415
+ "-wd",
416
+ help=__("Full path to working directory"),
417
+ is_eager=False,
418
+ ),
337
419
  ):
338
420
  """
339
421
  Initializes project in current working directory
@@ -10,6 +10,7 @@ from gitdb.exc import BadName
10
10
  from rich import print
11
11
 
12
12
  from thestage.color_scheme.color_scheme import ColorScheme
13
+ from thestage.config import THESTAGE_CONFIG_DIR
13
14
  from thestage.exceptions.git_access_exception import GitAccessException
14
15
  from thestage.git.ProgressPrinter import ProgressPrinter
15
16
  from thestage.services.filesystem_service import FileSystemServiceCore
@@ -18,7 +19,7 @@ from thestage.services.filesystem_service import FileSystemServiceCore
18
19
  class GitLocalClient:
19
20
  __base_name_remote: str = 'origin'
20
21
  __base_name_local: str = 'main'
21
- __git_ignore_thestage_line: str = '/.thestage/'
22
+ __git_ignore_thestage_line: str = f'/{THESTAGE_CONFIG_DIR}/'
22
23
 
23
24
  __special_main_branches = ['main', 'master']
24
25
 
@@ -30,6 +31,7 @@ class GitLocalClient:
30
31
  ):
31
32
  self.__file_system_service = file_system_service
32
33
 
34
+ # todo delete this fuckery
33
35
  def __get_repo(self, path: str) -> Repo:
34
36
  return git.Repo(path)
35
37
 
@@ -105,32 +107,37 @@ class GitLocalClient:
105
107
  with repo.git.custom_environment(GIT_SSH_COMMAND=git_ssh_cmd):
106
108
  remote: Remote = repo.remote(self.__base_name_remote)
107
109
  if remote:
110
+ progress = ProgressPrinter()
108
111
  try:
109
- remote.fetch()
110
- except GitCommandError as base_ex:
111
- msg = base_ex.stderr
112
- if msg and 'fatal: Could not read from remote repository' in msg:
113
- raise GitAccessException(
114
- message='You dont have access to repository, or repository not found.',
115
- url=self.build_http_repo_url(git_path=remote.url),
116
- dop_message=msg,
117
- )
118
- else:
119
- raise base_ex
120
-
121
- def git_pull(self, path: str, deploy_key_path: str, branch: Optional[str] = None):
112
+ remote.fetch(progress=progress)
113
+ except GitCommandError as ex:
114
+ for line in progress.allDroppedLines():
115
+ # returning the whole output if failed - so that user have any idea what's going on
116
+ print(f'>> {line}')
117
+ raise ex
118
+
119
+
120
+ def git_pull(self, path: str, deploy_key_path: str):
122
121
  repo = self.__get_repo(path=path)
123
122
  git_ssh_cmd = 'ssh -F /dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i %s' % deploy_key_path
124
123
 
125
124
  with repo.git.custom_environment(GIT_SSH_COMMAND=git_ssh_cmd):
126
125
  local_branch = self.__base_name_local
127
- if branch:
128
- if self.__base_name_remote in branch:
129
- local_branch = branch.replace(f"{self.__base_name_remote}/", '').strip()
130
- else:
131
- local_branch = branch
126
+ if repo.active_branch.name:
127
+ local_branch = repo.active_branch.name
132
128
 
133
- repo.git.pull(self.__base_name_remote, local_branch)
129
+ origin = repo.remote(self.__base_name_remote)
130
+
131
+ if origin:
132
+ progress = ProgressPrinter()
133
+ try:
134
+ origin.pull(refspec=local_branch, progress=progress)
135
+ typer.echo(f"Pulled remote changes to branch '{local_branch}'")
136
+ except GitCommandError as ex:
137
+ for line in progress.allDroppedLines():
138
+ # returning the whole output if failed - so that user have any idea what's going on
139
+ print(f'>> {line}')
140
+ raise ex
134
141
 
135
142
  def find_main_branch_name(self, path: str) -> Optional[str]:
136
143
  repo = self.__get_repo(path=path)
@@ -275,10 +282,16 @@ class GitLocalClient:
275
282
  if repo:
276
283
  return repo.head.is_detached
277
284
 
278
- def reset_hard(self, path: str):
285
+ def reset_hard(self, path: str, deploy_key_path: str, reset_to_origin: bool):
279
286
  repo = self.__get_repo(path=path)
280
287
  if repo:
281
- repo.git.reset('--hard')
288
+ git_ssh_cmd = 'ssh -F /dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i %s' % deploy_key_path
289
+ with repo.git.custom_environment(GIT_SSH_COMMAND=git_ssh_cmd):
290
+ if reset_to_origin:
291
+ repo.git.reset('--hard', f'origin/{repo.active_branch.name}')
292
+ typer.echo(f'Branch "{repo.active_branch.name}" is now synced to its remote counterpart')
293
+ else:
294
+ typer.echo('simple branch reset is not implemented')
282
295
 
283
296
  # refers to a "headless commit" where something was committed while in detached head state and head is pointing at that commit
284
297
  def is_head_committed_in_headless_state(self, path: str) -> bool:
@@ -297,6 +310,11 @@ class GitLocalClient:
297
310
  for branch in repo.heads:
298
311
  if branch.name == branch_name:
299
312
  return True
313
+
314
+ for ref in repo.remotes.origin.refs:
315
+ if ref.remote_head == branch_name:
316
+ typer.echo(f'Found remote branch "{branch_name}"')
317
+ return True
300
318
  return False
301
319
 
302
320
  def checkout_to_new_branch(self, path: str, branch_name: str):
@@ -361,7 +361,7 @@ class TheStageApiClient(TheStageApiClientCore):
361
361
  result = UserProfileResponse.model_validate(response) if response else None
362
362
  return result if result else None
363
363
 
364
- def stop_task_on_instance(
364
+ def cancel_task(
365
365
  self,
366
366
  token: str,
367
367
  task_id: int,
@@ -83,6 +83,7 @@ class FileSystemServiceCore:
83
83
  file.write(new_line)
84
84
  file.write('\n')
85
85
 
86
+ # TODO remove this fucking useless shit
86
87
  def check_if_path_exist(self, file: str) -> bool:
87
88
  path = self.get_path(file, auto_create=False)
88
89
  if path.exists():
@@ -151,7 +151,7 @@ class LoggingService(AbstractService):
151
151
  print_logs_task.cancel()
152
152
  if not input_task.result(): # result is only expected if ctrl+D triggered EOFError
153
153
  typer.echo(f"\rTask {task_id} will be canceled")
154
- self.__thestage_api_client.stop_task_on_instance(
154
+ self.__thestage_api_client.cancel_task(
155
155
  token=config.main.thestage_auth_token,
156
156
  task_id=task.id,
157
157
  )
@@ -148,11 +148,6 @@ class ProjectService(AbstractService):
148
148
 
149
149
  self.__git_local_client.git_fetch(path=config.runtime.working_directory, deploy_key_path=deploy_key_path)
150
150
 
151
- branch = self.__git_local_client.find_main_branch_name(path=config.runtime.working_directory, )
152
- if branch:
153
- self.__git_local_client.git_pull(path=config.runtime.working_directory, deploy_key_path=deploy_key_path,
154
- branch=branch)
155
-
156
151
  self.__git_local_client.init_gitignore(path=config.runtime.working_directory)
157
152
 
158
153
  self.__git_local_client.git_add_all(repo_path=config.runtime.working_directory)
@@ -401,6 +396,19 @@ class ProjectService(AbstractService):
401
396
  typer.echo("The task failed with an error")
402
397
  raise typer.Exit(1)
403
398
 
399
+ @error_handler()
400
+ def cancel_task(self, task_id: int, config: ConfigEntity):
401
+ cancel_result = self.__thestage_api_client.cancel_task(
402
+ token=config.main.thestage_auth_token,
403
+ task_id=task_id,
404
+ )
405
+
406
+ if cancel_result.is_success:
407
+ typer.echo(f'Task {task_id} has been canceled')
408
+ else:
409
+ typer.echo(f'Task {task_id} could not be canceled: {cancel_result.message}')
410
+
411
+
404
412
  @error_handler()
405
413
  def project_run_inference_simulator(
406
414
  self,
@@ -828,6 +836,8 @@ class ProjectService(AbstractService):
828
836
  typer.echo("No main branch found")
829
837
 
830
838
 
839
+
840
+
831
841
  @error_handler()
832
842
  def set_default_container(self, config: ConfigEntity, container_uid: Optional[str]):
833
843
  project_config: ProjectConfig = self.__config_provider.read_project_config()
@@ -880,6 +890,8 @@ class ProjectService(AbstractService):
880
890
  typer.echo(f"No project found in working directory")
881
891
  raise typer.Exit(1)
882
892
 
893
+ is_deploy_key_exists = project_config.deploy_key_path and self.__file_system_service.check_if_path_exist(project_config.deploy_key_path)
894
+
883
895
  typer.echo(tabulate(
884
896
  [
885
897
  [
@@ -888,11 +900,20 @@ class ProjectService(AbstractService):
888
900
  [
889
901
  "Default docker container unique ID", project_config.default_container_uid if project_config.default_container_uid else "<None>"
890
902
  ],
903
+ [
904
+ "Deploy key path", project_config.deploy_key_path if is_deploy_key_exists else "<None>"
905
+ ],
891
906
  ],
892
907
  showindex=False,
893
908
  tablefmt="simple",
894
909
  ))
895
910
 
911
+ if is_deploy_key_exists:
912
+ typer.echo("")
913
+ typer.echo(f"You can insert the following text:")
914
+ print(f"[{ColorScheme.USEFUL_INFO.value}]GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i {project_config.deploy_key_path}\"[{ColorScheme.USEFUL_INFO.value}]")
915
+ typer.echo(f"before any regular git command to manage your local Project repository directly")
916
+
896
917
  @error_handler()
897
918
  def __get_fixed_project_config(self, config: ConfigEntity) -> Optional[ProjectConfig]:
898
919
  project_config: ProjectConfig = self.__config_provider.read_project_config()
@@ -1083,4 +1104,38 @@ class ProjectService(AbstractService):
1083
1104
 
1084
1105
  except Exception as e:
1085
1106
  typer.echo(__("Failed to deploy the inference simulator model to SageMaker: %error%", {"error": str(e)}))
1086
- raise typer.Exit(1)
1107
+ raise typer.Exit(1)
1108
+
1109
+
1110
+ @error_handler()
1111
+ def pull_project(self, config: ConfigEntity):
1112
+ project_config: ProjectConfig = self.__get_fixed_project_config(config=config)
1113
+ if not project_config:
1114
+ typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first.", {"path": config.runtime.working_directory}))
1115
+ raise typer.Exit(1)
1116
+
1117
+ typer.echo("Pulling code from remote repository...")
1118
+ self.__git_local_client.git_pull(
1119
+ path=config.runtime.working_directory,
1120
+ deploy_key_path=project_config.deploy_key_path,
1121
+ )
1122
+
1123
+
1124
+ @error_handler()
1125
+ def reset_project(self, config: ConfigEntity):
1126
+ project_config: ProjectConfig = self.__get_fixed_project_config(config=config)
1127
+ if not project_config:
1128
+ typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first.", {"path": config.runtime.working_directory}))
1129
+ raise typer.Exit(1)
1130
+
1131
+ typer.echo("Fetching code from remote repository...")
1132
+ self.__git_local_client.git_fetch(
1133
+ path=config.runtime.working_directory,
1134
+ deploy_key_path=project_config.deploy_key_path,
1135
+ )
1136
+ typer.echo("Resetting local branch...")
1137
+ self.__git_local_client.reset_hard(
1138
+ path=config.runtime.working_directory,
1139
+ deploy_key_path=project_config.deploy_key_path,
1140
+ reset_to_origin=True
1141
+ )
File without changes
File without changes
File without changes
File without changes