frogml-cli 0.0.1__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 (287) hide show
  1. frogml_cli/__init__.py +10 -0
  2. frogml_cli/cli.py +40 -0
  3. frogml_cli/commands/__init__.py +0 -0
  4. frogml_cli/commands/_logic/__init__.py +0 -0
  5. frogml_cli/commands/_logic/tools.py +6 -0
  6. frogml_cli/commands/alerts/__init__.py +0 -0
  7. frogml_cli/commands/alerts/alerts_commnad_group.py +18 -0
  8. frogml_cli/commands/alerts/delete/__init__.py +0 -0
  9. frogml_cli/commands/alerts/delete/_logic.py +5 -0
  10. frogml_cli/commands/alerts/delete/ui.py +10 -0
  11. frogml_cli/commands/alerts/list/__init__.py +0 -0
  12. frogml_cli/commands/alerts/list/_logic.py +23 -0
  13. frogml_cli/commands/alerts/list/ui.py +17 -0
  14. frogml_cli/commands/alerts/register/__init__.py +0 -0
  15. frogml_cli/commands/alerts/register/_logic.py +72 -0
  16. frogml_cli/commands/alerts/register/ui.py +30 -0
  17. frogml_cli/commands/audience/__init__.py +0 -0
  18. frogml_cli/commands/audience/_logic/__init__.py +0 -0
  19. frogml_cli/commands/audience/_logic/config/__init__.py +0 -0
  20. frogml_cli/commands/audience/_logic/config/config_base.py +15 -0
  21. frogml_cli/commands/audience/_logic/config/parser.py +30 -0
  22. frogml_cli/commands/audience/_logic/config/v1/__init__.py +0 -0
  23. frogml_cli/commands/audience/_logic/config/v1/audience_config.py +25 -0
  24. frogml_cli/commands/audience/_logic/config/v1/conditions_config.py +59 -0
  25. frogml_cli/commands/audience/_logic/config/v1/config_v1.py +23 -0
  26. frogml_cli/commands/audience/_logic/config/v1/route_config.py +15 -0
  27. frogml_cli/commands/audience/_logic/config/v1/spec.py +9 -0
  28. frogml_cli/commands/audience/audience_api_dump.py +86 -0
  29. frogml_cli/commands/audience/audience_commands_group.py +30 -0
  30. frogml_cli/commands/audience/create/__init__.py +0 -0
  31. frogml_cli/commands/audience/create/logic.py +41 -0
  32. frogml_cli/commands/audience/create/ui.py +21 -0
  33. frogml_cli/commands/audience/delete/__init__.py +0 -0
  34. frogml_cli/commands/audience/delete/logic.py +13 -0
  35. frogml_cli/commands/audience/delete/ui.py +17 -0
  36. frogml_cli/commands/audience/get/__init__.py +0 -0
  37. frogml_cli/commands/audience/get/logic.py +14 -0
  38. frogml_cli/commands/audience/get/ui.py +25 -0
  39. frogml_cli/commands/audience/list/__init__.py +0 -0
  40. frogml_cli/commands/audience/list/logic.py +16 -0
  41. frogml_cli/commands/audience/list/ui.py +26 -0
  42. frogml_cli/commands/audience/update/__init__.py +0 -0
  43. frogml_cli/commands/audience/update/logic.py +37 -0
  44. frogml_cli/commands/audience/update/ui.py +26 -0
  45. frogml_cli/commands/auto_scalling/__init__.py +0 -0
  46. frogml_cli/commands/auto_scalling/_logic/__init__.py +0 -0
  47. frogml_cli/commands/auto_scalling/_logic/config/__init__.py +3 -0
  48. frogml_cli/commands/auto_scalling/_logic/config/config.py +152 -0
  49. frogml_cli/commands/auto_scalling/_logic/config/parser.py +21 -0
  50. frogml_cli/commands/auto_scalling/attach/__init__.py +0 -0
  51. frogml_cli/commands/auto_scalling/attach/_logic.py +43 -0
  52. frogml_cli/commands/auto_scalling/attach/ui.py +21 -0
  53. frogml_cli/commands/auto_scalling/autoscaling_commands_group.py +15 -0
  54. frogml_cli/commands/automations/__init__.py +0 -0
  55. frogml_cli/commands/automations/automations_commands_group.py +30 -0
  56. frogml_cli/commands/automations/delete/__init__.py +0 -0
  57. frogml_cli/commands/automations/delete/_logic.py +6 -0
  58. frogml_cli/commands/automations/delete/ui.py +23 -0
  59. frogml_cli/commands/automations/executions/__init__.py +0 -0
  60. frogml_cli/commands/automations/executions/executions_commands_group.py +14 -0
  61. frogml_cli/commands/automations/executions/list/__init__.py +0 -0
  62. frogml_cli/commands/automations/executions/list/_logic.py +8 -0
  63. frogml_cli/commands/automations/executions/list/ui.py +27 -0
  64. frogml_cli/commands/automations/list/__init__.py +0 -0
  65. frogml_cli/commands/automations/list/_logic.py +36 -0
  66. frogml_cli/commands/automations/list/ui.py +21 -0
  67. frogml_cli/commands/automations/register/__init__.py +0 -0
  68. frogml_cli/commands/automations/register/_logic.py +43 -0
  69. frogml_cli/commands/automations/register/ui.py +44 -0
  70. frogml_cli/commands/config/__init__.py +0 -0
  71. frogml_cli/commands/config/add/__init__.py +0 -0
  72. frogml_cli/commands/config/add/ui.py +62 -0
  73. frogml_cli/commands/config/config_commands_group.py +11 -0
  74. frogml_cli/commands/feature_store/__init__.py +0 -0
  75. frogml_cli/commands/feature_store/backfill/__init__.py +0 -0
  76. frogml_cli/commands/feature_store/backfill/_logic.py +140 -0
  77. frogml_cli/commands/feature_store/backfill/ui.py +129 -0
  78. frogml_cli/commands/feature_store/delete/__init__.py +0 -0
  79. frogml_cli/commands/feature_store/delete/_logic.py +107 -0
  80. frogml_cli/commands/feature_store/delete/ui.py +40 -0
  81. frogml_cli/commands/feature_store/execution/__init__.py +0 -0
  82. frogml_cli/commands/feature_store/execution/ui.py +19 -0
  83. frogml_cli/commands/feature_store/feature_store_command_group.py +29 -0
  84. frogml_cli/commands/feature_store/list/__init__.py +0 -0
  85. frogml_cli/commands/feature_store/list/ui.py +140 -0
  86. frogml_cli/commands/feature_store/pause/__init__.py +0 -0
  87. frogml_cli/commands/feature_store/pause/ui.py +18 -0
  88. frogml_cli/commands/feature_store/register/__init__.py +0 -0
  89. frogml_cli/commands/feature_store/register/_logic.py +369 -0
  90. frogml_cli/commands/feature_store/register/ui.py +111 -0
  91. frogml_cli/commands/feature_store/resume/__init__.py +0 -0
  92. frogml_cli/commands/feature_store/resume/ui.py +18 -0
  93. frogml_cli/commands/feature_store/trigger/__init__.py +0 -0
  94. frogml_cli/commands/feature_store/trigger/ui.py +39 -0
  95. frogml_cli/commands/models/__init__.py +0 -0
  96. frogml_cli/commands/models/build/__init__.py +0 -0
  97. frogml_cli/commands/models/build/_logic/__init__.py +0 -0
  98. frogml_cli/commands/models/build/_logic/build_steps.py +42 -0
  99. frogml_cli/commands/models/build/_logic/client_logs/__init__.py +0 -0
  100. frogml_cli/commands/models/build/_logic/client_logs/cli_phase_run_handler.py +123 -0
  101. frogml_cli/commands/models/build/_logic/client_logs/cli_trigger_build_logger.py +19 -0
  102. frogml_cli/commands/models/build/_logic/client_logs/logger.py +88 -0
  103. frogml_cli/commands/models/build/_logic/client_logs/messages.py +36 -0
  104. frogml_cli/commands/models/build/_logic/client_logs/spinner.py +14 -0
  105. frogml_cli/commands/models/build/_logic/client_logs/trigger_build_logger.py +54 -0
  106. frogml_cli/commands/models/build/_logic/client_logs/utils.py +12 -0
  107. frogml_cli/commands/models/build/_logic/phase/__init__.py +0 -0
  108. frogml_cli/commands/models/build/_logic/phase/a_fetch_model_code/__init__.py +20 -0
  109. frogml_cli/commands/models/build/_logic/phase/a_fetch_model_code/get_sdk_version_step.py +15 -0
  110. frogml_cli/commands/models/build/_logic/phase/b_remote_register_frogml_build/__init__.py +16 -0
  111. frogml_cli/commands/models/build/_logic/phase/c_deploy/__init__.py +6 -0
  112. frogml_cli/commands/models/build/_logic/phase/c_deploy/build_polling_status.py +55 -0
  113. frogml_cli/commands/models/build/_logic/phase/c_deploy/deploy_build.py +61 -0
  114. frogml_cli/commands/models/build/_logic/util/__init__.py +0 -0
  115. frogml_cli/commands/models/build/_logic/util/protobuf_factory.py +45 -0
  116. frogml_cli/commands/models/build/_logic/util/step_decorator.py +60 -0
  117. frogml_cli/commands/models/build/_logic/util/text.py +9 -0
  118. frogml_cli/commands/models/build/_logic/wait_until_finished.py +27 -0
  119. frogml_cli/commands/models/build/ui.py +337 -0
  120. frogml_cli/commands/models/builds/__init__.py +0 -0
  121. frogml_cli/commands/models/builds/builds_commands_group.py +16 -0
  122. frogml_cli/commands/models/builds/cancel/__init__.py +0 -0
  123. frogml_cli/commands/models/builds/cancel/_logic.py +5 -0
  124. frogml_cli/commands/models/builds/cancel/ui.py +15 -0
  125. frogml_cli/commands/models/builds/logs/__init__.py +0 -0
  126. frogml_cli/commands/models/builds/logs/ui.py +35 -0
  127. frogml_cli/commands/models/builds/status/__init__.py +0 -0
  128. frogml_cli/commands/models/builds/status/_logic.py +6 -0
  129. frogml_cli/commands/models/builds/status/ui.py +39 -0
  130. frogml_cli/commands/models/create/__init__.py +0 -0
  131. frogml_cli/commands/models/create/_logic.py +40 -0
  132. frogml_cli/commands/models/create/ui.py +46 -0
  133. frogml_cli/commands/models/delete/__init__.py +0 -0
  134. frogml_cli/commands/models/delete/_logic.py +18 -0
  135. frogml_cli/commands/models/delete/ui.py +25 -0
  136. frogml_cli/commands/models/deployments/__init__.py +0 -0
  137. frogml_cli/commands/models/deployments/deploy/__init__.py +0 -0
  138. frogml_cli/commands/models/deployments/deploy/_logic/__init__.py +0 -0
  139. frogml_cli/commands/models/deployments/deploy/_logic/advance_deployment_options_handler.py +31 -0
  140. frogml_cli/commands/models/deployments/deploy/_logic/base_deploy_executor.py +70 -0
  141. frogml_cli/commands/models/deployments/deploy/_logic/deploy_config.py +261 -0
  142. frogml_cli/commands/models/deployments/deploy/_logic/deployment.py +407 -0
  143. frogml_cli/commands/models/deployments/deploy/_logic/deployment_message_helpers.py +116 -0
  144. frogml_cli/commands/models/deployments/deploy/_logic/deployment_response_handler.py +156 -0
  145. frogml_cli/commands/models/deployments/deploy/_logic/deployment_size_mapper.py +98 -0
  146. frogml_cli/commands/models/deployments/deploy/_logic/get_latest_successful_build.py +28 -0
  147. frogml_cli/commands/models/deployments/deploy/_logic/local_deployment.py +193 -0
  148. frogml_cli/commands/models/deployments/deploy/batch/__init__.py +0 -0
  149. frogml_cli/commands/models/deployments/deploy/batch/_logic/__init__.py +0 -0
  150. frogml_cli/commands/models/deployments/deploy/batch/_logic/advanced_deployment_mapper.py +15 -0
  151. frogml_cli/commands/models/deployments/deploy/batch/_logic/deploy_executor.py +24 -0
  152. frogml_cli/commands/models/deployments/deploy/batch/ui.py +119 -0
  153. frogml_cli/commands/models/deployments/deploy/deploy_commands_group.py +19 -0
  154. frogml_cli/commands/models/deployments/deploy/realtime/__init__.py +0 -0
  155. frogml_cli/commands/models/deployments/deploy/realtime/_logic/__init__.py +0 -0
  156. frogml_cli/commands/models/deployments/deploy/realtime/_logic/advanced_deployment_mapper.py +21 -0
  157. frogml_cli/commands/models/deployments/deploy/realtime/_logic/deploy_executor.py +24 -0
  158. frogml_cli/commands/models/deployments/deploy/realtime/_logic/serving_strategy_mapper.py +75 -0
  159. frogml_cli/commands/models/deployments/deploy/realtime/ui.py +202 -0
  160. frogml_cli/commands/models/deployments/deploy/streaming/__init__.py +0 -0
  161. frogml_cli/commands/models/deployments/deploy/streaming/_logic/__init__.py +0 -0
  162. frogml_cli/commands/models/deployments/deploy/streaming/_logic/deploy_executor.py +24 -0
  163. frogml_cli/commands/models/deployments/deploy/streaming/_logic/serving_strategy_mapper.py +38 -0
  164. frogml_cli/commands/models/deployments/deploy/streaming/ui.py +206 -0
  165. frogml_cli/commands/models/deployments/undeploy/__init__.py +0 -0
  166. frogml_cli/commands/models/deployments/undeploy/_logic/__init__.py +0 -0
  167. frogml_cli/commands/models/deployments/undeploy/_logic/request_undeploy.py +249 -0
  168. frogml_cli/commands/models/deployments/undeploy/ui.py +61 -0
  169. frogml_cli/commands/models/describe/__init__.py +0 -0
  170. frogml_cli/commands/models/describe/_logic.py +169 -0
  171. frogml_cli/commands/models/describe/ui.py +35 -0
  172. frogml_cli/commands/models/executions/__init__.py +0 -0
  173. frogml_cli/commands/models/executions/cancel/__init__.py +0 -0
  174. frogml_cli/commands/models/executions/cancel/_logic.py +9 -0
  175. frogml_cli/commands/models/executions/cancel/ui.py +27 -0
  176. frogml_cli/commands/models/executions/execution_commands_group.py +24 -0
  177. frogml_cli/commands/models/executions/report/__init__.py +0 -0
  178. frogml_cli/commands/models/executions/report/_logic.py +14 -0
  179. frogml_cli/commands/models/executions/report/ui.py +43 -0
  180. frogml_cli/commands/models/executions/start/__init__.py +0 -0
  181. frogml_cli/commands/models/executions/start/_logic.py +83 -0
  182. frogml_cli/commands/models/executions/start/ui.py +208 -0
  183. frogml_cli/commands/models/executions/status/__init__.py +0 -0
  184. frogml_cli/commands/models/executions/status/_logic.py +13 -0
  185. frogml_cli/commands/models/executions/status/ui.py +27 -0
  186. frogml_cli/commands/models/init/__init__.py +0 -0
  187. frogml_cli/commands/models/init/_logic/__init__.py +0 -0
  188. frogml_cli/commands/models/init/_logic/initialize_model_structure.py +40 -0
  189. frogml_cli/commands/models/init/_logic/template/__init__.py +0 -0
  190. frogml_cli/commands/models/init/_logic/template/churn/__init__.py +0 -0
  191. frogml_cli/commands/models/init/_logic/template/churn/cookiecutter.json +3 -0
  192. frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/__init__.py +0 -0
  193. frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
  194. frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/conda.yml +10 -0
  195. frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
  196. frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/model.py +99 -0
  197. frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
  198. frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
  199. frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/test_churn.py +32 -0
  200. frogml_cli/commands/models/init/_logic/template/credit_risk/__init__.py +0 -0
  201. frogml_cli/commands/models/init/_logic/template/credit_risk/cookiecutter.json +3 -0
  202. frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/__init__.py +0 -0
  203. frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
  204. frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/conda.yml +11 -0
  205. frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
  206. frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/model.py +108 -0
  207. frogml_cli/commands/models/init/_logic/template/general/__init__.py +0 -0
  208. frogml_cli/commands/models/init/_logic/template/general/cookiecutter.json +6 -0
  209. frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/__init__.py +0 -0
  210. frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/__init__.py +5 -0
  211. frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/conda.yml +8 -0
  212. frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/model.py +66 -0
  213. frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/__init__.py +0 -0
  214. frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/test_qwak_model.py +5 -0
  215. frogml_cli/commands/models/init/_logic/template/titanic/__init__.py +0 -0
  216. frogml_cli/commands/models/init/_logic/template/titanic/cookiecutter.json +3 -0
  217. frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/__init__.py +0 -0
  218. frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
  219. frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/conda.yml +11 -0
  220. frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/model.py +98 -0
  221. frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
  222. frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
  223. frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +24 -0
  224. frogml_cli/commands/models/init/_logic/template/titanic_poetry/__init__.py +0 -0
  225. frogml_cli/commands/models/init/_logic/template/titanic_poetry/cookiecutter.json +3 -0
  226. frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/__init__.py +0 -0
  227. frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
  228. frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/model.py +98 -0
  229. frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/pyproject.toml +20 -0
  230. frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
  231. frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
  232. frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +25 -0
  233. frogml_cli/commands/models/init/ui.py +61 -0
  234. frogml_cli/commands/models/list/__init__.py +0 -0
  235. frogml_cli/commands/models/list/_logic.py +5 -0
  236. frogml_cli/commands/models/list/ui.py +41 -0
  237. frogml_cli/commands/models/list_models/__init__.py +0 -0
  238. frogml_cli/commands/models/list_models/_logic.py +11 -0
  239. frogml_cli/commands/models/list_models/ui.py +60 -0
  240. frogml_cli/commands/models/metadata/__init__.py +0 -0
  241. frogml_cli/commands/models/metadata/_logic.py +12 -0
  242. frogml_cli/commands/models/metadata/ui.py +60 -0
  243. frogml_cli/commands/models/models_command_group.py +44 -0
  244. frogml_cli/commands/models/runtime/__init__.py +0 -0
  245. frogml_cli/commands/models/runtime/logs/__init__.py +0 -0
  246. frogml_cli/commands/models/runtime/logs/ui.py +63 -0
  247. frogml_cli/commands/models/runtime/runtime_commands_group.py +17 -0
  248. frogml_cli/commands/models/runtime/update/__init__.py +0 -0
  249. frogml_cli/commands/models/runtime/update/_logic.py +9 -0
  250. frogml_cli/commands/models/runtime/update/ui.py +17 -0
  251. frogml_cli/commands/secrets/__init__.py +0 -0
  252. frogml_cli/commands/secrets/delete/__init__.py +0 -0
  253. frogml_cli/commands/secrets/delete/_logic.py +5 -0
  254. frogml_cli/commands/secrets/delete/ui.py +21 -0
  255. frogml_cli/commands/secrets/get/__init__.py +0 -0
  256. frogml_cli/commands/secrets/get/_logic.py +5 -0
  257. frogml_cli/commands/secrets/get/ui.py +17 -0
  258. frogml_cli/commands/secrets/secrets_commands_group.py +19 -0
  259. frogml_cli/commands/secrets/set/__init__.py +0 -0
  260. frogml_cli/commands/secrets/set/_logic.py +5 -0
  261. frogml_cli/commands/secrets/set/ui.py +16 -0
  262. frogml_cli/commands/ui_tools.py +18 -0
  263. frogml_cli/exceptions/__init__.py +14 -0
  264. frogml_cli/exceptions/frogml_command_exception.py +2 -0
  265. frogml_cli/exceptions/frogml_deploy_new_build_failed.py +5 -0
  266. frogml_cli/exceptions/frogml_resource_not_found.py +2 -0
  267. frogml_cli/inner/__init__.py +0 -0
  268. frogml_cli/inner/file_registry.py +98 -0
  269. frogml_cli/inner/tools/__init__.py +0 -0
  270. frogml_cli/inner/tools/cli_tools.py +179 -0
  271. frogml_cli/inner/tools/config_handler.py +29 -0
  272. frogml_cli/inner/tools/dataclasses_utils.py +21 -0
  273. frogml_cli/inner/tools/logger/__init__.py +3 -0
  274. frogml_cli/inner/tools/logger/logger.py +278 -0
  275. frogml_cli/inner/tools/logger/logging.yml +79 -0
  276. frogml_cli/inner/tools/tracking.py +47 -0
  277. frogml_cli/main.py +9 -0
  278. frogml_cli/tools/__init__.py +0 -0
  279. frogml_cli/tools/colors.py +13 -0
  280. frogml_cli/tools/const.py +3 -0
  281. frogml_cli/tools/files.py +63 -0
  282. frogml_cli/tools/log_handling.py +159 -0
  283. frogml_cli/tools/utils.py +45 -0
  284. frogml_cli-0.0.1.dist-info/METADATA +51 -0
  285. frogml_cli-0.0.1.dist-info/RECORD +287 -0
  286. frogml_cli-0.0.1.dist-info/WHEEL +4 -0
  287. frogml_cli-0.0.1.dist-info/entry_points.txt +3 -0
File without changes
@@ -0,0 +1,14 @@
1
+ import grpc
2
+ from frogml._proto.qwak.audience.v1.audience_pb2 import Audience
3
+ from frogml.core.clients.audience import AudienceClient
4
+
5
+ from frogml_cli.exceptions import FrogmlCommandException, FrogmlResourceNotFound
6
+
7
+
8
+ def get_audience(audience_id: str) -> Audience:
9
+ try:
10
+ return AudienceClient().get_audience(audience_id=audience_id)
11
+ except grpc.RpcError as e:
12
+ if e.args[0].code == grpc.StatusCode.NOT_FOUND:
13
+ raise FrogmlResourceNotFound(e.args[0].details)
14
+ raise FrogmlCommandException(e.args[0].details)
@@ -0,0 +1,25 @@
1
+ import click
2
+
3
+ from frogml_cli.commands.audience.audience_api_dump import (
4
+ audience_to_json,
5
+ audience_to_pretty_string,
6
+ )
7
+ from frogml_cli.commands.audience.get.logic import get_audience
8
+ from frogml_cli.exceptions import FrogmlCommandException, FrogmlResourceNotFound
9
+ from frogml_cli.inner.tools.cli_tools import FrogMLCommand
10
+
11
+
12
+ @click.command("get", cls=FrogMLCommand)
13
+ @click.option("--audience-id", type=str)
14
+ @click.option("--json-format", is_flag=True, type=bool)
15
+ def get_audience_command(audience_id: str, json_format: bool, **kwargs):
16
+ click.echo(f"Getting audience {audience_id}")
17
+ try:
18
+ audience = get_audience(audience_id)
19
+ if json_format:
20
+ click.echo(audience_to_json(audience))
21
+ else:
22
+ click.echo(audience_to_pretty_string(audience_id, audience))
23
+ except (FrogmlCommandException, FrogmlResourceNotFound) as e:
24
+ click.echo(f"Failed to get audience, Error: {e}")
25
+ exit(1)
File without changes
@@ -0,0 +1,16 @@
1
+ from typing import List
2
+
3
+ import grpc
4
+ from frogml._proto.qwak.audience.v1.audience_pb2 import AudienceEntry
5
+ from frogml.core.clients.audience import AudienceClient
6
+
7
+ from frogml_cli.exceptions import FrogmlCommandException, FrogmlResourceNotFound
8
+
9
+
10
+ def list_audience() -> List[AudienceEntry]:
11
+ try:
12
+ return AudienceClient().list_audience()
13
+ except grpc.RpcError as e:
14
+ if e.args[0].code == grpc.StatusCode.NOT_FOUND:
15
+ raise FrogmlResourceNotFound(e.args[0].details)
16
+ raise FrogmlCommandException(e.args[0].details)
@@ -0,0 +1,26 @@
1
+ import click
2
+
3
+ from frogml_cli.commands._logic.tools import list_of_messages_to_json_str
4
+ from frogml_cli.commands.audience.audience_api_dump import (
5
+ audience_entries_to_pretty_string,
6
+ )
7
+ from frogml_cli.commands.audience.list.logic import list_audience
8
+ from frogml_cli.exceptions import FrogmlCommandException, FrogmlResourceNotFound
9
+ from frogml_cli.inner.tools.cli_tools import FrogMLCommand
10
+
11
+
12
+ @click.command("list", cls=FrogMLCommand)
13
+ @click.option("--json-format", is_flag=True, type=bool)
14
+ def list_audience_command(json_format: bool, **kwargs):
15
+ try:
16
+ audience_entries = list_audience()
17
+ if json_format:
18
+ click.echo(list_of_messages_to_json_str(audience_entries))
19
+ else:
20
+ click.echo("Getting audiences")
21
+ click.echo(
22
+ audience_entries_to_pretty_string(audience_entries=audience_entries)
23
+ )
24
+ except (FrogmlCommandException, FrogmlResourceNotFound) as e:
25
+ click.echo(f"Failed to list audiences, Error: {e}")
26
+ exit(1)
File without changes
@@ -0,0 +1,37 @@
1
+ from pathlib import Path
2
+ from typing import Optional
3
+
4
+ import grpc
5
+ from frogml.core.clients.audience import AudienceClient
6
+
7
+ from frogml_cli.commands.audience._logic.config.config_base import ConfigBase
8
+ from frogml_cli.commands.audience._logic.config.parser import parse_audience_from_yaml
9
+ from frogml_cli.commands.audience._logic.config.v1.config_v1 import ConfigV1
10
+ from frogml_cli.exceptions import FrogmlCommandException, FrogmlResourceNotFound
11
+
12
+
13
+ def update_audience(
14
+ audience_id: str, name: str = "", description: str = "", file: Optional[Path] = None
15
+ ) -> None:
16
+ config = parse_audience_from_yaml(file)
17
+ config = merge_kw_yaml(config=config, name=name, description=description)
18
+ audience_api = config.to_audiences_api()[0]
19
+
20
+ try:
21
+ AudienceClient().update_audience(audience_id=audience_id, audience=audience_api)
22
+ except grpc.RpcError as e:
23
+ if e.args[0].code == grpc.StatusCode.NOT_FOUND:
24
+ raise FrogmlResourceNotFound(e.args[0].details)
25
+ raise FrogmlCommandException(e.args[0].details)
26
+
27
+
28
+ def merge_kw_yaml(
29
+ config: ConfigBase, name: str = "", description: str = ""
30
+ ) -> ConfigBase:
31
+ if isinstance(config, ConfigV1):
32
+ if name:
33
+ config.spec.audiences[0].name = name
34
+ if description:
35
+ config.spec.audiences[0].description = description
36
+
37
+ return config
@@ -0,0 +1,26 @@
1
+ from pathlib import Path
2
+
3
+ import click
4
+
5
+ from frogml_cli.commands.audience.update.logic import update_audience
6
+ from frogml_cli.exceptions import FrogmlCommandException, FrogmlResourceNotFound
7
+ from frogml_cli.inner.tools.cli_tools import FrogMLCommand
8
+
9
+
10
+ @click.command("update", cls=FrogMLCommand)
11
+ @click.option("--audience-id", type=str)
12
+ @click.option("--name", type=str)
13
+ @click.option("--description", type=str)
14
+ @click.option("-f", "--file", type=click.Path(exists=True))
15
+ def update_audience_command(
16
+ audience_id: str, name: str, description: str, file: Path, **kwargs
17
+ ):
18
+ click.echo(f"Updating audience ID {audience_id}")
19
+ try:
20
+ update_audience(
21
+ audience_id=audience_id, name=name, description=description, file=file
22
+ )
23
+ click.echo(f"Audience ID {audience_id} updated successfully")
24
+ except (FrogmlCommandException, FrogmlResourceNotFound) as e:
25
+ click.echo(f"Failed to update audience, Error: {e}")
26
+ exit(1)
File without changes
File without changes
@@ -0,0 +1,3 @@
1
+ from .config import Config
2
+
3
+ __all__ = ["Config"]
@@ -0,0 +1,152 @@
1
+ from dataclasses import dataclass, field
2
+ from enum import Enum
3
+ from typing import List
4
+
5
+ from frogml._proto.qwak.auto_scaling.v1.auto_scaling_pb2 import (
6
+ AGGREGATION_TYPE_AVERAGE,
7
+ AGGREGATION_TYPE_MAX,
8
+ AGGREGATION_TYPE_MIN,
9
+ AGGREGATION_TYPE_P50,
10
+ AGGREGATION_TYPE_P90,
11
+ AGGREGATION_TYPE_P95,
12
+ AGGREGATION_TYPE_P99,
13
+ AGGREGATION_TYPE_SUM,
14
+ METRIC_TYPE_CPU,
15
+ METRIC_TYPE_ERROR_RATE,
16
+ METRIC_TYPE_GPU,
17
+ METRIC_TYPE_LATENCY,
18
+ METRIC_TYPE_MEMORY,
19
+ METRIC_TYPE_THROUGHPUT,
20
+ AutoScalingConfig,
21
+ PrometheusTrigger,
22
+ QuerySpec,
23
+ Trigger,
24
+ Triggers,
25
+ )
26
+
27
+ from frogml_cli.exceptions import FrogmlCommandException
28
+
29
+
30
+ class MetricType(Enum):
31
+ cpu = METRIC_TYPE_CPU
32
+ gpu = METRIC_TYPE_GPU
33
+ latency = METRIC_TYPE_LATENCY
34
+ memory = METRIC_TYPE_MEMORY
35
+ throughput = METRIC_TYPE_THROUGHPUT
36
+ error_rate = METRIC_TYPE_ERROR_RATE
37
+
38
+ @classmethod
39
+ def get_metric_type(cls, metric_type: str) -> "MetricType":
40
+ """
41
+ Converts a string representation of a metric type to its corresponding `MetricType` enum.
42
+ The method performs a case-insensitive lookup. If the provided metric type does not exist
43
+ in the `MetricType` enum, a `FrogmlCommandException` is raised.
44
+
45
+ :param metric_type: The name of the metric type to retrieve.
46
+ :return: The corresponding `MetricType` enum.
47
+ :raises: FrogmlCommandException if the provided `metric_type` does not match any member
48
+ """
49
+
50
+ try:
51
+ return cls[metric_type.lower()]
52
+ except KeyError as exception:
53
+ raise FrogmlCommandException(
54
+ f"The metric type {metric_type} doesn't exist"
55
+ ) from exception
56
+
57
+
58
+ class AggregationType(Enum):
59
+ avg = AGGREGATION_TYPE_AVERAGE
60
+ max = AGGREGATION_TYPE_MAX
61
+ min = AGGREGATION_TYPE_MIN
62
+ sum = AGGREGATION_TYPE_SUM
63
+ p50 = AGGREGATION_TYPE_P50
64
+ p90 = AGGREGATION_TYPE_P90
65
+ p95 = AGGREGATION_TYPE_P95
66
+ p99 = AGGREGATION_TYPE_P99
67
+
68
+ @classmethod
69
+ def get_aggregation_type(cls, aggregation_type: str) -> "AggregationType":
70
+ """
71
+ Converts a string representation of an aggregation type to its corresponding `AggregationType` enum.
72
+ The method performs a case-insensitive lookup. If the provided aggregation type does not exist
73
+ in the `AggregationType` enum, a `FrogmlCommandException` is raised.
74
+
75
+ :param aggregation_type: The name of the aggregation type to retrieve
76
+ :return: The corresponding `AggregationType` enum.
77
+ :raises: FrogmlCommandException if the provided `aggregation_type` does not match
78
+ """
79
+ try:
80
+ return cls[aggregation_type.lower()]
81
+ except KeyError as exception:
82
+ raise FrogmlCommandException(
83
+ f"The aggregation type {aggregation_type} doesn't exist"
84
+ ) from exception
85
+
86
+
87
+ @dataclass
88
+ class AutoScaling:
89
+ @dataclass
90
+ class Triggers:
91
+ @dataclass
92
+ class PrometheusTrigger:
93
+ @dataclass
94
+ class QuerySpec:
95
+ metric_type: str = field(default=None)
96
+ aggregation_type: str = field(default=None)
97
+ time_period: int = field(default=None)
98
+ error_code: str = field(default=None)
99
+
100
+ query_spec: QuerySpec = field(default=QuerySpec)
101
+ threshold: int = field(default=None)
102
+
103
+ prometheus_trigger: List[PrometheusTrigger] = field(default_factory=list)
104
+
105
+ min_replica_count: int = field(default=None)
106
+ max_replica_count: int = field(default=None)
107
+ polling_interval: int = field(default=None)
108
+ cool_down_period: int = field(default=None)
109
+ triggers: Triggers = field(default_factory=Triggers)
110
+
111
+ def to_autoscaling_api(self) -> AutoScalingConfig:
112
+ triggers = Triggers()
113
+ for trigger in self.triggers.prometheus_trigger:
114
+ metric_type: MetricType = MetricType.get_metric_type(
115
+ trigger.query_spec.metric_type
116
+ )
117
+ aggregation_type: AggregationType = AggregationType.get_aggregation_type(
118
+ trigger.query_spec.aggregation_type
119
+ )
120
+ triggers.triggers.append(
121
+ Trigger(
122
+ prometheus_trigger=PrometheusTrigger(
123
+ query_spec=QuerySpec(
124
+ metric_type=metric_type.value,
125
+ aggregation_type=aggregation_type.value,
126
+ time_period=trigger.query_spec.time_period,
127
+ error_code=trigger.query_spec.error_code,
128
+ ),
129
+ threshold=trigger.threshold,
130
+ )
131
+ )
132
+ )
133
+ return AutoScalingConfig(
134
+ min_replica_count=self.min_replica_count,
135
+ max_replica_count=self.max_replica_count,
136
+ polling_interval=self.polling_interval,
137
+ cool_down_period=self.cool_down_period,
138
+ triggers=triggers,
139
+ )
140
+
141
+
142
+ @dataclass
143
+ class Spec:
144
+ model_id: str = field(default="")
145
+ variation_name: str = field(default="")
146
+ auto_scaling: AutoScaling = field(default=AutoScaling)
147
+
148
+
149
+ @dataclass
150
+ class Config:
151
+ spec: Spec = field(default=Spec)
152
+ api_version: str = field(default="v1")
@@ -0,0 +1,21 @@
1
+ from pathlib import Path
2
+ from typing import Optional, Union
3
+
4
+ import yaml
5
+
6
+ from frogml_cli.commands.auto_scalling._logic.config import Config
7
+ from frogml_cli.inner.tools.dataclasses_utils import create_dataclass_instance
8
+
9
+
10
+ def parse_autoscaling_from_yaml(file_path: Optional[Union[Path, str]] = None) -> Config:
11
+ if file_path:
12
+ file_obj = Path(file_path)
13
+ if file_obj.exists():
14
+ autoscaling_dict = yaml.safe_load(file_obj.open("r"))
15
+ return create_dataclass_instance(Config, autoscaling_dict)
16
+ else:
17
+ raise FileNotFoundError(
18
+ f"autoscaling file {file_obj} definition isn't found"
19
+ )
20
+ else:
21
+ return Config()
File without changes
@@ -0,0 +1,43 @@
1
+ from typing import Dict
2
+
3
+ import grpc
4
+ from frogml.core.clients.autoscaling import AutoScalingClient
5
+
6
+ from frogml_cli.commands.auto_scalling._logic.config import Config
7
+ from frogml_cli.commands.auto_scalling._logic.config.parser import (
8
+ parse_autoscaling_from_yaml,
9
+ )
10
+ from frogml_cli.exceptions import FrogmlCommandException
11
+
12
+
13
+ def attach_autoscaling(model_id: str, variation_name: str, file: str) -> Dict[str, str]:
14
+ try:
15
+ config = parse_autoscaling_from_yaml(file)
16
+ config = merge_kw_yaml(
17
+ config=config, model_id=model_id, variation_name=variation_name
18
+ )
19
+ response = AutoScalingClient().attach_autoscaling(
20
+ model_id=config.spec.model_id,
21
+ variation_name=config.spec.variation_name,
22
+ auto_scaling_config=config.spec.auto_scaling.to_autoscaling_api(),
23
+ )
24
+ return {
25
+ "autoscaling_id": response.auto_scaling_id,
26
+ "model_id": config.spec.model_id,
27
+ "variation_name": config.spec.variation_name,
28
+ }
29
+ except grpc.RpcError as e:
30
+ raise FrogmlCommandException(e.args[0].details)
31
+
32
+
33
+ def merge_kw_yaml(
34
+ config: Config,
35
+ model_id: str = "",
36
+ variation_name: str = "",
37
+ ) -> Config:
38
+ if model_id:
39
+ config.spec.model_id = model_id
40
+ if variation_name:
41
+ config.spec.variation_name = variation_name
42
+
43
+ return config
@@ -0,0 +1,21 @@
1
+ import click
2
+
3
+ from frogml_cli.commands.auto_scalling.attach._logic import attach_autoscaling
4
+ from frogml_cli.exceptions import FrogmlCommandException
5
+ from frogml_cli.inner.tools.cli_tools import FrogMLCommand
6
+
7
+
8
+ @click.command("attach", cls=FrogMLCommand)
9
+ @click.option("-m", "--model-id", required=False, help="Model named ID")
10
+ @click.option("-v", "--variation-name", required=False, help="Model variation name")
11
+ @click.option("-f", "--file", required=True, type=click.Path(exists=True))
12
+ def attach(model_id: str, variation_name: str, file: str, **kwargs):
13
+ click.echo("Attaching autoscaling configuration")
14
+ try:
15
+ response = attach_autoscaling(model_id, variation_name, file)
16
+ click.echo(
17
+ f"Successfully configured autoscaling. model: {response['model_id']}, variation: {response['variation_name']}"
18
+ )
19
+ except FrogmlCommandException as e:
20
+ click.echo(f"Failed to attach autoscaling, Error: {e}")
21
+ exit(1)
@@ -0,0 +1,15 @@
1
+ import click
2
+
3
+ from frogml_cli.commands.auto_scalling.attach.ui import attach
4
+
5
+
6
+ @click.group(
7
+ name="autoscaling",
8
+ help="Manage autoscaling",
9
+ )
10
+ def autoscaling_commands_group():
11
+ # Click commands group injection
12
+ pass
13
+
14
+
15
+ autoscaling_commands_group.add_command(attach)
File without changes
@@ -0,0 +1,30 @@
1
+ import logging
2
+
3
+ import click
4
+
5
+ from frogml_cli.commands.automations.delete.ui import delete
6
+ from frogml_cli.commands.automations.executions.executions_commands_group import (
7
+ executions_command_group,
8
+ )
9
+ from frogml_cli.commands.automations.list.ui import list_automations
10
+ from frogml_cli.commands.automations.register.ui import register
11
+
12
+ logger = logging.getLogger(__name__)
13
+ DELIMITER = "----------------------------------------"
14
+
15
+ AUTOMATION = "automation"
16
+
17
+
18
+ @click.group(
19
+ name="automations",
20
+ help="Commands for interacting with the Qwak Automations",
21
+ )
22
+ def automations_commands_group():
23
+ # Click commands group injection
24
+ pass
25
+
26
+
27
+ automations_commands_group.add_command(delete)
28
+ automations_commands_group.add_command(list_automations)
29
+ automations_commands_group.add_command(register)
30
+ automations_commands_group.add_command(executions_command_group)
File without changes
@@ -0,0 +1,6 @@
1
+ from frogml.core.clients.automation_management.client import AutomationsManagementClient
2
+
3
+
4
+ def delete_automation(automation_id: str):
5
+ client = AutomationsManagementClient()
6
+ return client.delete_automation(automation_id=automation_id)
@@ -0,0 +1,23 @@
1
+ import click
2
+
3
+ from frogml_cli.commands.automations.delete._logic import delete_automation
4
+ from frogml_cli.inner.tools.cli_tools import FrogMLCommand
5
+
6
+
7
+ @click.command(
8
+ "delete",
9
+ help="Delete an automation object",
10
+ cls=FrogMLCommand,
11
+ )
12
+ @click.option(
13
+ "--automation-id",
14
+ type=str,
15
+ metavar="ID",
16
+ help="The automation id to delete",
17
+ )
18
+ def delete(automation_id: str, **kwargs):
19
+ deleted = delete_automation(automation_id=automation_id)
20
+ if deleted:
21
+ print(f"Automation {automation_id} deleted successfully")
22
+ else:
23
+ print(f"Automation {automation_id} was not found")
File without changes
@@ -0,0 +1,14 @@
1
+ import click
2
+
3
+ from frogml_cli.commands.automations.executions.list.ui import list_executions
4
+
5
+ DELIMITER = "----------------------------------------"
6
+
7
+
8
+ @click.group(name="executions", help=" automation executions")
9
+ def executions_command_group():
10
+ # Click commands group injection
11
+ pass
12
+
13
+
14
+ executions_command_group.add_command(list_executions)
@@ -0,0 +1,8 @@
1
+ from typing import List
2
+
3
+ from frogml.core.automations.automation_executions import AutomationExecution
4
+ from frogml.core.clients.automation_management.client import AutomationsManagementClient
5
+
6
+
7
+ def execute_list_executions(automation_id: str) -> List[AutomationExecution]:
8
+ return AutomationsManagementClient().list_executions(automation_id)
@@ -0,0 +1,27 @@
1
+ import click
2
+
3
+ from frogml_cli.commands.automations.executions.list._logic import (
4
+ execute_list_executions,
5
+ )
6
+ from frogml_cli.inner.tools.cli_tools import FrogMLCommand
7
+
8
+ DELIMITER = "----------------------------------------"
9
+
10
+
11
+ @click.command(
12
+ "list",
13
+ help="List all executions for a specific automation",
14
+ cls=FrogMLCommand,
15
+ )
16
+ @click.option(
17
+ "--automation-id",
18
+ type=str,
19
+ metavar="ID",
20
+ required=True,
21
+ help="The automation id to list its executions",
22
+ )
23
+ def list_executions(automation_id: str, **kwargs):
24
+ executions_list = execute_list_executions(automation_id)
25
+ for execution in executions_list:
26
+ print(execution)
27
+ print(DELIMITER)
File without changes
@@ -0,0 +1,36 @@
1
+ from frogml.core.clients.automation_management.client import AutomationsManagementClient
2
+ from tabulate import tabulate
3
+
4
+ from frogml_cli.commands._logic.tools import list_of_messages_to_json_str
5
+
6
+ COLUMNS = ["Id", "Name", "Model id", "Type", "Status", "Last updated", "Updated by"]
7
+
8
+
9
+ def execute_list_automations():
10
+ client = AutomationsManagementClient()
11
+ automations_list = client.list_automations()
12
+ data = []
13
+ for automation in automations_list:
14
+ data.append(
15
+ [
16
+ automation.id,
17
+ automation.name,
18
+ automation.model_id,
19
+ automation.action.__class__.__name__,
20
+ _map_automation_status(automation.is_enabled),
21
+ automation.create_audit.date,
22
+ automation.create_audit.user_id,
23
+ ]
24
+ )
25
+
26
+ return tabulate(data, headers=COLUMNS)
27
+
28
+
29
+ def execute_list_json_automations() -> str:
30
+ client = AutomationsManagementClient()
31
+ automations = client.get_list_automations_from_server()
32
+ return list_of_messages_to_json_str(automations)
33
+
34
+
35
+ def _map_automation_status(status: bool) -> str:
36
+ return "Active" if status else "Inactive"
@@ -0,0 +1,21 @@
1
+ import click
2
+
3
+ from frogml_cli.commands.automations.list._logic import (
4
+ execute_list_automations,
5
+ execute_list_json_automations,
6
+ )
7
+ from frogml_cli.inner.tools.cli_tools import FrogMLCommand
8
+
9
+
10
+ @click.command(
11
+ "list",
12
+ help="List all automations",
13
+ cls=FrogMLCommand,
14
+ )
15
+ @click.option("--json-format", is_flag=True, type=bool)
16
+ def list_automations(json_format: bool, **kwargs):
17
+ if json_format:
18
+ click.echo(execute_list_json_automations())
19
+
20
+ else:
21
+ click.echo(execute_list_automations())
File without changes
@@ -0,0 +1,43 @@
1
+ from typing import List
2
+
3
+ from frogml.core.automations import Automation
4
+ from frogml.core.clients.automation_management.client import AutomationsManagementClient
5
+
6
+ from frogml_cli.inner.file_registry import extract_class_objects
7
+ from frogml_cli.inner.tools.cli_tools import ask_yesno
8
+ from frogml_cli.tools.utils import frogml_spinner
9
+
10
+ DELIMITER = "----------------------------------------"
11
+
12
+
13
+ def register_automations(qwak_python_files: List[str], force: bool):
14
+ """
15
+ Register Automation Entities Objects
16
+
17
+ Args:
18
+ qwak_python_files: a list of python files containing qwak package imports
19
+ force: to force
20
+ """
21
+ with frogml_spinner(
22
+ begin_text="Finding Automations to register", print_callback=print
23
+ ):
24
+ qwak_automations: List[Automation] = extract_class_objects(
25
+ qwak_python_files, Automation
26
+ )
27
+ client = AutomationsManagementClient()
28
+ print(f"Found {len(qwak_automations)} Automations")
29
+ for automation, source_file_path in qwak_automations:
30
+ existing_automation = client.get_automation_by_name(automation.name)
31
+ if existing_automation:
32
+ if ask_yesno(
33
+ f"Update existing Automation '{automation.name}' from source file '{source_file_path}'?",
34
+ force,
35
+ ):
36
+ client.update_automation(existing_automation.id, automation.to_proto())
37
+ else:
38
+ if ask_yesno(
39
+ f"Create new Automation '{automation.name}' from source file '{source_file_path}'?",
40
+ force,
41
+ ):
42
+ client.create_automation(automation.to_proto())
43
+ print(DELIMITER)