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
@@ -0,0 +1,179 @@
1
+ import functools
2
+ import time
3
+ import warnings
4
+ from collections import namedtuple
5
+ from typing import Any, Callable, Dict, List, Tuple, Union
6
+
7
+ import click
8
+ from click import Context, OptionParser
9
+ from frogml.core.exceptions import FrogmlException
10
+ from frogml.core.inner.di_configuration import UserAccountConfiguration
11
+
12
+ from frogml_cli.inner.tools.tracking import log_event
13
+
14
+
15
+ def get_user_identifiers(account: UserAccountConfiguration):
16
+ try:
17
+ user_id = account.get_user_config().token
18
+ identifier_cls = namedtuple("Identifier", ["user_id"])
19
+ return identifier_cls(user_id)
20
+
21
+ except FrogmlException:
22
+ # User might not be registered or have a valid API key
23
+ return None
24
+
25
+
26
+ def usage_statistics_wrapper(func: Callable):
27
+ @functools.wraps(func)
28
+ def wrapper(*args, **kwargs):
29
+ ctx = click.get_current_context()
30
+ start_time = time.time()
31
+
32
+ account = UserAccountConfiguration()
33
+ user_identifiers = get_user_identifiers(account)
34
+
35
+ # If we could not get user identifiers for some reason (for example - user not logged in) - do not track
36
+ if not user_identifiers:
37
+ return func(*args, **kwargs)
38
+
39
+ event_properties = {
40
+ "command_group": ctx.command_path,
41
+ "commands": ctx.command.name,
42
+ "duration": time.time() - start_time,
43
+ }
44
+ try:
45
+ return_value = func(*args, **kwargs)
46
+
47
+ event_properties["response"] = return_value
48
+ event_properties["status"] = 0
49
+ log_event(
50
+ event_properties,
51
+ user_id=user_identifiers.user_id,
52
+ )
53
+
54
+ return return_value
55
+
56
+ except BaseException as e:
57
+ command_status = 1
58
+ if type(e) == KeyboardInterrupt:
59
+ command_status = 1
60
+
61
+ event_properties["error_type"] = type(e).__name__
62
+ event_properties["error_message"] = str(e)
63
+ event_properties["status"] = command_status
64
+
65
+ log_event(
66
+ event_properties,
67
+ user_id=user_identifiers.user_id,
68
+ )
69
+ raise
70
+
71
+ return wrapper
72
+
73
+
74
+ class DeprecatedOption(click.Option):
75
+ def __init__(self, *args, **kwargs):
76
+ self.deprecated = kwargs.pop("deprecated", ())
77
+ self.preferred = kwargs.pop("preferred", args[0][-1])
78
+ super(DeprecatedOption, self).__init__(*args, **kwargs)
79
+
80
+
81
+ class FrogMLCommand(click.Command):
82
+ def __init__(self, *args, **kwargs):
83
+ super().__init__(*args, **kwargs)
84
+
85
+ def make_parser(self, ctx: Context) -> OptionParser:
86
+ parser = super(FrogMLCommand, self).make_parser(ctx)
87
+
88
+ # get the parser options
89
+ options = set(parser._short_opt.values())
90
+ options |= set(parser._long_opt.values())
91
+
92
+ for option in options:
93
+ if not isinstance(option.obj, DeprecatedOption):
94
+ continue
95
+
96
+ def make_process(an_option):
97
+ """Construct a closure to the parser option processor"""
98
+
99
+ orig_process = an_option.process
100
+ deprecated = getattr(an_option.obj, "deprecated", None)
101
+ preferred = getattr(an_option.obj, "preferred", None)
102
+
103
+ if not deprecated:
104
+ f"Expected `deprecated` value for `{an_option.obj.name}`"
105
+
106
+ def process(value, state):
107
+ """The function above us on the stack used 'opt' to
108
+ pick option from a dict, see if it is deprecated"""
109
+
110
+ # reach up the stack and get 'opt'
111
+ import inspect
112
+
113
+ frame = inspect.currentframe()
114
+ try:
115
+ opt = frame.f_back.f_locals.get("opt")
116
+ finally:
117
+ del frame
118
+
119
+ if opt in deprecated:
120
+ warnings.warn(
121
+ f"{opt} has been deprecated, use {preferred}."
122
+ f" {opt} will be removed in future releases.",
123
+ DeprecationWarning,
124
+ )
125
+
126
+ return orig_process(value, state)
127
+
128
+ return process
129
+
130
+ option.process = make_process(option)
131
+
132
+ return parser
133
+
134
+ @usage_statistics_wrapper
135
+ def invoke(self, ctx: click.Context) -> Any:
136
+ return super().invoke(ctx)
137
+
138
+
139
+ def ask_yesno(
140
+ question: str, force: bool, print_callback: Callable[[str], None] = print
141
+ ) -> bool:
142
+ """
143
+ Helper to get yes / no answer from user.
144
+
145
+ Args:
146
+ question: yes/no question to show the user
147
+ force: automatically returns True if force is True
148
+ print_callback: function to use for printing
149
+
150
+ Returns:
151
+ True/False by user input (unless forced and then always True)
152
+ """
153
+
154
+ print_callback(f"{question}")
155
+ if force:
156
+ print_callback("Forced yes")
157
+ return True
158
+ return click.confirm("continue?")
159
+
160
+
161
+ def dictify_params(env_vars: Union[Dict[str, str], List[str], Tuple[str]]):
162
+ result = dict()
163
+
164
+ if env_vars is None:
165
+ return result
166
+
167
+ if isinstance(env_vars, dict):
168
+ return env_vars
169
+
170
+ if isinstance(env_vars, (list, tuple)):
171
+ for env_var in env_vars:
172
+ if "=" not in env_var:
173
+ raise FrogmlException(
174
+ f'The environment variable definition passed {env_var} is invalid. Format is "KEY=VALUE"'
175
+ )
176
+ split_param = env_var.split("=")
177
+ result[split_param[0]] = split_param[1]
178
+
179
+ return result
@@ -0,0 +1,29 @@
1
+ from typing import Any, Tuple, Union
2
+
3
+ from frogml.core.clients.build_orchestrator import BuildOrchestratorClient
4
+ from frogml.core.clients.instance_template.client import (
5
+ InstanceTemplateManagementClient,
6
+ )
7
+ from frogml.core.inner.build_config.build_config_v1 import BuildConfigV1
8
+ from frogml.core.inner.tool.run_config import FrogmlConfigBase, YamlConfigMixin
9
+
10
+
11
+ def config_handler(
12
+ config: Union[FrogmlConfigBase, YamlConfigMixin, Any],
13
+ from_file: str,
14
+ out_conf: bool,
15
+ sections: Tuple[str, ...] = (),
16
+ **kwargs,
17
+ ) -> Any:
18
+ conf: Union[FrogmlConfigBase, YamlConfigMixin] = config.from_yaml(from_file)
19
+ conf.merge_cli_argument(sections=sections, **kwargs)
20
+
21
+ if isinstance(conf, BuildConfigV1):
22
+ conf.fetch_base_docker_image_name(
23
+ BuildOrchestratorClient(), InstanceTemplateManagementClient()
24
+ )
25
+
26
+ if out_conf:
27
+ print(conf.to_yaml())
28
+
29
+ return conf
@@ -0,0 +1,21 @@
1
+ import dataclasses
2
+ from typing import Any, Dict, List, Type, Union
3
+
4
+
5
+ def create_dataclass_instance(dataclass_type: Type, input_dict: Dict[str, Any]) -> Any:
6
+ fields = {f.name: f.type for f in dataclasses.fields(dataclass_type)}
7
+
8
+ def construct_dataclass(
9
+ dc_type: Union[Type, List], value: Any
10
+ ) -> Union[Type, List]:
11
+ if dataclasses.is_dataclass(dc_type):
12
+ return create_dataclass_instance(dc_type, value)
13
+ elif getattr(dc_type, "__origin__", None) is list: # This is a List
14
+ element_type = dc_type.__args__[0]
15
+ return [construct_dataclass(element_type, v) for v in value]
16
+ else:
17
+ return value
18
+
19
+ return dataclass_type(
20
+ **{k: construct_dataclass(fields[k], v) for k, v in input_dict.items()}
21
+ )
@@ -0,0 +1,3 @@
1
+ from .logger import setup_frogml_logger
2
+
3
+ __all__ = ["setup_frogml_logger"]
@@ -0,0 +1,278 @@
1
+ import logging
2
+ import logging.config
3
+ import os
4
+ from logging.handlers import RotatingFileHandler
5
+ from pathlib import Path
6
+ from typing import Optional
7
+
8
+ import yaml
9
+ from frogml.core.exceptions import FrogmlException
10
+
11
+ DEFAULT_LOGGER_NAME = "frogml"
12
+ REMOTE_LOGGER_NAME = "frogml_remote"
13
+ MODEL_LOGGER_NAME = "frogml_model"
14
+ FEATURE_STORE_LOGGER_NAME = "feature_store"
15
+ BUILD_LOCAL_LOGGER_NAME = "build_local"
16
+ DOCKER_INTERNAL_LOGGER_NAME = "docker_internal"
17
+
18
+ ENVIRON_LOGGER_TYPE = "LOGGER_TYPE"
19
+
20
+ BUILD_LOCAL_FILE_HANDLER_NAME = "build_log_file_handler"
21
+ FILE_HANDLER_NAME = "file_handler"
22
+ CONSOLE_HANDLER_NAME = "console"
23
+ REMOTE_CONSOLE_HANDLER_NAME = "remote_console"
24
+
25
+ DEFINED_LOGGER_NAMES = {
26
+ DEFAULT_LOGGER_NAME,
27
+ REMOTE_LOGGER_NAME,
28
+ MODEL_LOGGER_NAME,
29
+ FEATURE_STORE_LOGGER_NAME,
30
+ BUILD_LOCAL_LOGGER_NAME,
31
+ DOCKER_INTERNAL_LOGGER_NAME,
32
+ }
33
+
34
+ VERBOSITY_LEVEL_MAPPING = {0: logging.CRITICAL, 1: logging.INFO, 2: logging.DEBUG}
35
+ REVERSED_VERBOSITY_LEVEL_MAPPING = {
36
+ value: key for key, value in VERBOSITY_LEVEL_MAPPING.items()
37
+ }
38
+
39
+ AIRFLOW_ENV_FLAG = "AIRFLOW__LOGGING__REMOTE_LOGGING"
40
+
41
+
42
+ def setup_frogml_logger(
43
+ default_level: int = logging.INFO,
44
+ logger_name_handler_addition: str = None,
45
+ disable_existing_loggers: bool = False,
46
+ ):
47
+ """Setup frogml logger:
48
+ 1. Rotating file in $HOME/.frogml/log/sdk.log (10MB * 5 files) (DEBUG level)
49
+ 2. Stdout logger with colored logs. (INFO level)
50
+
51
+ Args:
52
+ default_level: Default logging level in case of failure
53
+ logger_name_handler_addition:
54
+ Logger name which the handlers of will be appended to all loggers which have handlers
55
+ Overriding stdout stream handler if exists
56
+ disable_existing_loggers: disables all existing loggers
57
+
58
+ Raises:
59
+ FrogmlException: If loading logging.yml fails or the preparation of the logging environment raises an exceptions
60
+
61
+ Notes:
62
+ 1. https://docs.python.org/3/library/logging.html#logging-levels
63
+ """
64
+
65
+ config_file = Path(__file__).parent / "logging.yml"
66
+ if config_file.exists() and not non_frogml_logger_enabled():
67
+ with config_file.open(mode="rt") as f:
68
+ try:
69
+ # Creating log directory
70
+ log_path = Path(__get_config_folder())
71
+ log_path.mkdir(parents=True, exist_ok=True)
72
+ # Load logger configuration
73
+ config = yaml.safe_load(f.read())
74
+ config["handlers"][FILE_HANDLER_NAME]["filename"] = str(
75
+ log_path / "sdk.log"
76
+ )
77
+ config["handlers"][BUILD_LOCAL_FILE_HANDLER_NAME]["filename"] = str(
78
+ log_path / "sdk.log"
79
+ )
80
+ config["disable_existing_loggers"] = disable_existing_loggers
81
+
82
+ logging.config.dictConfig(config)
83
+
84
+ if logger_name_handler_addition:
85
+ if (
86
+ logger_name_handler_addition
87
+ in logging.Logger.manager.loggerDict
88
+ ):
89
+ _add_logger_handlers(logger_name_handler_addition)
90
+ else:
91
+ print(
92
+ "Tried to set orphan loggers handlers with a non-existing logger name handlers'"
93
+ )
94
+
95
+ except Exception as e:
96
+ raise FrogmlException(
97
+ f"Error in Logging Configuration. Error message: {e}"
98
+ )
99
+ else:
100
+ logging.basicConfig(level=default_level)
101
+ print("Failed to load configuration file. Using default configs")
102
+
103
+
104
+ def __get_config_folder() -> str:
105
+ frogml_home_dir: str = (
106
+ os.getenv("FROGML_HOME")
107
+ if os.getenv("FROGML_HOME") is not None
108
+ else f"{str(Path.home())}"
109
+ )
110
+
111
+ return f"{frogml_home_dir}/.frogml"
112
+
113
+
114
+ def _add_logger_handlers(logger_name):
115
+ """
116
+ Add a specific logger handlers to all loggers
117
+ Override loggers StreamHandler handlers if the input logger has a StreamHandler
118
+
119
+ Args:
120
+ logger_name: logger name which consists of the handlers we wish to set
121
+ """
122
+
123
+ logger_handlers = logging.getLogger(logger_name).handlers
124
+ base_contains_stdout = any(
125
+ [
126
+ handler
127
+ for handler in logger_handlers
128
+ if type(handler) is logging.StreamHandler
129
+ ]
130
+ )
131
+
132
+ for logger in [
133
+ logger
134
+ for logger in logging.Logger.manager.loggerDict.values()
135
+ if not isinstance(logger, logging.PlaceHolder)
136
+ ]:
137
+ if logger.handlers:
138
+ logger.handlers = [
139
+ handler
140
+ for handler in logger.handlers
141
+ if base_contains_stdout and type(handler) is not logging.StreamHandler
142
+ ] + logger_handlers
143
+
144
+
145
+ def get_frogml_logger(
146
+ logger_name: Optional[str] = None, fallback_logger_name: Optional[str] = None
147
+ ) -> logging.Logger:
148
+ """Get frogml logger (Singleton)
149
+
150
+ Returns:
151
+ logging.Logger: Frogml logger.
152
+ """
153
+ if not logger_name:
154
+ logger_name = get_frogml_logger_name(fallback_logger_name)
155
+
156
+ if (logger_name not in DEFINED_LOGGER_NAMES) and not non_frogml_logger_enabled:
157
+ print("Failed to get requested logger name. Using default logger")
158
+
159
+ return logging.getLogger(logger_name)
160
+
161
+
162
+ def set_frogml_logger_stdout_verbosity_level(verbose: int, format: str = "text"):
163
+ """Set frogml stdout to verbose (a.k.a DEBUG level)
164
+
165
+ Args:
166
+ verbose: Log verbosity level - 0: WARNING, 1:INFO, 2: DEBUG
167
+
168
+ Notes:
169
+ 1. https://docs.python.org/3/library/logging.html#logging-levels
170
+ """
171
+ if format == "json":
172
+ verbose = 0
173
+ logger: logging.Logger = get_frogml_logger()
174
+ logger.setLevel(VERBOSITY_LEVEL_MAPPING[verbose])
175
+ for handler in logger.handlers:
176
+ if isinstance(handler, logging.StreamHandler):
177
+ handler.setLevel(VERBOSITY_LEVEL_MAPPING[verbose])
178
+
179
+
180
+ def get_frogml_logger_verbosity_level() -> Optional[int]:
181
+ """Get current Frogml logger level.
182
+
183
+ Returns:
184
+ int: Frogml logger level 10 < level < 50.
185
+
186
+ Notes:
187
+ 1. https://docs.python.org/3/library/logging.html#logging-levels
188
+ 2. when we update the log level through set_frogml_logger_stdout_verbosity_level we update all handler levels
189
+ thus returning the first stream handler should be correct
190
+ """
191
+
192
+ logger: logging.Logger = get_frogml_logger()
193
+
194
+ for handler in logger.handlers:
195
+ if isinstance(handler, logging.StreamHandler):
196
+ return logging.getLevelName(handler.level)
197
+
198
+
199
+ def set_frogml_logger_propagate(prop: bool):
200
+ """Set frogml logger propagation
201
+
202
+ Args:
203
+ prop: True if propagate else False
204
+
205
+ """
206
+ get_frogml_logger().propagate = prop
207
+
208
+
209
+ def translate_to_frogml_verbosity_level(loglevel: int) -> Optional[int]:
210
+ """Get frogml equivalent of the logging verbosity levels
211
+
212
+ Args:
213
+ loglevel: logging log level int
214
+ """
215
+ return REVERSED_VERBOSITY_LEVEL_MAPPING.get(loglevel, None)
216
+
217
+
218
+ def get_frogml_logger_name(fallback_logger_name: Optional[str] = None):
219
+ if fallback_logger_name:
220
+ return os.getenv(ENVIRON_LOGGER_TYPE, fallback_logger_name)
221
+ else:
222
+ return os.getenv(ENVIRON_LOGGER_TYPE, DEFAULT_LOGGER_NAME)
223
+
224
+
225
+ def get_handler_from_logger(
226
+ logger: logging.Logger, handler_name: str
227
+ ) -> logging.Handler:
228
+ matching_handlers = list(
229
+ filter(lambda h: h.get_name() == handler_name, logger.handlers)
230
+ )
231
+ if len(matching_handlers) == 0 and not non_frogml_logger_enabled:
232
+ raise FrogmlException(
233
+ f"Error in setting log file. Error message: handler of name {handler_name} was not found in logger"
234
+ )
235
+ elif len(matching_handlers) > 1:
236
+ raise FrogmlException(
237
+ f"Error in setting log file. Error message: handler of name {handler_name} was found more than once "
238
+ f"in logger"
239
+ )
240
+
241
+ return matching_handlers[0]
242
+
243
+
244
+ def set_file_handler_log_file(
245
+ logger: logging.Logger, handler_name: str, log_file: Path
246
+ ):
247
+ existing_handler = get_handler_from_logger(logger, handler_name)
248
+ if type(existing_handler) != RotatingFileHandler:
249
+ raise FrogmlException(
250
+ f"Error in setting log file. Error message: handler of name {handler_name} is not a file logger handler"
251
+ )
252
+ replacement_handler: RotatingFileHandler = copy_file_handler_from_existing(
253
+ existing_handler, log_file
254
+ )
255
+ logger.removeHandler(existing_handler)
256
+ logger.addHandler(replacement_handler)
257
+
258
+
259
+ def copy_file_handler_from_existing(
260
+ handler: RotatingFileHandler, log_file: Path
261
+ ) -> RotatingFileHandler:
262
+ return RotatingFileHandler(
263
+ log_file,
264
+ mode=handler.mode,
265
+ maxBytes=int(handler.maxBytes),
266
+ backupCount=int(handler.backupCount),
267
+ encoding=handler.encoding,
268
+ delay=handler.delay,
269
+ )
270
+
271
+
272
+ def set_handler_verbosity(logger: logging.Logger, handler_name: str, log_level: int):
273
+ handler = get_handler_from_logger(logger, handler_name)
274
+ handler.setLevel(log_level)
275
+
276
+
277
+ def non_frogml_logger_enabled():
278
+ return os.getenv(AIRFLOW_ENV_FLAG) is not None
@@ -0,0 +1,79 @@
1
+ version: 1
2
+ disable_existing_loggers: false
3
+
4
+ formatters:
5
+ brief:
6
+ format: '%(message)s'
7
+ semi_precise:
8
+ format: "%(asctime)s [%(levelname)-5.5s] %(message)s"
9
+ datefmt: '%Y-%m-%d %H:%M:%S'
10
+ precise:
11
+ format: '%(asctime)s %(levelname)-8s %(module)s - %(lineno)d - %(message)s'
12
+ datefmt: '%Y-%m-%d %H:%M:%S'
13
+ remote:
14
+ class: pythonjsonlogger.json.JsonFormatter
15
+ format: '%(asctime)s %(process)d %(levelname)s %(module)s %(lineno)d %(message)s'
16
+ datefmt: '%Y-%m-%dT%H:%M:%S'
17
+ json:
18
+ class: pythonjsonlogger.json.JsonFormatter
19
+ format: '%(asctime)s %(process)d %(levelname)s %(module)s %(lineno)d %(message)s'
20
+ datefmt: '%Y-%m-%dT%H:%M:%S'
21
+
22
+ handlers:
23
+ console:
24
+ class : logging.StreamHandler
25
+ formatter: brief
26
+ level : INFO
27
+ stream : ext://sys.stdout
28
+ file_handler:
29
+ class: logging.handlers.RotatingFileHandler
30
+ level: DEBUG
31
+ formatter: precise
32
+ filename: ""
33
+ maxBytes: 10485760 # 10MB
34
+ backupCount: 5
35
+ encoding: utf8
36
+ remote_console:
37
+ class: logging.StreamHandler
38
+ formatter: remote
39
+ level: DEBUG
40
+ stream: ext://sys.stdout
41
+ model:
42
+ class: logging.StreamHandler
43
+ formatter: json
44
+ level: INFO
45
+ stream: ext://sys.stdout
46
+ build_log_file_handler:
47
+ class: logging.handlers.RotatingFileHandler
48
+ level: DEBUG
49
+ formatter: semi_precise
50
+ filename: ""
51
+ maxBytes: 10485760 # 10MB
52
+ backupCount: 5
53
+ encoding: utf8
54
+
55
+ loggers:
56
+ frogml:
57
+ level: DEBUG
58
+ handlers: [console, file_handler]
59
+ propagate: false
60
+ frogml_remote:
61
+ level: DEBUG
62
+ handlers: [remote_console]
63
+ propagate: false
64
+ frogml_model:
65
+ level: DEBUG
66
+ handlers: [model]
67
+ propagate: false
68
+ feature_store:
69
+ level: DEBUG
70
+ handlers: [model]
71
+ propagate: false
72
+ build_local:
73
+ level: DEBUG
74
+ handlers: [build_log_file_handler, console]
75
+ propagate: false
76
+ docker_internal:
77
+ level: DEBUG
78
+ handlers: [console]
79
+ propagate: false
@@ -0,0 +1,47 @@
1
+ import logging
2
+ import platform
3
+ import sys
4
+
5
+ import requests
6
+
7
+ from frogml_cli import __version__ as cli_version
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ def _amplitude_url():
13
+ return "https://api2.amplitude.com/2/httpapi"
14
+
15
+
16
+ def _platform_info():
17
+ return platform.platform()
18
+
19
+
20
+ def _python_version():
21
+ return "{major}.{minor}.{micro}".format(
22
+ major=sys.version_info.major,
23
+ minor=sys.version_info.minor,
24
+ micro=sys.version_info.micro,
25
+ )
26
+
27
+
28
+ def log_event(properties, user_id):
29
+ properties["sdk_version"] = cli_version
30
+ properties["python_version"] = _python_version()
31
+ properties["platform_info"] = _platform_info()
32
+
33
+ event = [
34
+ {
35
+ "event_type": "sdk-event",
36
+ "user_id": user_id,
37
+ "event_properties": properties,
38
+ "ip": "$remote",
39
+ }
40
+ ]
41
+
42
+ event_data = {"events": event}
43
+
44
+ try:
45
+ return requests.post(_amplitude_url(), json=event_data, timeout=1)
46
+ except Exception as e:
47
+ logger.debug(str(e))
frogml_cli/main.py ADDED
@@ -0,0 +1,9 @@
1
+ from frogml_cli.cli import create_frogml_cli
2
+
3
+
4
+ def frogml_cli():
5
+ return create_frogml_cli()()
6
+
7
+
8
+ if __name__ == "__main__":
9
+ frogml_cli()()
File without changes
@@ -0,0 +1,13 @@
1
+ class Color:
2
+ PURPLE = "\033[95m"
3
+ CYAN = "\033[96m"
4
+ WHITE = "\033[97m"
5
+ GREY = "\033[98m"
6
+ DARKCYAN = "\033[36m"
7
+ BLUE = "\033[94m"
8
+ GREEN = "\033[92m"
9
+ YELLOW = "\033[93m"
10
+ RED = "\033[91m"
11
+ BOLD = "\033[1m"
12
+ UNDERLINE = "\033[4m"
13
+ END = "\033[0m"
@@ -0,0 +1,3 @@
1
+ from frogml._proto.qwak.batch_job.v1.batch_job_resources_pb2 import GpuType
2
+
3
+ GPU_TYPES = list(set(GpuType.DESCRIPTOR.values_by_name) - {"INVALID_GPU"})