zrb 1.8.2__tar.gz → 1.8.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {zrb-1.8.2 → zrb-1.8.4}/PKG-INFO +14 -10
- {zrb-1.8.2 → zrb-1.8.4}/README.md +13 -9
- {zrb-1.8.2 → zrb-1.8.4}/pyproject.toml +1 -1
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/__main__.py +2 -1
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/asdf/asdf.py +1 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/tmux/tmux.py +1 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/ubuntu.py +11 -2
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/zsh/zsh.py +1 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/session/session.py +9 -3
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/base/execution.py +1 -2
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/base/lifecycle.py +22 -18
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/cmd_task.py +3 -0
- zrb-1.8.4/src/zrb/util/cmd/command.py +192 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/run.py +2 -0
- zrb-1.8.2/src/zrb/util/cmd/command.py +0 -141
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/attr/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/attr/type.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/base64.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/git.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/git_subtree.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/group.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/http.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/jwt.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/chat_session.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/history.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/llm_ask.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/previous-session.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/tool/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/tool/api.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/tool/cli.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/tool/file.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/tool/rag.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/tool/sub_agent.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/llm/tool/web.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/md5.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/.coveragerc +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/.flake8 +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/.gitignore +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/README.md +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/add_column_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/add_column_util.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/config.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/gateway/view/content/my-module/my-entity.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/my_entity_service.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/my_entity_service_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_db_repository.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_repository.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_repository_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/schema/my_entity.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_create_my_entity.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_delete_my_entity.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_read_my_entity.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_update_my_entity.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/client_method.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/gateway_subroute.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/navigation_config_file.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/format_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/group.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/gateway/subroute/my_module.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/alembic.ini +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_api_client.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_client.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_client_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_direct_client.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/migration/README +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/migration/env.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/migration/script.py.mako +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/migration/versions/.gitkeep +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/migration_metadata.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/service/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/module_task_definition.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/navigation_config_file.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task_util.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/util.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/venv_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/app_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_db_repository.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_service.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/db_engine_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/error.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/logger_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/parser_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/schema.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/app.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/parser.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/user_agent.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/view.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/main.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/alembic.ini +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_api_client.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_direct_client.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/README +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/env.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/script.py.mako +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_auth_tables.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/8ed025bcc845_create_permissions.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration_metadata.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_db_repository.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_db_repository.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_db_repository.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/alembic.ini +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/config/navigation.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/migration/README +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/migration/env.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/migration/script.py.mako +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/migration/versions/.gitkeep +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/migration_metadata.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/schema/navigation.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/auth.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/view.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/auth/permission.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/auth/role.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/auth/user.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/error.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/homepage.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/login.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/logout.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/common/util.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/crud/style.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/crud/util.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/pico-style.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/script.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/style.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/images/android-chrome-192x192.png +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/images/android-chrome-512x512.png +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/images/favicon-32x32.png +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.amber.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.blue.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.cyan.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.fuchsia.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.green.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.grey.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.indigo.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.jade.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.lime.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.orange.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.pink.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.pumpkin.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.purple.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.red.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.sand.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.slate.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.violet.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.yellow.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.zinc.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/template/default.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/permission.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/role.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/user.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/template.env +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/_util/access_token.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_create_permission.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_delete_permission.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_read_permission.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_update_permission.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/test_user_session.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_health_and_readiness.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_homepage.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_not_found_error.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test.sh +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/add/fastapp/fastapp_util.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/create/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/create/project-template/README.md +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/create/project-template/zrb_init.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/project/create/project_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/python.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/random.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/asdf/asdf_helper.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/common_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/latex/ubuntu.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/tmux/tmux_config.sh +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/tmux/tmux_helper.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/zsh/zsh_config.sh +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/setup/zsh/zsh_helper.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/shell/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/shell/autocomplete/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/shell/autocomplete/bash.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/shell/autocomplete/subcmd.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/shell/autocomplete/zsh.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/todo.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/builtin/uuid.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/callback/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/callback/any_callback.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/callback/callback.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/cmd/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/cmd/cmd_result.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/cmd/cmd_val.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/config.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/content_transformer/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/content_transformer/any_content_transformer.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/content_transformer/content_transformer.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/context/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/context/any_context.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/context/any_shared_context.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/context/context.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/context/shared_context.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/dot_dict/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/dot_dict/dot_dict.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/env/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/env/any_env.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/env/env.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/env/env_file.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/env/env_map.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/group/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/group/any_group.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/group/group.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/any_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/base_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/bool_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/float_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/int_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/option_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/password_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/str_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/input/text_input.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/llm_config.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/cli.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/common_util.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_app.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_auth_config.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/docs_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/error_page/serve_default_404.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/error_page/show_error_page.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/error_page/view.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/home_page/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/home_page/home_page_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/home_page/view.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/login_api_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/login_page/login_page_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/login_page/view.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/logout_api_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/logout_page/logout_page_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/logout_page/view.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/node_page/group/show_group_page.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/node_page/group/view.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/node_page/node_page_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/node_page/task/partial/input.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/node_page/task/show_task_page.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/node_page/task/view.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/refresh_token_api_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/global_template.html +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/refresh-token.template.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/common.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/common.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/favicon-32x32.png +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/login/event.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/logout/event.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.amber.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.blue.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.cyan.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.fuchsia.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.green.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.grey.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.indigo.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.jade.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.lime.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.orange.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.pink.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.pumpkin.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.purple.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.red.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.sand.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.slate.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.violet.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.yellow.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/pico-css/pico.zinc.min.css +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/session/common-util.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/session/current-session.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/session/event.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/resources/session/past-session.js +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/static/static_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/task_input_api_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_route/task_session_api_route.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_schema/session.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_schema/token.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_schema/user.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_util/cookie.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_util/html.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_util/token.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/runner/web_util/user.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/session/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/session/any_session.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/session_state_log/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/session_state_log/session_state_log.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/session_state_logger/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/session_state_logger/any_session_state_logger.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/session_state_logger/file_session_state_logger.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/session_state_logger/session_state_logger_factory.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/any_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/base/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/base/context.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/base/monitoring.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/base/operators.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/base_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/base_trigger.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/http_check.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/agent.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/config.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/context.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/context_enrichment.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/error.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/history.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/history_summarization.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/print_node.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/prompt.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/tool_wrapper.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm/typing.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/llm_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/make_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/rsync_task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/scaffolder.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/scheduler.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/task.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task/tcp_check.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task_status/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/task_status/task_status.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/attr.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/cli/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/cli/style.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/cli/subcommand.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/cmd/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/cmd/remote.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/modification_mode.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/modify_class.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/modify_class_parent.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/modify_class_property.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/modify_dict.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/modify_function.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/modify_function_call.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/modify_method.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/codemod/modify_module.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/cron.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/file.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/git.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/git_subtree.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/group.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/init_path.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/load.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/string/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/string/conversion.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/string/format.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/string/name.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/util/todo.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/xcom/__init__.py +0 -0
- {zrb-1.8.2 → zrb-1.8.4}/src/zrb/xcom/xcom.py +0 -0
{zrb-1.8.2 → zrb-1.8.4}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: zrb
|
3
|
-
Version: 1.8.
|
3
|
+
Version: 1.8.4
|
4
4
|
Summary: Your Automation Powerhouse
|
5
5
|
Home-page: https://github.com/state-alchemists/zrb
|
6
6
|
License: AGPL-3.0-or-later
|
@@ -194,31 +194,35 @@ Then open your browser and visit `http://localhost:21213`
|
|
194
194
|

|
195
195
|
|
196
196
|
|
197
|
-
# 🐋
|
197
|
+
# 🐋 Running Zrb as a Container
|
198
198
|
|
199
|
-
Zrb
|
200
|
-
- The normal version
|
201
|
-
- The dind (Docker in Docker) version
|
199
|
+
Zrb can be run in a containerized environment, offering two distinct versions to suit different needs:
|
202
200
|
|
203
|
-
|
201
|
+
- **Standard Version**: Ideal for general use cases where Docker CLI access is not required.
|
202
|
+
- **Dind (Docker in Docker) Version**: Includes built-in Docker commands, perfect for scenarios where you need to access the host's Docker CLI.
|
204
203
|
|
205
|
-
|
204
|
+
### Standard Version
|
205
|
+
|
206
|
+
The standard version of the Zrb container is suitable for most automation tasks. To run this version, execute the following command:
|
206
207
|
|
207
208
|
```bash
|
208
|
-
#
|
209
|
+
# Replace <host-path> and <container-path> with your desired paths
|
209
210
|
docker run -v ${HOME}:/zrb-home -it --rm stalchmst/zrb:1.8.1 zrb
|
210
211
|
```
|
211
212
|
|
212
|
-
|
213
|
+
### Dind Version
|
214
|
+
|
215
|
+
The Dind version is tailored for advanced use cases where Docker commands need to be executed within the container. This version allows the container to interact with the host's Docker daemon. To run the Dind version, use the command below:
|
213
216
|
|
214
217
|
```bash
|
215
|
-
#
|
218
|
+
# Replace <host-path> and <container-path> with your desired paths
|
216
219
|
docker run \
|
217
220
|
-v ${HOME}:/zrb-home \
|
218
221
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
219
222
|
-it --rm stalchmst/zrb:1.8.1-dind docker ps
|
220
223
|
```
|
221
224
|
|
225
|
+
> **Note:** The Dind (Docker in Docker) version of the container is larger in size compared to the standard version due to the inclusion of Docker CLI tools. Consider this when choosing the appropriate version for your needs.
|
222
226
|
|
223
227
|
# 🎥 Demo & Documentation
|
224
228
|
|
@@ -156,31 +156,35 @@ Then open your browser and visit `http://localhost:21213`
|
|
156
156
|

|
157
157
|
|
158
158
|
|
159
|
-
# 🐋
|
159
|
+
# 🐋 Running Zrb as a Container
|
160
160
|
|
161
|
-
Zrb
|
162
|
-
- The normal version
|
163
|
-
- The dind (Docker in Docker) version
|
161
|
+
Zrb can be run in a containerized environment, offering two distinct versions to suit different needs:
|
164
162
|
|
165
|
-
|
163
|
+
- **Standard Version**: Ideal for general use cases where Docker CLI access is not required.
|
164
|
+
- **Dind (Docker in Docker) Version**: Includes built-in Docker commands, perfect for scenarios where you need to access the host's Docker CLI.
|
166
165
|
|
167
|
-
|
166
|
+
### Standard Version
|
167
|
+
|
168
|
+
The standard version of the Zrb container is suitable for most automation tasks. To run this version, execute the following command:
|
168
169
|
|
169
170
|
```bash
|
170
|
-
#
|
171
|
+
# Replace <host-path> and <container-path> with your desired paths
|
171
172
|
docker run -v ${HOME}:/zrb-home -it --rm stalchmst/zrb:1.8.1 zrb
|
172
173
|
```
|
173
174
|
|
174
|
-
|
175
|
+
### Dind Version
|
176
|
+
|
177
|
+
The Dind version is tailored for advanced use cases where Docker commands need to be executed within the container. This version allows the container to interact with the host's Docker daemon. To run the Dind version, use the command below:
|
175
178
|
|
176
179
|
```bash
|
177
|
-
#
|
180
|
+
# Replace <host-path> and <container-path> with your desired paths
|
178
181
|
docker run \
|
179
182
|
-v ${HOME}:/zrb-home \
|
180
183
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
181
184
|
-it --rm stalchmst/zrb:1.8.1-dind docker ps
|
182
185
|
```
|
183
186
|
|
187
|
+
> **Note:** The Dind (Docker in Docker) version of the container is larger in size compared to the standard version due to the inclusion of Docker CLI tools. Consider this when choosing the appropriate version for your needs.
|
184
188
|
|
185
189
|
# 🎥 Demo & Documentation
|
186
190
|
|
@@ -60,8 +60,9 @@ def serve_cli():
|
|
60
60
|
# run the CLI
|
61
61
|
cli.run(sys.argv[1:])
|
62
62
|
except KeyboardInterrupt:
|
63
|
+
# The exception is handled by the task runner
|
63
64
|
print(stylize_warning("\nStopped"), file=sys.stderr)
|
64
|
-
|
65
|
+
pass
|
65
66
|
except RuntimeError as e:
|
66
67
|
if f"{e}".lower() != "event loop is closed":
|
67
68
|
raise e
|
@@ -1,10 +1,18 @@
|
|
1
1
|
from zrb.builtin.group import setup_group
|
2
2
|
from zrb.task.cmd_task import CmdTask
|
3
3
|
|
4
|
-
update_ubuntu = CmdTask(
|
4
|
+
update_ubuntu = CmdTask(
|
5
|
+
name="update-ubuntu",
|
6
|
+
cmd="sudo apt update",
|
7
|
+
render_cmd=False,
|
8
|
+
is_interactive=True,
|
9
|
+
)
|
5
10
|
|
6
11
|
upgrade_todo = CmdTask(
|
7
|
-
name="upgrade-ubuntu",
|
12
|
+
name="upgrade-ubuntu",
|
13
|
+
cmd="sudo apt upgrade -y",
|
14
|
+
render_cmd=False,
|
15
|
+
is_interactive=True,
|
8
16
|
)
|
9
17
|
update_ubuntu >> upgrade_todo
|
10
18
|
|
@@ -22,6 +30,7 @@ setup_ubuntu = setup_group.add_task(
|
|
22
30
|
"cmake make tree tmux zsh neovim xdotool xsel",
|
23
31
|
],
|
24
32
|
render_cmd=False,
|
33
|
+
is_interactive=True,
|
25
34
|
),
|
26
35
|
alias="ubuntu",
|
27
36
|
)
|
@@ -51,9 +51,9 @@ class Session(AnySession):
|
|
51
51
|
self._shared_ctx = shared_ctx
|
52
52
|
self._shared_ctx.set_session(self)
|
53
53
|
self._parent = parent
|
54
|
-
self._action_coros: dict[AnyTask,
|
55
|
-
self._monitoring_coros: dict[AnyTask,
|
56
|
-
self._coros: list[
|
54
|
+
self._action_coros: dict[AnyTask, asyncio.Task] = {}
|
55
|
+
self._monitoring_coros: dict[AnyTask, asyncio.Task] = {}
|
56
|
+
self._coros: list[asyncio.Task] = []
|
57
57
|
self._colors = [
|
58
58
|
GREEN,
|
59
59
|
YELLOW,
|
@@ -100,6 +100,12 @@ class Session(AnySession):
|
|
100
100
|
self._is_terminated = True
|
101
101
|
for task_status in self._task_status.values():
|
102
102
|
task_status.mark_as_terminated()
|
103
|
+
for task in self._action_coros.values():
|
104
|
+
task.cancel()
|
105
|
+
for task in self._monitoring_coros.values():
|
106
|
+
task.cancel()
|
107
|
+
for task in self._coros:
|
108
|
+
task.cancel()
|
103
109
|
|
104
110
|
@property
|
105
111
|
def is_terminated(self) -> bool:
|
@@ -175,8 +175,7 @@ async def execute_action_with_retry(task: "BaseTask", session: AnySession) -> An
|
|
175
175
|
ctx.log_warning("Task cancelled or interrupted")
|
176
176
|
session.get_task_status(task).mark_as_failed() # Mark as failed on cancel
|
177
177
|
# Do not trigger fallbacks/successors on cancellation
|
178
|
-
|
179
|
-
|
178
|
+
raise
|
180
179
|
except BaseException as e:
|
181
180
|
ctx.log_error(f"Attempt {attempt + 1}/{max_attempt} failed: {e}")
|
182
181
|
session.get_task_status(
|
@@ -38,26 +38,30 @@ async def run_and_cleanup(
|
|
38
38
|
ctx = task.get_ctx(session) # Get context for logging
|
39
39
|
ctx.log_info("Terminating session after run completion/error.")
|
40
40
|
session.terminate()
|
41
|
-
|
42
41
|
# Clean up other potentially running asyncio tasks (excluding the main one)
|
43
42
|
# Be cautious with blanket cancellation if other background tasks are expected
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
43
|
+
try:
|
44
|
+
pending = [
|
45
|
+
t
|
46
|
+
for t in asyncio.all_tasks()
|
47
|
+
if t is not main_task_coro and not t.done()
|
48
|
+
]
|
49
|
+
if pending:
|
50
|
+
ctx = task.get_ctx(session) # Get context for logging
|
51
|
+
ctx.log_debug(f"Cleaning up {len(pending)} pending asyncio tasks...")
|
52
|
+
for t in pending:
|
53
|
+
t.cancel()
|
54
|
+
try:
|
55
|
+
# Give cancelled tasks a moment to process cancellation
|
56
|
+
await asyncio.wait(pending, timeout=1.0)
|
57
|
+
except asyncio.CancelledError:
|
58
|
+
# Expected if tasks handle cancellation promptly
|
59
|
+
pass
|
60
|
+
except Exception as cleanup_exc:
|
61
|
+
# Log errors during cleanup if necessary
|
62
|
+
ctx.log_warning(f"Error during task cleanup: {cleanup_exc}")
|
63
|
+
except RuntimeError as cleanup_exc:
|
64
|
+
ctx.log_warning(f"Error during task cleanup: {cleanup_exc}")
|
61
65
|
|
62
66
|
|
63
67
|
async def run_task_async(
|
@@ -48,6 +48,7 @@ class CmdTask(BaseTask):
|
|
48
48
|
warn_unrecommended_command: bool | None = None,
|
49
49
|
max_output_line: int = 1000,
|
50
50
|
max_error_line: int = 1000,
|
51
|
+
is_interactive: bool = False,
|
51
52
|
execute_condition: BoolAttr = True,
|
52
53
|
retries: int = 2,
|
53
54
|
retry_period: float = 0,
|
@@ -104,6 +105,7 @@ class CmdTask(BaseTask):
|
|
104
105
|
self._max_error_line = max_error_line
|
105
106
|
self._should_plain_print = plain_print
|
106
107
|
self._should_warn_unrecommended_command = warn_unrecommended_command
|
108
|
+
self._is_interactive = is_interactive
|
107
109
|
|
108
110
|
async def _exec_action(self, ctx: AnyContext) -> CmdResult:
|
109
111
|
"""Turn _cmd attribute into subprocess.Popen and execute it as task's action.
|
@@ -140,6 +142,7 @@ class CmdTask(BaseTask):
|
|
140
142
|
register_pid_method=lambda pid: ctx.xcom.get(xcom_pid_key).push(pid),
|
141
143
|
max_output_line=self._max_output_line,
|
142
144
|
max_error_line=self._max_error_line,
|
145
|
+
is_interactive=self._is_interactive,
|
143
146
|
)
|
144
147
|
# Check for errors
|
145
148
|
if return_code > 0:
|
@@ -0,0 +1,192 @@
|
|
1
|
+
import asyncio
|
2
|
+
import os
|
3
|
+
import re
|
4
|
+
import signal
|
5
|
+
import sys
|
6
|
+
from collections import deque
|
7
|
+
from collections.abc import Callable
|
8
|
+
from typing import TextIO
|
9
|
+
|
10
|
+
import psutil
|
11
|
+
|
12
|
+
from zrb.cmd.cmd_result import CmdResult
|
13
|
+
|
14
|
+
|
15
|
+
def check_unrecommended_commands(cmd_script: str) -> dict[str, str]:
|
16
|
+
"""
|
17
|
+
Check a command script for the use of unrecommended or non-POSIX compliant commands.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
cmd_script (str): The command script string to check.
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
dict[str, str]: A dictionary where keys are the violating commands/patterns
|
24
|
+
and values are the reasons they are unrecommended.
|
25
|
+
"""
|
26
|
+
banned_commands = {
|
27
|
+
"<(": "Process substitution isn't POSIX compliant and causes trouble",
|
28
|
+
"column": "Command isn't included in Ubuntu packages and is not POSIX compliant",
|
29
|
+
"echo": "echo isn't consistent across OS; use printf instead",
|
30
|
+
"eval": "Avoid eval as it can accidentally execute arbitrary strings",
|
31
|
+
"realpath": "Not available by default on OSX",
|
32
|
+
"source": "Not POSIX compliant; use '.' instead",
|
33
|
+
" test": "Use '[' instead for consistency",
|
34
|
+
"which": "Command in not POSIX compliant, use command -v",
|
35
|
+
}
|
36
|
+
banned_commands_regex = {
|
37
|
+
r"grep.* -y": "grep -y does not work on Alpine; use grep -i",
|
38
|
+
r"grep.* -P": "grep -P is not valid on OSX",
|
39
|
+
r"grep[^|]+--\w{2,}": "grep long commands do not work on Alpine",
|
40
|
+
r'readlink.+-.*f.+["$]': "readlink -f behaves differently on OSX",
|
41
|
+
r"sort.*-V": "sort -V is not supported everywhere",
|
42
|
+
r"sort.*--sort-versions": "sort --sort-version is not supported everywhere",
|
43
|
+
r"\bls ": "Avoid using ls; use shell globs or find instead",
|
44
|
+
}
|
45
|
+
violations = {}
|
46
|
+
# Check banned commands
|
47
|
+
for cmd, reason in banned_commands.items():
|
48
|
+
if cmd in cmd_script:
|
49
|
+
violations[cmd] = reason
|
50
|
+
# Check banned regex patterns
|
51
|
+
for pattern, reason in banned_commands_regex.items():
|
52
|
+
if re.search(pattern, cmd_script):
|
53
|
+
violations[pattern] = reason
|
54
|
+
return violations
|
55
|
+
|
56
|
+
|
57
|
+
async def run_command(
|
58
|
+
cmd: list[str],
|
59
|
+
cwd: str | None = None,
|
60
|
+
env_map: dict[str, str] | None = None,
|
61
|
+
print_method: Callable[..., None] | None = None,
|
62
|
+
register_pid_method: Callable[[int], None] | None = None,
|
63
|
+
max_output_line: int = 1000,
|
64
|
+
max_error_line: int = 1000,
|
65
|
+
is_interactive: bool = False,
|
66
|
+
) -> tuple[CmdResult, int]:
|
67
|
+
"""
|
68
|
+
Executes a command using the robust `readline` strategy with a memory
|
69
|
+
limit, and correctly handles terminal control characters in the output.
|
70
|
+
Please note that `interactive` execution is generally not recommended and thus
|
71
|
+
disabled by default.
|
72
|
+
When using `interactive execution, the command will not be started in new session
|
73
|
+
and will share the same stdin as the main process, which might trigger race condition.
|
74
|
+
You can use interactive execution for a limited usecase when the command
|
75
|
+
require user input.
|
76
|
+
"""
|
77
|
+
actual_print_method = print_method if print_method is not None else print
|
78
|
+
if cwd is None:
|
79
|
+
cwd = os.getcwd()
|
80
|
+
# While environment variables alone weren't the fix, they are still
|
81
|
+
# good practice for encouraging simpler output from tools.
|
82
|
+
child_env = (env_map or os.environ).copy()
|
83
|
+
child_env["TERM"] = "xterm-256color" # A capable but standard terminal
|
84
|
+
child_env["NO_COLOR"] = "0" # Explicitly allow color
|
85
|
+
cmd_process = await asyncio.create_subprocess_exec(
|
86
|
+
*cmd,
|
87
|
+
cwd=cwd,
|
88
|
+
env=child_env,
|
89
|
+
start_new_session=not is_interactive,
|
90
|
+
stdin=__get_cmd_stdin(is_interactive),
|
91
|
+
stdout=asyncio.subprocess.PIPE,
|
92
|
+
stderr=asyncio.subprocess.PIPE,
|
93
|
+
limit=10 * 10 * 1024, # Buffer memory limit
|
94
|
+
)
|
95
|
+
if register_pid_method is not None:
|
96
|
+
register_pid_method(cmd_process.pid)
|
97
|
+
# Use the new, simple, and correct stream reader.
|
98
|
+
stdout_task = asyncio.create_task(
|
99
|
+
__read_stream(cmd_process.stdout, actual_print_method, max_output_line)
|
100
|
+
)
|
101
|
+
stderr_task = asyncio.create_task(
|
102
|
+
__read_stream(cmd_process.stderr, actual_print_method, max_error_line)
|
103
|
+
)
|
104
|
+
try:
|
105
|
+
return_code = await cmd_process.wait()
|
106
|
+
stdout, stderr = await asyncio.gather(stdout_task, stderr_task)
|
107
|
+
return CmdResult(stdout, stderr), return_code
|
108
|
+
except (KeyboardInterrupt, asyncio.CancelledError):
|
109
|
+
try:
|
110
|
+
os.killpg(cmd_process.pid, signal.SIGINT)
|
111
|
+
await asyncio.wait_for(cmd_process.wait(), timeout=2.0)
|
112
|
+
except asyncio.TimeoutError:
|
113
|
+
# If it doesn't terminate, kill it forcefully
|
114
|
+
actual_print_method(
|
115
|
+
f"Process {cmd_process.pid} did not terminate gracefully, killing."
|
116
|
+
)
|
117
|
+
kill_pid(cmd_process.pid, print_method=actual_print_method)
|
118
|
+
except Exception:
|
119
|
+
pass
|
120
|
+
# Final cleanup
|
121
|
+
stdout_task.cancel()
|
122
|
+
stderr_task.cancel()
|
123
|
+
await asyncio.gather(stdout_task, stderr_task, return_exceptions=True)
|
124
|
+
raise
|
125
|
+
|
126
|
+
|
127
|
+
def __get_cmd_stdin(is_interactive: bool) -> int | TextIO:
|
128
|
+
if is_interactive and sys.stdin.isatty():
|
129
|
+
return sys.stdin
|
130
|
+
return asyncio.subprocess.DEVNULL
|
131
|
+
|
132
|
+
|
133
|
+
async def __read_stream(
|
134
|
+
stream: asyncio.StreamReader,
|
135
|
+
print_method: Callable[..., None],
|
136
|
+
max_lines: int,
|
137
|
+
) -> str:
|
138
|
+
"""
|
139
|
+
Reads from the stream using the robust `readline()` and correctly
|
140
|
+
interprets carriage returns (`\r`) as distinct print events.
|
141
|
+
"""
|
142
|
+
captured_lines = deque(maxlen=max_lines if max_lines > 0 else 0)
|
143
|
+
while True:
|
144
|
+
try:
|
145
|
+
line_bytes = await stream.readline()
|
146
|
+
if not line_bytes:
|
147
|
+
break
|
148
|
+
except ValueError:
|
149
|
+
# Safety valve for the memory limit.
|
150
|
+
error_msg = "[ERROR] A single line of output was too long to process."
|
151
|
+
print_method(error_msg)
|
152
|
+
if max_lines > 0:
|
153
|
+
captured_lines.append(error_msg)
|
154
|
+
break
|
155
|
+
except (KeyboardInterrupt, asyncio.CancelledError):
|
156
|
+
raise
|
157
|
+
except Exception:
|
158
|
+
break
|
159
|
+
decoded_line = line_bytes.decode("utf-8", errors="replace")
|
160
|
+
parts = decoded_line.replace("\r", "\n").splitlines()
|
161
|
+
for part in parts:
|
162
|
+
clean_part = part.rstrip()
|
163
|
+
if clean_part:
|
164
|
+
try:
|
165
|
+
print_method(clean_part, end="\r\n")
|
166
|
+
except Exception:
|
167
|
+
print_method(clean_part)
|
168
|
+
if max_lines > 0:
|
169
|
+
captured_lines.append(clean_part)
|
170
|
+
return "\r\n".join(captured_lines)
|
171
|
+
|
172
|
+
|
173
|
+
def kill_pid(pid: int, print_method: Callable[..., None] | None = None):
|
174
|
+
"""
|
175
|
+
Kill a process and its children given the parent process ID.
|
176
|
+
|
177
|
+
Args:
|
178
|
+
pid (int): The process ID of the parent process.
|
179
|
+
print_method (Callable[..., None] | None): A method to print status messages.
|
180
|
+
Defaults to the built-in print function.
|
181
|
+
"""
|
182
|
+
actual_print_method = print_method if print_method is not None else print
|
183
|
+
try:
|
184
|
+
parent = psutil.Process(pid)
|
185
|
+
children = parent.children(recursive=True)
|
186
|
+
for child in children:
|
187
|
+
actual_print_method(f"Killing child process {child.pid}")
|
188
|
+
child.kill()
|
189
|
+
actual_print_method(f"Killing process {pid}")
|
190
|
+
parent.kill()
|
191
|
+
except psutil.NoSuchProcess:
|
192
|
+
actual_print_method(f"Process with pid: {pid} already terminated")
|
@@ -13,6 +13,8 @@ async def run_async(value: Any) -> Any:
|
|
13
13
|
Returns:
|
14
14
|
Any: The result of the awaited value or the value itself if not awaitable.
|
15
15
|
"""
|
16
|
+
if isinstance(value, asyncio.Task):
|
17
|
+
return value
|
16
18
|
if inspect.isawaitable(value):
|
17
19
|
return await value
|
18
20
|
return await asyncio.to_thread(lambda: value)
|
@@ -1,141 +0,0 @@
|
|
1
|
-
import asyncio
|
2
|
-
import os
|
3
|
-
import re
|
4
|
-
import sys
|
5
|
-
from collections.abc import Callable
|
6
|
-
|
7
|
-
import psutil
|
8
|
-
|
9
|
-
from zrb.cmd.cmd_result import CmdResult
|
10
|
-
|
11
|
-
|
12
|
-
def check_unrecommended_commands(cmd_script: str) -> dict[str, str]:
|
13
|
-
"""
|
14
|
-
Check a command script for the use of unrecommended or non-POSIX compliant commands.
|
15
|
-
|
16
|
-
Args:
|
17
|
-
cmd_script (str): The command script string to check.
|
18
|
-
|
19
|
-
Returns:
|
20
|
-
dict[str, str]: A dictionary where keys are the violating commands/patterns
|
21
|
-
and values are the reasons they are unrecommended.
|
22
|
-
"""
|
23
|
-
banned_commands = {
|
24
|
-
"<(": "Process substitution isn't POSIX compliant and causes trouble",
|
25
|
-
"column": "Command isn't included in Ubuntu packages and is not POSIX compliant",
|
26
|
-
"echo": "echo isn't consistent across OS; use printf instead",
|
27
|
-
"eval": "Avoid eval as it can accidentally execute arbitrary strings",
|
28
|
-
"realpath": "Not available by default on OSX",
|
29
|
-
"source": "Not POSIX compliant; use '.' instead",
|
30
|
-
" test": "Use '[' instead for consistency",
|
31
|
-
"which": "Command in not POSIX compliant, use command -v",
|
32
|
-
}
|
33
|
-
banned_commands_regex = {
|
34
|
-
r"grep.* -y": "grep -y does not work on Alpine; use grep -i",
|
35
|
-
r"grep.* -P": "grep -P is not valid on OSX",
|
36
|
-
r"grep[^|]+--\w{2,}": "grep long commands do not work on Alpine",
|
37
|
-
r'readlink.+-.*f.+["$]': "readlink -f behaves differently on OSX",
|
38
|
-
r"sort.*-V": "sort -V is not supported everywhere",
|
39
|
-
r"sort.*--sort-versions": "sort --sort-version is not supported everywhere",
|
40
|
-
r"\bls ": "Avoid using ls; use shell globs or find instead",
|
41
|
-
}
|
42
|
-
violations = {}
|
43
|
-
# Check banned commands
|
44
|
-
for cmd, reason in banned_commands.items():
|
45
|
-
if cmd in cmd_script:
|
46
|
-
violations[cmd] = reason
|
47
|
-
# Check banned regex patterns
|
48
|
-
for pattern, reason in banned_commands_regex.items():
|
49
|
-
if re.search(pattern, cmd_script):
|
50
|
-
violations[pattern] = reason
|
51
|
-
return violations
|
52
|
-
|
53
|
-
|
54
|
-
async def run_command(
|
55
|
-
cmd: list[str],
|
56
|
-
cwd: str | None = None,
|
57
|
-
env_map: dict[str, str] | None = None,
|
58
|
-
print_method: Callable[..., None] | None = None,
|
59
|
-
register_pid_method: Callable[[int], None] | None = None,
|
60
|
-
max_output_line: int = 1000,
|
61
|
-
max_error_line: int = 1000,
|
62
|
-
) -> tuple[CmdResult, int]:
|
63
|
-
async def __read_stream(
|
64
|
-
stream, print_method: Callable[..., None], max_lines: int
|
65
|
-
) -> str:
|
66
|
-
lines = []
|
67
|
-
if hasattr(stream, "_limit"):
|
68
|
-
# The limit is set to 10 MB
|
69
|
-
stream._limit = 1024 * 1024 * 10
|
70
|
-
while True:
|
71
|
-
line = None
|
72
|
-
try:
|
73
|
-
line = await stream.readline()
|
74
|
-
except asyncio.exceptions.CancelledError:
|
75
|
-
pass
|
76
|
-
except asyncio.exceptions.LimitOverrunError as e:
|
77
|
-
# Recover by reading a limited chunk instead
|
78
|
-
await stream.read(e.consumed)
|
79
|
-
line = "<output line too long>"
|
80
|
-
except BaseException as e:
|
81
|
-
line = f"Error while reading stream {type(e)} {e}"
|
82
|
-
pass
|
83
|
-
if not line:
|
84
|
-
break
|
85
|
-
try:
|
86
|
-
line = line.decode("utf-8").rstrip()
|
87
|
-
except Exception:
|
88
|
-
pass
|
89
|
-
lines.append(line)
|
90
|
-
if len(lines) > max_lines:
|
91
|
-
lines.pop(0) # Keep only the last max_lines
|
92
|
-
print_method(line)
|
93
|
-
return "\n".join(lines)
|
94
|
-
|
95
|
-
actual_print_method = print_method if print_method is not None else print
|
96
|
-
cmd_process = None
|
97
|
-
if cwd is None:
|
98
|
-
cwd = os.getcwd()
|
99
|
-
if env_map is None:
|
100
|
-
env_map = os.environ
|
101
|
-
cmd_process = await asyncio.create_subprocess_exec(
|
102
|
-
*cmd,
|
103
|
-
cwd=cwd,
|
104
|
-
stdin=sys.stdin if sys.stdin.isatty() else None,
|
105
|
-
stdout=asyncio.subprocess.PIPE,
|
106
|
-
stderr=asyncio.subprocess.PIPE,
|
107
|
-
env=env_map,
|
108
|
-
bufsize=0,
|
109
|
-
)
|
110
|
-
if register_pid_method is not None:
|
111
|
-
register_pid_method(cmd_process.pid)
|
112
|
-
stdout_task = asyncio.create_task(
|
113
|
-
__read_stream(cmd_process.stdout, actual_print_method, max_output_line)
|
114
|
-
)
|
115
|
-
stderr_task = asyncio.create_task(
|
116
|
-
__read_stream(cmd_process.stderr, actual_print_method, max_error_line)
|
117
|
-
)
|
118
|
-
# Wait for process to complete and gather stdout/stderr
|
119
|
-
return_code = await cmd_process.wait()
|
120
|
-
stdout = await stdout_task
|
121
|
-
stderr = await stderr_task
|
122
|
-
return CmdResult(stdout, stderr), return_code
|
123
|
-
|
124
|
-
|
125
|
-
def kill_pid(pid: int, print_method: Callable[..., None] | None = None):
|
126
|
-
"""
|
127
|
-
Kill a process and its children given the parent process ID.
|
128
|
-
|
129
|
-
Args:
|
130
|
-
pid (int): The process ID of the parent process.
|
131
|
-
print_method (Callable[..., None] | None): A method to print status messages.
|
132
|
-
Defaults to the built-in print function.
|
133
|
-
"""
|
134
|
-
actual_print_method = print_method if print_method is not None else print
|
135
|
-
parent = psutil.Process(pid)
|
136
|
-
children = parent.children(recursive=True)
|
137
|
-
for child in children:
|
138
|
-
actual_print_method(f"Killing child process {child.pid}")
|
139
|
-
child.terminate()
|
140
|
-
actual_print_method(f"Killing process {pid}")
|
141
|
-
parent.terminate()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|