qwak-sdk 0.1.0__py3-none-any.whl → 0.2.20rc0__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.
Potentially problematic release.
This version of qwak-sdk might be problematic. Click here for more details.
- qwak_sdk/__init__.py +9 -0
- qwak_sdk/cli.py +51 -0
- qwak_sdk/commands/admin/__init__.py +0 -0
- qwak_sdk/commands/admin/admin_commands_group.py +17 -0
- qwak_sdk/commands/admin/apikeys/__init__.py +0 -0
- qwak_sdk/commands/admin/apikeys/api_keys_commands_group.py +17 -0
- qwak_sdk/commands/admin/apikeys/generate/__init__.py +0 -0
- qwak_sdk/commands/admin/apikeys/generate/_logic.py +21 -0
- qwak_sdk/commands/admin/apikeys/generate/ui.py +45 -0
- qwak_sdk/commands/admin/apikeys/revoke/__init__.py +0 -0
- qwak_sdk/commands/admin/apikeys/revoke/_logic.py +22 -0
- qwak_sdk/commands/admin/apikeys/revoke/ui.py +31 -0
- qwak_sdk/commands/audience/__init__.py +0 -0
- qwak_sdk/commands/audience/_logic/__init__.py +0 -0
- qwak_sdk/commands/audience/_logic/config/__init__.py +0 -0
- qwak_sdk/commands/audience/_logic/config/config_base.py +16 -0
- qwak_sdk/commands/audience/_logic/config/parser.py +28 -0
- qwak_sdk/commands/audience/_logic/config/v1/__init__.py +0 -0
- qwak_sdk/commands/audience/_logic/config/v1/audience_config.py +26 -0
- qwak_sdk/commands/audience/_logic/config/v1/conditions_config.py +60 -0
- qwak_sdk/commands/audience/_logic/config/v1/config_v1.py +24 -0
- qwak_sdk/commands/audience/_logic/config/v1/route_config.py +14 -0
- qwak_sdk/commands/audience/_logic/config/v1/spec.py +11 -0
- qwak_sdk/commands/auto_scalling/__init__.py +0 -0
- qwak_sdk/commands/auto_scalling/_logic/__init__.py +0 -0
- qwak_sdk/commands/auto_scalling/_logic/config/__init__.py +3 -0
- qwak_sdk/commands/auto_scalling/_logic/config/config.py +100 -0
- qwak_sdk/commands/auto_scalling/_logic/config/parser.py +21 -0
- qwak_sdk/commands/auto_scalling/attach/__init__.py +0 -0
- qwak_sdk/commands/auto_scalling/attach/_logic.py +43 -0
- qwak_sdk/commands/auto_scalling/attach/ui.py +21 -0
- qwak_sdk/commands/auto_scalling/autoscaling_commands_group.py +15 -0
- qwak_sdk/commands/automations/__init__.py +0 -0
- qwak_sdk/commands/automations/automations_commands_group.py +30 -0
- qwak_sdk/commands/automations/delete/__init__.py +0 -0
- qwak_sdk/commands/automations/delete/_logic.py +6 -0
- qwak_sdk/commands/automations/delete/ui.py +23 -0
- qwak_sdk/commands/automations/executions/__init__.py +0 -0
- qwak_sdk/commands/automations/executions/executions_commands_group.py +14 -0
- qwak_sdk/commands/automations/executions/list/__init__.py +0 -0
- qwak_sdk/commands/automations/executions/list/_logic.py +8 -0
- qwak_sdk/commands/automations/executions/list/ui.py +25 -0
- qwak_sdk/commands/automations/list/__init__.py +0 -0
- qwak_sdk/commands/automations/list/_logic.py +8 -0
- qwak_sdk/commands/automations/list/ui.py +21 -0
- qwak_sdk/commands/automations/register/__init__.py +0 -0
- qwak_sdk/commands/automations/register/_logic.py +43 -0
- qwak_sdk/commands/automations/register/ui.py +44 -0
- qwak_sdk/commands/feature_store/__init__.py +0 -0
- qwak_sdk/commands/feature_store/delete/__init__.py +0 -0
- qwak_sdk/commands/feature_store/delete/_logic.py +52 -0
- qwak_sdk/commands/feature_store/delete/ui.py +40 -0
- qwak_sdk/commands/feature_store/feature_store_command_group.py +25 -0
- qwak_sdk/commands/feature_store/list/__init__.py +0 -0
- qwak_sdk/commands/feature_store/list/ui.py +140 -0
- qwak_sdk/commands/feature_store/pause/__init__.py +0 -0
- qwak_sdk/commands/feature_store/pause/ui.py +18 -0
- qwak_sdk/commands/feature_store/register/__init__.py +0 -0
- qwak_sdk/commands/feature_store/register/_logic.py +289 -0
- qwak_sdk/commands/feature_store/register/ui.py +105 -0
- qwak_sdk/commands/feature_store/resume/__init__.py +0 -0
- qwak_sdk/commands/feature_store/resume/ui.py +18 -0
- qwak_sdk/commands/feature_store/trigger/__init__.py +0 -0
- qwak_sdk/commands/feature_store/trigger/ui.py +32 -0
- qwak_sdk/commands/models/__init__.py +0 -0
- qwak_sdk/commands/models/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/_logic/variations.py +55 -0
- qwak_sdk/commands/models/build/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/build_steps.py +68 -0
- qwak_sdk/commands/models/build/_logic/client_logs/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/client_logs/build_run_handlers.py +189 -0
- qwak_sdk/commands/models/build/_logic/client_logs/cli_ui.py +125 -0
- qwak_sdk/commands/models/build/_logic/client_logs/logger.py +88 -0
- qwak_sdk/commands/models/build/_logic/client_logs/messages.py +40 -0
- qwak_sdk/commands/models/build/_logic/client_logs/notifier_impl.py +49 -0
- qwak_sdk/commands/models/build/_logic/client_logs/spinner.py +14 -0
- qwak_sdk/commands/models/build/_logic/client_logs/time_source.py +37 -0
- qwak_sdk/commands/models/build/_logic/client_logs/utils.py +12 -0
- qwak_sdk/commands/models/build/_logic/config/config_v1.py +253 -0
- qwak_sdk/commands/models/build/_logic/constant/host_resource.py +4 -0
- qwak_sdk/commands/models/build/_logic/constant/step_description.py +29 -0
- qwak_sdk/commands/models/build/_logic/constant/temp_dir.py +2 -0
- qwak_sdk/commands/models/build/_logic/constant/upload_tag.py +5 -0
- qwak_sdk/commands/models/build/_logic/context.py +62 -0
- qwak_sdk/commands/models/build/_logic/interface/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/interface/notifier_interface.py +29 -0
- qwak_sdk/commands/models/build/_logic/interface/step_inteface.py +29 -0
- qwak_sdk/commands/models/build/_logic/phase/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/__init__.py +14 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_model_step.py +42 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/common.py +33 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/fetch_strategy_manager.py +60 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/folder/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/folder/folder_strategy.py +73 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/git/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/git/git_strategy.py +149 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/strategy.py +69 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/zip/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/zip/zip_strategy.py +64 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/post_fetch_validation_step.py +117 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/pre_fetch_validation_step.py +135 -0
- qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/__init__.py +11 -0
- qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/cleanup_step.py +20 -0
- qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/start_remote_build_step.py +42 -0
- qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/upload_step.py +349 -0
- qwak_sdk/commands/models/build/_logic/phase/c_deploy/__init__.py +6 -0
- qwak_sdk/commands/models/build/_logic/phase/c_deploy/build_polling_status.py +54 -0
- qwak_sdk/commands/models/build/_logic/phase/c_deploy/deploy_build.py +44 -0
- qwak_sdk/commands/models/build/_logic/util/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/util/protobuf_factory.py +45 -0
- qwak_sdk/commands/models/build/_logic/util/step_decorator.py +37 -0
- qwak_sdk/commands/models/build/_logic/util/text.py +9 -0
- qwak_sdk/commands/models/build/ui.py +241 -0
- qwak_sdk/commands/models/builds/__init__.py +0 -0
- qwak_sdk/commands/models/builds/builds_commands_group.py +16 -0
- qwak_sdk/commands/models/builds/cancel/__init__.py +0 -0
- qwak_sdk/commands/models/builds/cancel/_logic.py +5 -0
- qwak_sdk/commands/models/builds/cancel/ui.py +15 -0
- qwak_sdk/commands/models/builds/logs/__init__.py +0 -0
- qwak_sdk/commands/models/builds/logs/ui.py +35 -0
- qwak_sdk/commands/models/builds/status/__init__.py +0 -0
- qwak_sdk/commands/models/builds/status/_logic.py +6 -0
- qwak_sdk/commands/models/builds/status/ui.py +30 -0
- qwak_sdk/commands/models/create/__init__.py +0 -0
- qwak_sdk/commands/models/create/_logic.py +35 -0
- qwak_sdk/commands/models/create/ui.py +27 -0
- qwak_sdk/commands/models/delete/__init__.py +0 -0
- qwak_sdk/commands/models/delete/_logic.py +5 -0
- qwak_sdk/commands/models/delete/ui.py +16 -0
- qwak_sdk/commands/models/deployments/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/advance_deployment_options_handler.py +31 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/base_deploy_executor.py +64 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deploy_config.py +241 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment.py +405 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_message_helpers.py +98 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_response_handler.py +154 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_size_mapper.py +21 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/get_latest_successful_build.py +31 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/variations.py +79 -0
- qwak_sdk/commands/models/deployments/deploy/batch/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/batch/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/batch/_logic/advanced_deployment_mapper.py +14 -0
- qwak_sdk/commands/models/deployments/deploy/batch/_logic/deploy_executor.py +24 -0
- qwak_sdk/commands/models/deployments/deploy/batch/ui.py +104 -0
- qwak_sdk/commands/models/deployments/deploy/deploy_commands_group.py +19 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/advanced_deployment_mapper.py +20 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/deploy_executor.py +24 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/serving_strategy_mapper.py +105 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/ui.py +179 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/_logic/deploy_executor.py +24 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/_logic/serving_strategy_mapper.py +38 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/ui.py +196 -0
- qwak_sdk/commands/models/deployments/undeploy/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/undeploy/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/undeploy/_logic/request_undeploy.py +176 -0
- qwak_sdk/commands/models/deployments/undeploy/_logic/variations.py +74 -0
- qwak_sdk/commands/models/deployments/undeploy/ui.py +78 -0
- qwak_sdk/commands/models/executions/__init__.py +0 -0
- qwak_sdk/commands/models/executions/cancel/__init__.py +0 -0
- qwak_sdk/commands/models/executions/cancel/_logic.py +9 -0
- qwak_sdk/commands/models/executions/cancel/ui.py +27 -0
- qwak_sdk/commands/models/executions/execution_commands_group.py +24 -0
- qwak_sdk/commands/models/executions/report/__init__.py +0 -0
- qwak_sdk/commands/models/executions/report/_logic.py +14 -0
- qwak_sdk/commands/models/executions/report/ui.py +43 -0
- qwak_sdk/commands/models/executions/start/__init__.py +0 -0
- qwak_sdk/commands/models/executions/start/_logic.py +16 -0
- qwak_sdk/commands/models/executions/start/ui.py +176 -0
- qwak_sdk/commands/models/executions/status/__init__.py +0 -0
- qwak_sdk/commands/models/executions/status/_logic.py +13 -0
- qwak_sdk/commands/models/executions/status/ui.py +27 -0
- qwak_sdk/commands/models/init/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/initialize_model_structure.py +40 -0
- qwak_sdk/commands/models/init/_logic/template/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/cookiecutter.json +3 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/conda.yml +10 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/model.py +95 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/test_churn.py +32 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/cookiecutter.json +3 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/conda.yml +10 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/model.py +108 -0
- qwak_sdk/commands/models/init/_logic/template/general/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/general/cookiecutter.json +6 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/conda.yml +8 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/model.py +66 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/test_qwak_model.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/cookiecutter.json +3 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/conda.yml +10 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/model.py +98 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +24 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/cookiecutter.json +3 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/model.py +98 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/pyproject.toml +18 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +25 -0
- qwak_sdk/commands/models/init/ui.py +61 -0
- qwak_sdk/commands/models/list/__init__.py +0 -0
- qwak_sdk/commands/models/list/_logic.py +5 -0
- qwak_sdk/commands/models/list/ui.py +31 -0
- qwak_sdk/commands/models/models_command_group.py +36 -0
- qwak_sdk/commands/models/runtime/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/feedback/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/feedback/_logic.py +81 -0
- qwak_sdk/commands/models/runtime/feedback/ui.py +45 -0
- qwak_sdk/commands/models/runtime/logs/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/logs/ui.py +63 -0
- qwak_sdk/commands/models/runtime/runtime_commands_group.py +21 -0
- qwak_sdk/commands/models/runtime/traffic_update/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/traffic_update/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/traffic_update/_logic/execute_runtime_update_traffic.py +54 -0
- qwak_sdk/commands/models/runtime/traffic_update/_logic/variations.py +84 -0
- qwak_sdk/commands/models/runtime/traffic_update/ui.py +37 -0
- qwak_sdk/commands/models/runtime/update/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/update/_logic.py +9 -0
- qwak_sdk/commands/models/runtime/update/ui.py +15 -0
- qwak_sdk/commands/projects/__init__.py +0 -0
- qwak_sdk/commands/projects/create/__init__.py +0 -0
- qwak_sdk/commands/projects/create/_logic.py +6 -0
- qwak_sdk/commands/projects/create/ui.py +21 -0
- qwak_sdk/commands/projects/delete/__init__.py +0 -0
- qwak_sdk/commands/projects/delete/_logic.py +6 -0
- qwak_sdk/commands/projects/delete/ui.py +15 -0
- qwak_sdk/commands/projects/list/__init__.py +0 -0
- qwak_sdk/commands/projects/list/_logic.py +6 -0
- qwak_sdk/commands/projects/list/ui.py +36 -0
- qwak_sdk/commands/projects/projects_command_group.py +19 -0
- qwak_sdk/commands/secrets/__init__.py +0 -0
- qwak_sdk/commands/secrets/delete/__init__.py +0 -0
- qwak_sdk/commands/secrets/delete/_logic.py +5 -0
- qwak_sdk/commands/secrets/delete/ui.py +21 -0
- qwak_sdk/commands/secrets/get/__init__.py +0 -0
- qwak_sdk/commands/secrets/get/_logic.py +5 -0
- qwak_sdk/commands/secrets/get/ui.py +17 -0
- qwak_sdk/commands/secrets/secrets_commands_group.py +19 -0
- qwak_sdk/commands/secrets/set/__init__.py +0 -0
- qwak_sdk/commands/secrets/set/_logic.py +5 -0
- qwak_sdk/commands/secrets/set/ui.py +16 -0
- qwak_sdk/commands/ui_tools.py +18 -0
- qwak_sdk/common/__init__.py +0 -0
- qwak_sdk/common/run_config/__init__.py +22 -0
- qwak_sdk/common/run_config/base.py +101 -0
- qwak_sdk/common/run_config/utils.py +249 -0
- qwak_sdk/exceptions/__init__.py +11 -0
- qwak_sdk/exceptions/qwak_command_exception.py +2 -0
- qwak_sdk/exceptions/qwak_deploy_new_build_failed.py +5 -0
- qwak_sdk/exceptions/qwak_general_build_exception.py +13 -0
- qwak_sdk/exceptions/qwak_remote_build_failed.py +5 -0
- qwak_sdk/exceptions/qwak_resource_not_found.py +2 -0
- qwak_sdk/exceptions/qwak_suggestion_exception.py +27 -0
- qwak_sdk/inner/__init__.py +0 -0
- qwak_sdk/inner/file_registry.py +97 -0
- qwak_sdk/inner/tools/__init__.py +0 -0
- qwak_sdk/inner/tools/cli_tools.py +159 -0
- qwak_sdk/inner/tools/config_handler.py +18 -0
- qwak_sdk/inner/tools/logger/__init__.py +3 -0
- qwak_sdk/inner/tools/logger/logger.py +269 -0
- qwak_sdk/inner/tools/logger/logging.yml +79 -0
- qwak_sdk/inner/tools/tracking.py +47 -0
- qwak_sdk/main.py +9 -0
- qwak_sdk/tools/__init__.py +0 -0
- qwak_sdk/tools/colors.py +13 -0
- qwak_sdk/tools/files.py +9 -0
- qwak_sdk/tools/log_handling.py +146 -0
- qwak_sdk/tools/utils.py +46 -0
- qwak_sdk-0.2.20rc0.dist-info/METADATA +42 -0
- qwak_sdk-0.2.20rc0.dist-info/RECORD +302 -0
- {qwak_sdk-0.1.0.dist-info → qwak_sdk-0.2.20rc0.dist-info}/WHEEL +1 -2
- qwak_sdk-0.2.20rc0.dist-info/entry_points.txt +3 -0
- qwak_sdk-0.1.0.dist-info/METADATA +0 -19
- qwak_sdk-0.1.0.dist-info/RECORD +0 -5
- qwak_sdk-0.1.0.dist-info/top_level.txt +0 -1
- {qwak-sdk → qwak_sdk/commands}/__init__.py +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from qwak.exceptions import QwakException
|
|
6
|
+
from yaspin.core import Yaspin
|
|
7
|
+
|
|
8
|
+
from qwak_sdk.tools.colors import Color
|
|
9
|
+
|
|
10
|
+
from .messages import (
|
|
11
|
+
FAILED_CONTACT_QWAK_SUPPORT,
|
|
12
|
+
FAILED_CONTACT_QWAK_SUPPORT_PROGRAMMATIC,
|
|
13
|
+
)
|
|
14
|
+
from .utils import zip_logs
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BuildRunHandler(ABC):
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def handle_phase_in_progress(self, phase_id: str):
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def handle_phase_finished_successfully(
|
|
24
|
+
self, phase_id: str, duration_in_seconds: int
|
|
25
|
+
):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def handle_contact_support_error(
|
|
30
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
31
|
+
):
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def handle_remote_build_error(
|
|
36
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
37
|
+
):
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def handle_keyboard_interrupt(
|
|
42
|
+
self, build_id: str, phase_id: str, duration_in_seconds: int
|
|
43
|
+
):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def handle_pipeline_exception(
|
|
48
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
49
|
+
):
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def handle_pipeline_quiet_exception(
|
|
54
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
55
|
+
):
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
def build_phase_to_human_readable_string(self, phase_id: str):
|
|
59
|
+
return phase_id[len("BuildPhase.") :].replace("_", " ").capitalize()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class CLIBuildRunner(BuildRunHandler):
|
|
63
|
+
def __init__(self, sp: Yaspin, log_path: Path):
|
|
64
|
+
self.sp = sp
|
|
65
|
+
self.log_path = str(log_path)
|
|
66
|
+
|
|
67
|
+
def handle_phase_in_progress(self, phase_id: str):
|
|
68
|
+
logging.debug(
|
|
69
|
+
f"Build phase in progress: {self.build_phase_to_human_readable_string(phase_id)}"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def handle_phase_finished_successfully(
|
|
73
|
+
self, phase_id: str, duration_in_seconds: int
|
|
74
|
+
):
|
|
75
|
+
if self.sp:
|
|
76
|
+
self.sp.ok("✅")
|
|
77
|
+
|
|
78
|
+
logging.debug(
|
|
79
|
+
f"Phase successfully finished: {self.build_phase_to_human_readable_string(phase_id)} after {duration_in_seconds} seconds"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def __report_failure(self, phase_id: str, duration_in_seconds: int):
|
|
83
|
+
logging.debug(
|
|
84
|
+
f"Build phase failed: {self.build_phase_to_human_readable_string(phase_id)} after {duration_in_seconds} seconds"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def handle_contact_support_error(
|
|
88
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
89
|
+
):
|
|
90
|
+
print(f"\n{ex}")
|
|
91
|
+
print(
|
|
92
|
+
FAILED_CONTACT_QWAK_SUPPORT.format(
|
|
93
|
+
build_id=build_id,
|
|
94
|
+
log_file=Path(self.log_path).parent / build_id,
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
zip_logs(log_path=self.log_path, build_id=build_id)
|
|
98
|
+
self.__report_failure(phase_id, duration_in_seconds)
|
|
99
|
+
exit(1)
|
|
100
|
+
|
|
101
|
+
def handle_remote_build_error(
|
|
102
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
103
|
+
):
|
|
104
|
+
if self.sp:
|
|
105
|
+
self.sp.fail("💥")
|
|
106
|
+
print(f"\n{Color.RED}{ex}")
|
|
107
|
+
else:
|
|
108
|
+
print(f"\n{ex}")
|
|
109
|
+
self.__report_failure(phase_id, duration_in_seconds)
|
|
110
|
+
exit(1)
|
|
111
|
+
|
|
112
|
+
def handle_keyboard_interrupt(
|
|
113
|
+
self, build_id: str, phase_id: str, duration_in_seconds: int
|
|
114
|
+
):
|
|
115
|
+
print(f"\n{Color.RED}Stopping Qwak build (ctrl-c)")
|
|
116
|
+
zip_logs(log_path=self.log_path, build_id=build_id)
|
|
117
|
+
self.__report_failure(phase_id, duration_in_seconds)
|
|
118
|
+
exit(1)
|
|
119
|
+
|
|
120
|
+
def handle_pipeline_exception(
|
|
121
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
122
|
+
):
|
|
123
|
+
if self.sp:
|
|
124
|
+
self.sp.fail("💥")
|
|
125
|
+
print(f"\n{Color.RED}{ex}")
|
|
126
|
+
zip_logs(
|
|
127
|
+
log_path=self.log_path,
|
|
128
|
+
build_id=build_id,
|
|
129
|
+
)
|
|
130
|
+
self.__report_failure(phase_id, duration_in_seconds)
|
|
131
|
+
exit(1)
|
|
132
|
+
|
|
133
|
+
def handle_pipeline_quiet_exception(
|
|
134
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
135
|
+
):
|
|
136
|
+
if self.sp:
|
|
137
|
+
self.sp.ok("‼️")
|
|
138
|
+
self.__report_failure(phase_id, duration_in_seconds)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class ProgrammaticBuildRunner(BuildRunHandler):
|
|
142
|
+
def handle_phase_in_progress(self, phase_id: str):
|
|
143
|
+
logging.debug(
|
|
144
|
+
f"Build phase in progress: {self.build_phase_to_human_readable_string(phase_id)}"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
def handle_phase_finished_successfully(
|
|
148
|
+
self, phase_id: str, duration_in_seconds: int
|
|
149
|
+
):
|
|
150
|
+
logging.debug(
|
|
151
|
+
f"Phase successfully finished: {self.build_phase_to_human_readable_string(phase_id)} after {duration_in_seconds} seconds"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def __report_failure(self, phase_id: str, duration_in_seconds: int):
|
|
155
|
+
logging.debug(
|
|
156
|
+
f"Build phase failed: {self.build_phase_to_human_readable_string(phase_id)} after {duration_in_seconds} seconds"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def handle_contact_support_error(
|
|
160
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
161
|
+
):
|
|
162
|
+
print(
|
|
163
|
+
FAILED_CONTACT_QWAK_SUPPORT_PROGRAMMATIC.format(
|
|
164
|
+
build_id=build_id,
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
self.__report_failure(phase_id, duration_in_seconds)
|
|
168
|
+
raise QwakException(str(ex))
|
|
169
|
+
|
|
170
|
+
def handle_keyboard_interrupt(
|
|
171
|
+
self, build_id: str, phase_id: str, duration_in_seconds: int
|
|
172
|
+
):
|
|
173
|
+
self.__report_failure(phase_id, duration_in_seconds)
|
|
174
|
+
|
|
175
|
+
def handle_pipeline_exception(
|
|
176
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
177
|
+
):
|
|
178
|
+
self.__report_failure(phase_id, duration_in_seconds)
|
|
179
|
+
raise QwakException(str(ex))
|
|
180
|
+
|
|
181
|
+
def handle_pipeline_quiet_exception(
|
|
182
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
183
|
+
):
|
|
184
|
+
self.__report_failure(phase_id, duration_in_seconds)
|
|
185
|
+
|
|
186
|
+
def handle_remote_build_error(
|
|
187
|
+
self, build_id: str, phase_id: str, ex: BaseException, duration_in_seconds: int
|
|
188
|
+
):
|
|
189
|
+
self.handle_pipeline_exception(build_id, phase_id, ex, duration_in_seconds)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
from typing import Tuple
|
|
2
|
+
|
|
3
|
+
from qwak.exceptions import QuietError
|
|
4
|
+
|
|
5
|
+
from qwak_sdk.commands.models.build._logic.context import Context
|
|
6
|
+
from qwak_sdk.exceptions import QwakGeneralBuildException
|
|
7
|
+
from qwak_sdk.exceptions.qwak_remote_build_failed import QwakRemoteBuildFailedException
|
|
8
|
+
|
|
9
|
+
from ..build_steps import StepsPipeline, remote_build_steps
|
|
10
|
+
from ..config.config_v1 import ConfigV1
|
|
11
|
+
from ..interface.notifier_interface import Notifier
|
|
12
|
+
from .build_run_handlers import BuildRunHandler, CLIBuildRunner, ProgrammaticBuildRunner
|
|
13
|
+
from .logger import build_logger
|
|
14
|
+
from .messages import SUCCESS_MSG_REMOTE, SUCCESS_MSG_REMOTE_WITH_DEPLOY
|
|
15
|
+
from .notifier_impl import NotifierImpl
|
|
16
|
+
from .spinner import spinner
|
|
17
|
+
from .time_source import Stopwatch, SystemClockTimeSource, TimeSource
|
|
18
|
+
from .utils import zip_logs
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def execute_build_pipeline(
|
|
22
|
+
config: ConfigV1,
|
|
23
|
+
json_logs: bool,
|
|
24
|
+
programmatic: bool = False,
|
|
25
|
+
):
|
|
26
|
+
with build_logger(config=config, json_logs=json_logs) as (
|
|
27
|
+
logger,
|
|
28
|
+
log_path,
|
|
29
|
+
):
|
|
30
|
+
pipeline, success_msg = create_pipeline(config)
|
|
31
|
+
|
|
32
|
+
time_source = SystemClockTimeSource()
|
|
33
|
+
for phase in pipeline.phases:
|
|
34
|
+
phase_details = phase.get_phase_details()
|
|
35
|
+
notifier = NotifierImpl(
|
|
36
|
+
logger,
|
|
37
|
+
prefix="" if json_logs else phase_details.get_description(),
|
|
38
|
+
phase_details=phase_details,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
if programmatic:
|
|
42
|
+
build_runner = ProgrammaticBuildRunner()
|
|
43
|
+
phase_run(phase, pipeline.context, build_runner, notifier, time_source)
|
|
44
|
+
else:
|
|
45
|
+
with spinner(
|
|
46
|
+
text=phase_details.get_description(),
|
|
47
|
+
show=(config.verbose == 0 and not json_logs),
|
|
48
|
+
) as sp:
|
|
49
|
+
notifier.set_spinner(sp)
|
|
50
|
+
build_runner = CLIBuildRunner(sp, log_path)
|
|
51
|
+
phase_run(
|
|
52
|
+
phase, pipeline.context, build_runner, notifier, time_source
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
print(
|
|
56
|
+
success_msg.format(
|
|
57
|
+
build_id=pipeline.context.build_id,
|
|
58
|
+
model_id=pipeline.context.model_id,
|
|
59
|
+
project_uuid=pipeline.context.project_uuid,
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
zip_logs(log_path=log_path, build_id=pipeline.context.build_id)
|
|
63
|
+
|
|
64
|
+
return pipeline.context.build_id
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def phase_run(
|
|
68
|
+
phase: StepsPipeline,
|
|
69
|
+
context: Context,
|
|
70
|
+
build_runner: BuildRunHandler,
|
|
71
|
+
notifier: Notifier,
|
|
72
|
+
time_source: TimeSource,
|
|
73
|
+
):
|
|
74
|
+
build_id = context.build_id
|
|
75
|
+
current_step_phase = None
|
|
76
|
+
stop_watch = Stopwatch(time_source)
|
|
77
|
+
try:
|
|
78
|
+
for step in phase.steps:
|
|
79
|
+
current_step_phase = str(step.build_phase)
|
|
80
|
+
step.set_notifier(notifier)
|
|
81
|
+
build_runner.handle_phase_in_progress(current_step_phase)
|
|
82
|
+
|
|
83
|
+
step.execute()
|
|
84
|
+
|
|
85
|
+
phase_duration = stop_watch.elapsed_time_in_seconds()
|
|
86
|
+
build_runner.handle_phase_finished_successfully(
|
|
87
|
+
current_step_phase, phase_duration
|
|
88
|
+
)
|
|
89
|
+
except QwakGeneralBuildException as e:
|
|
90
|
+
phase_duration = stop_watch.elapsed_time_in_seconds()
|
|
91
|
+
build_runner.handle_contact_support_error(
|
|
92
|
+
build_id, current_step_phase, e, phase_duration
|
|
93
|
+
)
|
|
94
|
+
except QwakRemoteBuildFailedException as e:
|
|
95
|
+
phase_duration = stop_watch.elapsed_time_in_seconds()
|
|
96
|
+
build_runner.handle_remote_build_error(
|
|
97
|
+
build_id, current_step_phase, e, phase_duration
|
|
98
|
+
)
|
|
99
|
+
except KeyboardInterrupt:
|
|
100
|
+
phase_duration = stop_watch.elapsed_time_in_seconds()
|
|
101
|
+
build_runner.handle_keyboard_interrupt(
|
|
102
|
+
build_id, current_step_phase, phase_duration
|
|
103
|
+
)
|
|
104
|
+
except BaseException as e:
|
|
105
|
+
notifier.exception("Failed", e)
|
|
106
|
+
phase_duration = stop_watch.elapsed_time_in_seconds()
|
|
107
|
+
if not isinstance(e, QuietError):
|
|
108
|
+
build_runner.handle_pipeline_exception(
|
|
109
|
+
build_id, current_step_phase, e, phase_duration
|
|
110
|
+
)
|
|
111
|
+
else:
|
|
112
|
+
build_runner.handle_pipeline_quiet_exception(
|
|
113
|
+
build_id, current_step_phase, e, phase_duration
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def create_pipeline(
|
|
118
|
+
config: ConfigV1,
|
|
119
|
+
) -> Tuple[StepsPipeline, str]:
|
|
120
|
+
success_message = (
|
|
121
|
+
SUCCESS_MSG_REMOTE_WITH_DEPLOY if config.deploy else SUCCESS_MSG_REMOTE
|
|
122
|
+
)
|
|
123
|
+
pipeline = remote_build_steps(config)
|
|
124
|
+
|
|
125
|
+
return pipeline, success_message
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import shutil
|
|
6
|
+
import sys
|
|
7
|
+
import uuid
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from qwak_sdk import __version__ as qwak_sdk_version
|
|
11
|
+
from qwak_sdk.commands.models.build._logic.config.config_v1 import ConfigV1
|
|
12
|
+
from qwak_sdk.commands.models.build._logic.constant.host_resource import (
|
|
13
|
+
HOST_QWAK_HIDDEN_FOLDER,
|
|
14
|
+
)
|
|
15
|
+
from qwak_sdk.inner.tools.logger import setup_qwak_logger
|
|
16
|
+
from qwak_sdk.inner.tools.logger.logger import (
|
|
17
|
+
BUILD_LOCAL_FILE_HANDLER_NAME,
|
|
18
|
+
BUILD_LOCAL_LOGGER_NAME,
|
|
19
|
+
CONSOLE_HANDLER_NAME,
|
|
20
|
+
REMOTE_CONSOLE_HANDLER_NAME,
|
|
21
|
+
REMOTE_LOGGER_NAME,
|
|
22
|
+
VERBOSITY_LEVEL_MAPPING,
|
|
23
|
+
get_qwak_logger,
|
|
24
|
+
non_qwak_logger_enabled,
|
|
25
|
+
set_file_handler_log_file,
|
|
26
|
+
set_handler_verbosity,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
BUILDS_LOGS = HOST_QWAK_HIDDEN_FOLDER / "logs" / "build"
|
|
30
|
+
BUILD_LOG_NAME = "build.log"
|
|
31
|
+
MAX_LOGS_NUMBER = 15
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@contextlib.contextmanager
|
|
35
|
+
def build_logger(config: ConfigV1, json_logs: bool):
|
|
36
|
+
log_path = BUILDS_LOGS / config.build_properties.model_id / str(uuid.uuid4())[:4]
|
|
37
|
+
log_path.mkdir(parents=True, exist_ok=True)
|
|
38
|
+
try:
|
|
39
|
+
(log_path / "build_config.yml").write_text(config.to_yaml())
|
|
40
|
+
log_system_information(log_path)
|
|
41
|
+
|
|
42
|
+
log_file = log_path / BUILD_LOG_NAME
|
|
43
|
+
setup_qwak_logger()
|
|
44
|
+
yield setup_logger(
|
|
45
|
+
log_file=log_file, verbosity_level=config.verbose, json_logs=json_logs
|
|
46
|
+
), log_path
|
|
47
|
+
finally:
|
|
48
|
+
# Cleanup - Save only x last zips
|
|
49
|
+
logs_zip_sorted_by_data = sorted(
|
|
50
|
+
BUILDS_LOGS.rglob("**/*"), key=os.path.getmtime
|
|
51
|
+
)[:-MAX_LOGS_NUMBER]
|
|
52
|
+
path: Path
|
|
53
|
+
for path in logs_zip_sorted_by_data:
|
|
54
|
+
if path.is_file():
|
|
55
|
+
os.remove(path)
|
|
56
|
+
elif path.is_dir():
|
|
57
|
+
shutil.rmtree(path, ignore_errors=True)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def setup_logger(
|
|
61
|
+
log_file: Path, verbosity_level: int, json_logs: bool
|
|
62
|
+
) -> logging.Logger:
|
|
63
|
+
# Init logger
|
|
64
|
+
fallback_logger_name = (
|
|
65
|
+
BUILD_LOCAL_LOGGER_NAME if not json_logs else REMOTE_LOGGER_NAME
|
|
66
|
+
)
|
|
67
|
+
logger = get_qwak_logger(fallback_logger_name=fallback_logger_name)
|
|
68
|
+
|
|
69
|
+
if not non_qwak_logger_enabled():
|
|
70
|
+
if logger.name == BUILD_LOCAL_LOGGER_NAME:
|
|
71
|
+
set_file_handler_log_file(logger, BUILD_LOCAL_FILE_HANDLER_NAME, log_file)
|
|
72
|
+
set_handler_verbosity(
|
|
73
|
+
logger, CONSOLE_HANDLER_NAME, VERBOSITY_LEVEL_MAPPING[verbosity_level]
|
|
74
|
+
)
|
|
75
|
+
elif logger.name == REMOTE_LOGGER_NAME and json_logs:
|
|
76
|
+
set_handler_verbosity(
|
|
77
|
+
logger,
|
|
78
|
+
REMOTE_CONSOLE_HANDLER_NAME,
|
|
79
|
+
VERBOSITY_LEVEL_MAPPING[verbosity_level],
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return logger
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def log_system_information(destination: Path):
|
|
86
|
+
(destination / "python_version").write_text(sys.version)
|
|
87
|
+
(destination / "qwak_sdk_version").write_text(qwak_sdk_version)
|
|
88
|
+
(destination / "os_detail").write_text(platform.platform())
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
BUILD_LOGS_URL = (
|
|
2
|
+
"https://app.qwak.ai/projects/{project_uuid}/{model_id}/build/{build_id}"
|
|
3
|
+
)
|
|
4
|
+
|
|
5
|
+
SUCCESS_MSG_REMOTE = """
|
|
6
|
+
Build ID \033[4m{build_id}\033[0m triggered remotely
|
|
7
|
+
|
|
8
|
+
########### To follow build logs using CLI
|
|
9
|
+
qwak models builds logs -b {build_id} --follow
|
|
10
|
+
|
|
11
|
+
########### To follow build logs using Qwak platform
|
|
12
|
+
https://app.qwak.ai/projects/{project_uuid}/{model_id}/build/{build_id}
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
SUCCESS_MSG_REMOTE_WITH_DEPLOY = """
|
|
16
|
+
Build ID \033[4m{build_id}\033[0m finished successfully and deployed
|
|
17
|
+
|
|
18
|
+
########### To view the model using Qwak platform
|
|
19
|
+
https://app.qwak.ai/projects/{project_uuid}/{model_id}
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
FAILED_CONTACT_QWAK_SUPPORT = """
|
|
23
|
+
Build ID \033[4m{build_id}\033[0m failed!!
|
|
24
|
+
You can share the logs from \033[4m{log_file}.zip\033[0m with Qwak support.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
FAILED_CONTACT_QWAK_SUPPORT_PROGRAMMATIC = """
|
|
28
|
+
Build ID \033[4m{build_id}\033[0m failed!!
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
FAILED_REMOTE_BUILD_SUGGESTION = """
|
|
32
|
+
Your build failed. You can check the reason for the failure in the Qwak Platform:
|
|
33
|
+
https://app.qwak.ai/projects/{project_uuid}/{model_id}/build/{build_id}
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
FAILED_DEPLOY_BUILD_SUGGESTION = """
|
|
37
|
+
Deploying the build Failed. You can check the reason for the failure in the Qwak Platform:
|
|
38
|
+
https://app.qwak.ai/projects/{project_uuid}/{model_id}?tabId=1
|
|
39
|
+
Since the build finished successfully, you can try and redeploy it either from the platform or from the CLI
|
|
40
|
+
"""
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from logging import Logger
|
|
3
|
+
|
|
4
|
+
from yaspin.core import Yaspin
|
|
5
|
+
|
|
6
|
+
from qwak_sdk.commands.models.build._logic.constant.step_description import PhaseDetails
|
|
7
|
+
from qwak_sdk.commands.models.build._logic.interface.notifier_interface import Notifier
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NotifierImpl(Notifier):
|
|
11
|
+
def __init__(
|
|
12
|
+
self, logger: Logger, prefix: str, phase_details: PhaseDetails
|
|
13
|
+
) -> None:
|
|
14
|
+
self.logger = logging.LoggerAdapter(
|
|
15
|
+
logger,
|
|
16
|
+
{
|
|
17
|
+
"phase": phase_details.get_description(),
|
|
18
|
+
"phase_id": phase_details.get_id(),
|
|
19
|
+
},
|
|
20
|
+
)
|
|
21
|
+
self.prefix = f"{prefix} - " if prefix else ""
|
|
22
|
+
self.spinner = None
|
|
23
|
+
|
|
24
|
+
def set_spinner(self, spinner: Yaspin):
|
|
25
|
+
self.spinner = spinner
|
|
26
|
+
|
|
27
|
+
def exception(self, line: str, e: BaseException) -> None:
|
|
28
|
+
self.logger.error(
|
|
29
|
+
f"""Message: {line}
|
|
30
|
+
Exception: {e}
|
|
31
|
+
""",
|
|
32
|
+
exc_info=False,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def error(self, line: str) -> None:
|
|
36
|
+
self.logger.error(f"{self.prefix}{line}")
|
|
37
|
+
|
|
38
|
+
def warning(self, line: str) -> None:
|
|
39
|
+
self.logger.warning(f"{self.prefix}{line}")
|
|
40
|
+
|
|
41
|
+
def info(self, line: str) -> None:
|
|
42
|
+
self.logger.info(f"{self.prefix}{line}")
|
|
43
|
+
|
|
44
|
+
def debug(self, line: str) -> None:
|
|
45
|
+
self.logger.debug(f"{self.prefix}{line}")
|
|
46
|
+
|
|
47
|
+
def spinner_text(self, line: str) -> None:
|
|
48
|
+
if self.spinner:
|
|
49
|
+
self.spinner.text = f"{self.prefix}{line}"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from contextlib import contextmanager
|
|
2
|
+
from typing import Generator, Optional
|
|
3
|
+
|
|
4
|
+
from yaspin import yaspin
|
|
5
|
+
from yaspin.core import Yaspin
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@contextmanager
|
|
9
|
+
def spinner(text: Optional[str], show: bool) -> Generator[Yaspin, None, None]:
|
|
10
|
+
if show:
|
|
11
|
+
with yaspin(text=text, color="blue", timer=True).bold as sp:
|
|
12
|
+
yield sp
|
|
13
|
+
else:
|
|
14
|
+
yield
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from time import time
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TimeSource(ABC):
|
|
7
|
+
@abstractmethod
|
|
8
|
+
def current_epoch_time(self) -> int:
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Stopwatch:
|
|
13
|
+
def __init__(self, time_source: TimeSource):
|
|
14
|
+
self.time_source = time_source
|
|
15
|
+
self.start_time = self.time_source.current_epoch_time()
|
|
16
|
+
|
|
17
|
+
def elapsed_time_in_seconds(self) -> int:
|
|
18
|
+
end_time = self.time_source.current_epoch_time()
|
|
19
|
+
return end_time - self.start_time
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SystemClockTimeSource(TimeSource):
|
|
23
|
+
def current_epoch_time(self) -> int:
|
|
24
|
+
return int(time())
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class MockClockTimeSource(TimeSource):
|
|
28
|
+
def __init__(self, time_values=None):
|
|
29
|
+
self.time_values = []
|
|
30
|
+
if time_values:
|
|
31
|
+
self.time_values = list(time_values)
|
|
32
|
+
|
|
33
|
+
def current_epoch_time(self) -> int:
|
|
34
|
+
return self.time_values.pop(0)
|
|
35
|
+
|
|
36
|
+
def set_epoch_time_values(self, values: List[int]) -> None:
|
|
37
|
+
self.time_values = values
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def zip_logs(log_path: str, build_id: str):
|
|
6
|
+
if build_id:
|
|
7
|
+
shutil.make_archive(
|
|
8
|
+
base_name=str(Path(log_path).parent / build_id),
|
|
9
|
+
format="zip",
|
|
10
|
+
root_dir=log_path,
|
|
11
|
+
)
|
|
12
|
+
shutil.rmtree(log_path, ignore_errors=True)
|