zrb 1.0.0a2__py3-none-any.whl → 1.0.0a3__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.
- zrb/__init__.py +48 -39
- zrb/__main__.py +3 -3
- zrb/attr/type.py +2 -1
- zrb/builtin/__init__.py +40 -2
- zrb/builtin/base64.py +32 -0
- zrb/builtin/git.py +156 -0
- zrb/builtin/git_subtree.py +88 -0
- zrb/builtin/group.py +34 -0
- zrb/builtin/llm.py +31 -0
- zrb/builtin/md5.py +34 -0
- zrb/builtin/project/__init__.py +0 -0
- zrb/builtin/project/add/__init__.py +0 -0
- zrb/builtin/project/add/fastapp.py +72 -0
- zrb/builtin/project/add/fastapp_template/.gitignore +4 -0
- zrb/builtin/project/add/fastapp_template/README.md +7 -0
- zrb/builtin/project/add/fastapp_template/__init__.py +0 -0
- zrb/builtin/project/add/fastapp_template/_zrb/config.py +17 -0
- zrb/builtin/project/add/fastapp_template/_zrb/group.py +16 -0
- zrb/builtin/project/add/fastapp_template/_zrb/helper.py +97 -0
- zrb/builtin/project/add/fastapp_template/_zrb/main.py +132 -0
- zrb/builtin/project/add/fastapp_template/_zrb/venv_task.py +22 -0
- zrb/builtin/project/add/fastapp_template/common/__init__.py +0 -0
- zrb/builtin/project/add/fastapp_template/common/app.py +18 -0
- zrb/builtin/project/add/fastapp_template/common/db_engine.py +5 -0
- zrb/builtin/project/add/fastapp_template/common/db_repository.py +134 -0
- zrb/builtin/project/add/fastapp_template/common/error.py +8 -0
- zrb/builtin/project/add/fastapp_template/common/schema.py +5 -0
- zrb/builtin/project/add/fastapp_template/common/usecase.py +232 -0
- zrb/builtin/project/add/fastapp_template/config.py +29 -0
- zrb/builtin/project/add/fastapp_template/main.py +7 -0
- zrb/builtin/project/add/fastapp_template/migrate.py +3 -0
- zrb/builtin/project/add/fastapp_template/module/__init__.py +0 -0
- zrb/builtin/project/add/fastapp_template/module/auth/alembic.ini +117 -0
- zrb/builtin/project/add/fastapp_template/module/auth/client/api_client.py +7 -0
- zrb/builtin/project/add/fastapp_template/module/auth/client/base_client.py +27 -0
- zrb/builtin/project/add/fastapp_template/module/auth/client/direct_client.py +6 -0
- zrb/builtin/project/add/fastapp_template/module/auth/client/factory.py +9 -0
- zrb/builtin/project/add/fastapp_template/module/auth/migration/README +1 -0
- zrb/builtin/project/add/fastapp_template/module/auth/migration/env.py +108 -0
- zrb/builtin/project/add/fastapp_template/module/auth/migration/script.py.mako +26 -0
- zrb/builtin/project/add/fastapp_template/module/auth/migration/versions/3093c7336477_add_user_table.py +37 -0
- zrb/builtin/project/add/fastapp_template/module/auth/migration_metadata.py +6 -0
- zrb/builtin/project/add/fastapp_template/module/auth/route.py +22 -0
- zrb/builtin/project/add/fastapp_template/module/auth/service/__init__.py +0 -0
- zrb/builtin/project/add/fastapp_template/module/auth/service/user/__init__.py +0 -0
- zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/__init__.py +0 -0
- zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/db_repository.py +39 -0
- zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/factory.py +13 -0
- zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/repository.py +34 -0
- zrb/builtin/project/add/fastapp_template/module/auth/service/user/usecase.py +45 -0
- zrb/builtin/project/add/fastapp_template/module/gateway/alembic.ini +117 -0
- zrb/builtin/project/add/fastapp_template/module/gateway/migration/README +1 -0
- zrb/builtin/project/add/fastapp_template/module/gateway/migration/env.py +108 -0
- zrb/builtin/project/add/fastapp_template/module/gateway/migration/script.py.mako +26 -0
- zrb/builtin/project/add/fastapp_template/module/gateway/migration/versions/.gitkeep +0 -0
- zrb/builtin/project/add/fastapp_template/module/gateway/migration_metadata.py +3 -0
- zrb/builtin/project/add/fastapp_template/module/gateway/route.py +27 -0
- zrb/builtin/project/add/fastapp_template/requirements.txt +6 -0
- zrb/builtin/project/add/fastapp_template/schema/__init__.py +0 -0
- zrb/builtin/project/add/fastapp_template/schema/role.py +31 -0
- zrb/builtin/project/add/fastapp_template/schema/user.py +31 -0
- zrb/builtin/project/add/fastapp_template/template.env +2 -0
- zrb/builtin/project/create/__init__.py +0 -0
- zrb/builtin/project/create/create.py +41 -0
- zrb/builtin/project/create/project-template/README.md +3 -0
- zrb/builtin/project/create/project-template/zrb_init.py +7 -0
- zrb/builtin/python.py +11 -0
- zrb/builtin/shell/__init__.py +0 -5
- zrb/builtin/shell/autocomplete/__init__.py +0 -9
- zrb/builtin/shell/autocomplete/bash.py +5 -6
- zrb/builtin/shell/autocomplete/subcmd.py +7 -8
- zrb/builtin/shell/autocomplete/zsh.py +5 -6
- zrb/builtin/todo.py +186 -0
- zrb/callback/any_callback.py +1 -1
- zrb/callback/callback.py +5 -5
- zrb/cmd/cmd_val.py +2 -2
- zrb/config.py +4 -1
- zrb/content_transformer/any_content_transformer.py +1 -1
- zrb/content_transformer/content_transformer.py +2 -2
- zrb/context/any_context.py +1 -1
- zrb/context/any_shared_context.py +3 -3
- zrb/context/context.py +10 -8
- zrb/context/shared_context.py +9 -8
- zrb/env/__init__.py +0 -3
- zrb/env/any_env.py +1 -1
- zrb/env/env.py +3 -4
- zrb/env/env_file.py +4 -4
- zrb/env/env_map.py +2 -2
- zrb/group/__init__.py +0 -3
- zrb/group/any_group.py +3 -3
- zrb/group/group.py +7 -6
- zrb/input/any_input.py +1 -1
- zrb/input/base_input.py +4 -4
- zrb/input/bool_input.py +5 -5
- zrb/input/float_input.py +3 -3
- zrb/input/int_input.py +3 -3
- zrb/input/option_input.py +51 -0
- zrb/input/password_input.py +2 -2
- zrb/input/str_input.py +1 -1
- zrb/input/text_input.py +12 -10
- zrb/runner/cli.py +79 -45
- zrb/runner/web_app/group_info_ui/controller.py +7 -8
- zrb/runner/web_app/group_info_ui/view.html +2 -2
- zrb/runner/web_app/home_page/controller.py +7 -6
- zrb/runner/web_app/home_page/view.html +2 -2
- zrb/runner/web_app/task_ui/controller.py +8 -12
- zrb/runner/web_app/task_ui/view.html +2 -2
- zrb/runner/web_server.py +137 -211
- zrb/runner/web_util.py +5 -35
- zrb/session/any_session.py +13 -7
- zrb/session/session.py +78 -40
- zrb/session_state_log/session_state_log.py +7 -5
- zrb/session_state_logger/any_session_state_logger.py +1 -1
- zrb/session_state_logger/default_session_state_logger.py +2 -2
- zrb/session_state_logger/file_session_state_logger.py +19 -27
- zrb/task/any_task.py +4 -4
- zrb/task/base_task.py +33 -23
- zrb/task/base_trigger.py +11 -12
- zrb/task/cmd_task.py +48 -39
- zrb/task/http_check.py +8 -8
- zrb/task/llm_task.py +160 -0
- zrb/task/make_task.py +9 -9
- zrb/task/rsync_task.py +7 -7
- zrb/task/scaffolder.py +14 -11
- zrb/task/scheduler.py +6 -7
- zrb/task/task.py +1 -1
- zrb/task/tcp_check.py +8 -8
- zrb/util/attr.py +19 -3
- zrb/util/cli/style.py +71 -2
- zrb/util/cli/subcommand.py +2 -2
- zrb/util/codemod/__init__.py +0 -0
- zrb/util/codemod/add_code_to_class.py +35 -0
- zrb/util/codemod/add_code_to_function.py +36 -0
- zrb/util/codemod/add_code_to_method.py +55 -0
- zrb/util/codemod/add_key_to_dict.py +51 -0
- zrb/util/codemod/add_param_to_function_call.py +39 -0
- zrb/util/codemod/add_property_to_class.py +55 -0
- zrb/util/git.py +156 -0
- zrb/util/git_subtree.py +94 -0
- zrb/util/group.py +2 -2
- zrb/util/llm/tool.py +63 -0
- zrb/util/string/conversion.py +7 -0
- zrb/util/todo.py +135 -0
- {zrb-1.0.0a2.dist-info → zrb-1.0.0a3.dist-info}/METADATA +8 -5
- zrb-1.0.0a3.dist-info/RECORD +194 -0
- zrb/builtin/shell/_group.py +0 -9
- zrb/builtin/shell/autocomplete/_group.py +0 -6
- zrb/runner/web_app/any_request_handler.py +0 -24
- zrb-1.0.0a2.dist-info/RECORD +0 -120
- {zrb-1.0.0a2.dist-info → zrb-1.0.0a3.dist-info}/WHEEL +0 -0
- {zrb-1.0.0a2.dist-info → zrb-1.0.0a3.dist-info}/entry_points.txt +0 -0
zrb/builtin/todo.py
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
import datetime
|
2
|
+
import os
|
3
|
+
|
4
|
+
from zrb.builtin.group import todo_group
|
5
|
+
from zrb.config import TODO_DIR
|
6
|
+
from zrb.context.any_context import AnyContext
|
7
|
+
from zrb.input.str_input import StrInput
|
8
|
+
from zrb.input.text_input import TextInput
|
9
|
+
from zrb.task.make_task import make_task
|
10
|
+
from zrb.util.cli.style import (
|
11
|
+
stylize_bold_green,
|
12
|
+
stylize_cyan,
|
13
|
+
stylize_magenta,
|
14
|
+
stylize_yellow,
|
15
|
+
)
|
16
|
+
from zrb.util.string.name import get_random_name
|
17
|
+
from zrb.util.todo import (
|
18
|
+
TodoTask,
|
19
|
+
parse_todo_line,
|
20
|
+
read_todo_from_file,
|
21
|
+
todo_task_to_line,
|
22
|
+
write_todo_to_file,
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
@make_task(
|
27
|
+
name="todo-add",
|
28
|
+
input=[
|
29
|
+
StrInput(
|
30
|
+
name="description",
|
31
|
+
description="Task description",
|
32
|
+
prompt="Task description",
|
33
|
+
),
|
34
|
+
StrInput(
|
35
|
+
name="priority",
|
36
|
+
description="Task priority",
|
37
|
+
prompt="Task priority",
|
38
|
+
default_str="E",
|
39
|
+
),
|
40
|
+
StrInput(
|
41
|
+
name="project",
|
42
|
+
description="Task project",
|
43
|
+
prompt="Task project (space separated)",
|
44
|
+
),
|
45
|
+
StrInput(
|
46
|
+
name="context",
|
47
|
+
description="Task context",
|
48
|
+
prompt="Task context (space separated)",
|
49
|
+
),
|
50
|
+
],
|
51
|
+
description="➕ Add todo",
|
52
|
+
group=todo_group,
|
53
|
+
alias="add",
|
54
|
+
)
|
55
|
+
def todo_add(ctx: AnyContext):
|
56
|
+
todo_file_path = os.path.join(TODO_DIR, "todo.txt")
|
57
|
+
todo_tasks: list[TodoTask] = []
|
58
|
+
if os.path.isfile(todo_file_path):
|
59
|
+
todo_tasks = read_todo_from_file(todo_file_path)
|
60
|
+
else:
|
61
|
+
os.makedirs(TODO_DIR, exist_ok=True)
|
62
|
+
todo_tasks.append(
|
63
|
+
_complete_todo_task(
|
64
|
+
TodoTask(
|
65
|
+
priority=ctx.input.priority.upper(),
|
66
|
+
description=ctx.input.description,
|
67
|
+
contexts=[
|
68
|
+
context.strip()
|
69
|
+
for context in ctx.input.context.split(" ")
|
70
|
+
if context.strip() != ""
|
71
|
+
],
|
72
|
+
projects=[
|
73
|
+
project.strip()
|
74
|
+
for project in ctx.input.project.split(" ")
|
75
|
+
if project.strip() != ""
|
76
|
+
],
|
77
|
+
)
|
78
|
+
)
|
79
|
+
)
|
80
|
+
write_todo_to_file(todo_file_path, todo_tasks)
|
81
|
+
return _get_visual_todo_list()
|
82
|
+
|
83
|
+
|
84
|
+
@make_task(name="todo-list", description="📋 List todo", group=todo_group, alias="list")
|
85
|
+
def todo_list(ctx: AnyContext):
|
86
|
+
return _get_visual_todo_list()
|
87
|
+
|
88
|
+
|
89
|
+
@make_task(
|
90
|
+
name="todo-edit",
|
91
|
+
input=[
|
92
|
+
TextInput(
|
93
|
+
name="text",
|
94
|
+
description="Todo.txt content",
|
95
|
+
prompt="Todo.txt content (will override existing)",
|
96
|
+
default_str=lambda _: _get_todo_txt_content(),
|
97
|
+
),
|
98
|
+
],
|
99
|
+
description="✏️ Edit todo",
|
100
|
+
group=todo_group,
|
101
|
+
alias="edit",
|
102
|
+
)
|
103
|
+
def todo_edit(ctx: AnyContext):
|
104
|
+
todo_tasks = [
|
105
|
+
_complete_todo_task(parse_todo_line(line))
|
106
|
+
for line in ctx.input.text.split("\n")
|
107
|
+
if line.strip() != ""
|
108
|
+
]
|
109
|
+
new_content = "\n".join(todo_task_to_line(todo_task) for todo_task in todo_tasks)
|
110
|
+
todo_file_path = os.path.join(TODO_DIR, "todo.txt")
|
111
|
+
with open(todo_file_path, "w") as f:
|
112
|
+
f.write(new_content)
|
113
|
+
return _get_visual_todo_list()
|
114
|
+
|
115
|
+
|
116
|
+
def _complete_todo_task(todo_task: TodoTask):
|
117
|
+
if todo_task.creation_date is None:
|
118
|
+
todo_task.creation_date = datetime.date.today()
|
119
|
+
if "id" not in todo_task.keyval:
|
120
|
+
todo_task.keyval["id"] = get_random_name()
|
121
|
+
return todo_task
|
122
|
+
|
123
|
+
|
124
|
+
def _get_visual_todo_list() -> str:
|
125
|
+
todo_file_path = os.path.join(TODO_DIR, "todo.txt")
|
126
|
+
if not os.path.isfile(todo_file_path):
|
127
|
+
return "\n".join(["", " Todo.txt not found... 🌵🦖", ""])
|
128
|
+
todo_tasks = read_todo_from_file(todo_file_path)
|
129
|
+
if len(todo_tasks) == 0:
|
130
|
+
return "\n".join(["", " Empty todo list... 🌵🦖", ""])
|
131
|
+
max_desc_name_length = max(len(todo_task.description) for todo_task in todo_tasks)
|
132
|
+
if max_desc_name_length < len("DESCRIPTION"):
|
133
|
+
max_desc_name_length = len("DESCRIPTION")
|
134
|
+
# Headers
|
135
|
+
results = [
|
136
|
+
stylize_bold_green(
|
137
|
+
" ".join(
|
138
|
+
[
|
139
|
+
"".ljust(3), # priority
|
140
|
+
"".ljust(3), # completed
|
141
|
+
"COMPLETED AT".rjust(14), # completed date
|
142
|
+
"CREATED AT".rjust(14), # completed date
|
143
|
+
"DESCRIPTION".ljust(max_desc_name_length),
|
144
|
+
"PROJECT/CONTEXT/OTHERS",
|
145
|
+
]
|
146
|
+
)
|
147
|
+
)
|
148
|
+
]
|
149
|
+
for todo_task in todo_tasks:
|
150
|
+
completed = "[x]" if todo_task.completed else "[ ]"
|
151
|
+
priority = " " if todo_task.priority is None else f"({todo_task.priority})"
|
152
|
+
completion_date = stylize_yellow(_date_to_str(todo_task.completion_date))
|
153
|
+
creation_date = stylize_cyan(_date_to_str(todo_task.creation_date))
|
154
|
+
description = todo_task.description.ljust(max_desc_name_length)
|
155
|
+
additions = ", ".join(
|
156
|
+
[stylize_yellow(f"+{project}") for project in todo_task.projects]
|
157
|
+
+ [stylize_cyan(f"@{context}") for context in todo_task.contexts]
|
158
|
+
+ [stylize_magenta(f"{key}:{val}") for key, val in todo_task.keyval.items()]
|
159
|
+
)
|
160
|
+
results.append(
|
161
|
+
" ".join(
|
162
|
+
[
|
163
|
+
completed,
|
164
|
+
priority,
|
165
|
+
completion_date,
|
166
|
+
creation_date,
|
167
|
+
description,
|
168
|
+
additions,
|
169
|
+
]
|
170
|
+
)
|
171
|
+
)
|
172
|
+
return "\n".join(results)
|
173
|
+
|
174
|
+
|
175
|
+
def _date_to_str(date: datetime.date | None) -> str:
|
176
|
+
if date is None:
|
177
|
+
return "".ljust(14)
|
178
|
+
return date.strftime("%a %Y-%m-%d")
|
179
|
+
|
180
|
+
|
181
|
+
def _get_todo_txt_content() -> str:
|
182
|
+
todo_file_path = os.path.join(TODO_DIR, "todo.txt")
|
183
|
+
if not os.path.isfile(todo_file_path):
|
184
|
+
return ""
|
185
|
+
with open(todo_file_path, "r") as f:
|
186
|
+
return f.read()
|
zrb/callback/any_callback.py
CHANGED
zrb/callback/callback.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
from typing import Any
|
2
2
|
|
3
|
-
from
|
4
|
-
from
|
5
|
-
from
|
6
|
-
from
|
7
|
-
from .
|
3
|
+
from zrb.attr.type import StrDictAttr
|
4
|
+
from zrb.callback.any_callback import AnyCallback
|
5
|
+
from zrb.session.any_session import AnySession
|
6
|
+
from zrb.task.any_task import AnyTask
|
7
|
+
from zrb.util.attr import get_str_dict_attr
|
8
8
|
|
9
9
|
|
10
10
|
class Callback(AnyCallback):
|
zrb/cmd/cmd_val.py
CHANGED
zrb/config.py
CHANGED
@@ -3,7 +3,7 @@ import logging
|
|
3
3
|
import os
|
4
4
|
import platform
|
5
5
|
|
6
|
-
from .util.string.conversion import to_boolean
|
6
|
+
from zrb.util.string.conversion import to_boolean
|
7
7
|
|
8
8
|
|
9
9
|
def _get_current_shell() -> str:
|
@@ -53,8 +53,11 @@ SHOW_PROMPT = to_boolean(os.getenv("ZRB_SHOW_PROMPT", "1"))
|
|
53
53
|
SESSION_LOG_DIR = os.getenv(
|
54
54
|
"ZRB_SESSION_LOG_DIR", os.path.expanduser(os.path.join("~", ".zrb-session"))
|
55
55
|
)
|
56
|
+
TODO_DIR = os.getenv("ZRB_TODO_DIR", os.path.expanduser(os.path.join("~", "todo")))
|
56
57
|
VERSION = metadata.version("zrb")
|
57
58
|
WEB_HTTP_PORT = int(os.getenv("ZRB_WEB_HTTP_PORT", "21213"))
|
59
|
+
LLM_MODEL = os.getenv("ZRB_LLM_MODEL", "ollama_chat/llama3.1")
|
60
|
+
LLM_SYSTEM_PROMPT = os.getenv("ZRB_LLM_SYSTEM_PROMPT", "You are a helpful assistant")
|
58
61
|
|
59
62
|
BANNER = f"""
|
60
63
|
bb
|
@@ -2,8 +2,8 @@ import fnmatch
|
|
2
2
|
import re
|
3
3
|
from collections.abc import Callable
|
4
4
|
|
5
|
-
from
|
6
|
-
from .
|
5
|
+
from zrb.content_transformer.any_content_transformer import AnyContentTransformer
|
6
|
+
from zrb.context.any_context import AnyContext
|
7
7
|
|
8
8
|
|
9
9
|
class ContentTransformer(AnyContentTransformer):
|
zrb/context/any_context.py
CHANGED
@@ -3,11 +3,11 @@ from __future__ import annotations # Enables forward references
|
|
3
3
|
from abc import ABC, abstractmethod
|
4
4
|
from typing import TYPE_CHECKING, Any
|
5
5
|
|
6
|
-
from
|
7
|
-
from
|
6
|
+
from zrb.dot_dict.dot_dict import DotDict
|
7
|
+
from zrb.xcom.xcom import Xcom
|
8
8
|
|
9
9
|
if TYPE_CHECKING:
|
10
|
-
from
|
10
|
+
from zrb.session import any_session
|
11
11
|
|
12
12
|
|
13
13
|
class AnySharedContext(ABC):
|
zrb/context/context.py
CHANGED
@@ -4,12 +4,12 @@ import re
|
|
4
4
|
import sys
|
5
5
|
from typing import Any, TextIO
|
6
6
|
|
7
|
-
from
|
8
|
-
from
|
9
|
-
from
|
10
|
-
from
|
11
|
-
from .
|
12
|
-
from .
|
7
|
+
from zrb.context.any_context import AnyContext
|
8
|
+
from zrb.context.any_shared_context import AnySharedContext
|
9
|
+
from zrb.dot_dict.dot_dict import DotDict
|
10
|
+
from zrb.session.any_session import AnySession
|
11
|
+
from zrb.util.cli.style import stylize, stylize_error, stylize_log, stylize_warning
|
12
|
+
from zrb.util.string.conversion import to_boolean
|
13
13
|
|
14
14
|
|
15
15
|
def _remove_ansi_escape_sequences(text):
|
@@ -103,14 +103,16 @@ class Context(AnyContext):
|
|
103
103
|
):
|
104
104
|
color = self._color
|
105
105
|
icon = self._icon
|
106
|
-
|
106
|
+
max_name_length = max(len(name) + len(icon) for name in self.session.task_names)
|
107
|
+
styled_task_name = f"{icon} {self._task_name}"
|
108
|
+
padded_styled_task_name = styled_task_name.rjust(max_name_length + 1)
|
107
109
|
if self._attempt == 0:
|
108
110
|
attempt_status = "".ljust(5)
|
109
111
|
else:
|
110
112
|
attempt_status = f"{self._attempt}/{self._max_attempt}".ljust(5)
|
111
113
|
now = datetime.datetime.now()
|
112
114
|
formatted_time = now.strftime("%y%m%d %H:%M:%S.%f")[:19]
|
113
|
-
prefix = f"{formatted_time} {attempt_status} {
|
115
|
+
prefix = f"{formatted_time} {attempt_status} {padded_styled_task_name} ⬤ "
|
114
116
|
message = sep.join([f"{value}" for value in values])
|
115
117
|
self.append_to_shared_log(_remove_ansi_escape_sequences(f"{prefix} {message}"))
|
116
118
|
stylized_prefix = stylize(prefix, color=color)
|
zrb/context/shared_context.py
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
import datetime
|
2
2
|
from typing import Any
|
3
3
|
|
4
|
-
from
|
5
|
-
from
|
6
|
-
from
|
7
|
-
from
|
4
|
+
from zrb.config import LOGGING_LEVEL
|
5
|
+
from zrb.context.any_shared_context import AnySharedContext
|
6
|
+
from zrb.dot_dict.dot_dict import DotDict
|
7
|
+
from zrb.session.any_session import AnySession
|
8
|
+
from zrb.util.string.conversion import (
|
9
|
+
double_quote,
|
8
10
|
to_boolean,
|
9
11
|
to_camel_case,
|
10
12
|
to_human_case,
|
@@ -12,9 +14,8 @@ from ..util.string.conversion import (
|
|
12
14
|
to_pascal_case,
|
13
15
|
to_snake_case,
|
14
16
|
)
|
15
|
-
from
|
16
|
-
from
|
17
|
-
from .any_shared_context import AnySharedContext
|
17
|
+
from zrb.util.string.format import fstring_format
|
18
|
+
from zrb.xcom.xcom import Xcom
|
18
19
|
|
19
20
|
|
20
21
|
class SharedContext(AnySharedContext):
|
@@ -86,12 +87,12 @@ class SharedContext(AnySharedContext):
|
|
86
87
|
data={
|
87
88
|
"ctx": self,
|
88
89
|
"datetime": datetime,
|
89
|
-
"Xcom": Xcom,
|
90
90
|
"to_boolean": to_boolean,
|
91
91
|
"to_camel_case": to_camel_case,
|
92
92
|
"to_human_case": to_human_case,
|
93
93
|
"to_kebab_case": to_kebab_case,
|
94
94
|
"to_pascal_case": to_pascal_case,
|
95
95
|
"to_snake_case": to_snake_case,
|
96
|
+
"double_quote": double_quote,
|
96
97
|
},
|
97
98
|
)
|
zrb/env/__init__.py
CHANGED
zrb/env/any_env.py
CHANGED
zrb/env/env.py
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
import os
|
2
2
|
|
3
|
+
from zrb.attr.type import StrAttr
|
3
4
|
from zrb.context.any_shared_context import AnySharedContext
|
4
|
-
|
5
|
-
from
|
6
|
-
from ..util.attr import get_str_attr
|
7
|
-
from .any_env import AnyEnv
|
5
|
+
from zrb.env.any_env import AnyEnv
|
6
|
+
from zrb.util.attr import get_str_attr
|
8
7
|
|
9
8
|
|
10
9
|
class Env(AnyEnv):
|
zrb/env/env_file.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
from dotenv import dotenv_values
|
2
2
|
|
3
|
-
from
|
4
|
-
from
|
5
|
-
from
|
6
|
-
from .
|
3
|
+
from zrb.attr.type import StrAttr
|
4
|
+
from zrb.context.shared_context import SharedContext
|
5
|
+
from zrb.env.env_map import EnvMap
|
6
|
+
from zrb.util.attr import get_str_attr
|
7
7
|
|
8
8
|
|
9
9
|
class EnvFile(EnvMap):
|
zrb/env/env_map.py
CHANGED
zrb/group/__init__.py
CHANGED
zrb/group/any_group.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
from abc import ABC, abstractmethod
|
2
|
-
from typing import Optional
|
2
|
+
from typing import Optional, Union
|
3
3
|
|
4
|
-
from
|
4
|
+
from zrb.task.any_task import AnyTask
|
5
5
|
|
6
6
|
|
7
7
|
class AnyGroup(ABC):
|
@@ -36,7 +36,7 @@ class AnyGroup(ABC):
|
|
36
36
|
pass
|
37
37
|
|
38
38
|
@abstractmethod
|
39
|
-
def add_group(self, group: "AnyGroup") -> "AnyGroup":
|
39
|
+
def add_group(self, group: Union["AnyGroup", str]) -> "AnyGroup":
|
40
40
|
pass
|
41
41
|
|
42
42
|
@abstractmethod
|
zrb/group/group.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
from
|
2
|
-
from .
|
1
|
+
from zrb.group.any_group import AnyGroup
|
2
|
+
from zrb.task.any_task import AnyTask
|
3
3
|
|
4
4
|
|
5
5
|
class Group(AnyGroup):
|
@@ -42,10 +42,11 @@ class Group(AnyGroup):
|
|
42
42
|
alias.sort()
|
43
43
|
return {name: self._tasks.get(name) for name in alias}
|
44
44
|
|
45
|
-
def add_group(self, group: AnyGroup, alias: str | None = None) -> AnyGroup:
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
def add_group(self, group: AnyGroup | str, alias: str | None = None) -> AnyGroup:
|
46
|
+
real_group = Group(group) if isinstance(group, str) else group
|
47
|
+
alias = alias if alias is not None else real_group.name
|
48
|
+
self._groups[alias] = real_group
|
49
|
+
return real_group
|
49
50
|
|
50
51
|
def add_task(self, task: AnyTask, alias: str | None = None) -> AnyTask:
|
51
52
|
alias = alias if alias is not None else task.name
|
zrb/input/any_input.py
CHANGED
zrb/input/base_input.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
from typing import Any
|
2
2
|
|
3
|
-
from
|
4
|
-
from
|
5
|
-
from
|
6
|
-
from .
|
3
|
+
from zrb.attr.type import StrAttr
|
4
|
+
from zrb.context.any_shared_context import AnySharedContext
|
5
|
+
from zrb.input.any_input import AnyInput
|
6
|
+
from zrb.util.attr import get_str_attr
|
7
7
|
|
8
8
|
|
9
9
|
class BaseInput(AnyInput):
|
zrb/input/bool_input.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
from
|
2
|
-
from
|
3
|
-
from
|
4
|
-
from .
|
1
|
+
from zrb.attr.type import StrAttr
|
2
|
+
from zrb.context.any_shared_context import AnySharedContext
|
3
|
+
from zrb.input.base_input import BaseInput
|
4
|
+
from zrb.util.string.conversion import to_boolean
|
5
5
|
|
6
6
|
|
7
|
-
class
|
7
|
+
class BoolInput(BaseInput):
|
8
8
|
def __init__(
|
9
9
|
self,
|
10
10
|
name: str,
|
zrb/input/float_input.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
from
|
2
|
-
from
|
3
|
-
from .base_input import BaseInput
|
1
|
+
from zrb.attr.type import StrAttr
|
2
|
+
from zrb.context.any_shared_context import AnySharedContext
|
3
|
+
from zrb.input.base_input import BaseInput
|
4
4
|
|
5
5
|
|
6
6
|
class FloatInput(BaseInput):
|
zrb/input/int_input.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
from
|
2
|
-
from
|
3
|
-
from .base_input import BaseInput
|
1
|
+
from zrb.attr.type import StrAttr
|
2
|
+
from zrb.context.any_shared_context import AnySharedContext
|
3
|
+
from zrb.input.base_input import BaseInput
|
4
4
|
|
5
5
|
|
6
6
|
class IntInput(BaseInput):
|
@@ -0,0 +1,51 @@
|
|
1
|
+
from zrb.attr.type import StrAttr, StrListAttr
|
2
|
+
from zrb.context.any_shared_context import AnySharedContext
|
3
|
+
from zrb.input.base_input import BaseInput
|
4
|
+
from zrb.util.attr import get_str_list_attr
|
5
|
+
|
6
|
+
|
7
|
+
class OptionInput(BaseInput):
|
8
|
+
def __init__(
|
9
|
+
self,
|
10
|
+
name: str,
|
11
|
+
description: str | None = None,
|
12
|
+
prompt: str | None = None,
|
13
|
+
options: StrListAttr = [],
|
14
|
+
default_str: StrAttr = "",
|
15
|
+
auto_render: bool = True,
|
16
|
+
allow_empty: bool = True,
|
17
|
+
):
|
18
|
+
super().__init__(
|
19
|
+
name=name,
|
20
|
+
description=description,
|
21
|
+
prompt=prompt,
|
22
|
+
default_str=default_str,
|
23
|
+
auto_render=auto_render,
|
24
|
+
allow_empty=allow_empty,
|
25
|
+
)
|
26
|
+
self._options = options
|
27
|
+
|
28
|
+
def to_html(self, ctx: AnySharedContext) -> str:
|
29
|
+
name = self.name
|
30
|
+
description = self.description
|
31
|
+
default = self._get_default_str(ctx)
|
32
|
+
html = [f'<select name="{name}" placeholder="{description}">']
|
33
|
+
for value in get_str_list_attr(ctx, self._options, self._auto_render):
|
34
|
+
selected = "selected" if value == default else ""
|
35
|
+
html.append(f'<option value="{value}" {selected}>{value}</option>')
|
36
|
+
html.append("</select>")
|
37
|
+
return "\n".join(html)
|
38
|
+
|
39
|
+
def _prompt_cli_str(self, shared_ctx: AnySharedContext) -> str:
|
40
|
+
prompt_message = self.prompt_message
|
41
|
+
default_value = self._get_default_str(shared_ctx)
|
42
|
+
options = get_str_list_attr(shared_ctx, self._options, self._auto_render)
|
43
|
+
option_str = ", ".join(options)
|
44
|
+
if default_value != "":
|
45
|
+
prompt_message = f"{prompt_message} ({option_str}) [{default_value}]"
|
46
|
+
value = input(f"{prompt_message}: ")
|
47
|
+
if value.strip() != "" and value.strip() not in options:
|
48
|
+
value = self._prompt_cli_str(shared_ctx)
|
49
|
+
if value.strip() == "":
|
50
|
+
value = default_value
|
51
|
+
return value
|
zrb/input/password_input.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import getpass
|
2
2
|
from collections.abc import Callable
|
3
3
|
|
4
|
-
from
|
5
|
-
from .base_input import BaseInput
|
4
|
+
from zrb.context.any_shared_context import AnySharedContext
|
5
|
+
from zrb.input.base_input import BaseInput
|
6
6
|
|
7
7
|
|
8
8
|
class PasswordInput(BaseInput):
|
zrb/input/str_input.py
CHANGED
zrb/input/text_input.py
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
import os
|
1
2
|
import subprocess
|
2
3
|
import tempfile
|
3
4
|
from collections.abc import Callable
|
4
5
|
|
5
|
-
from
|
6
|
-
from
|
7
|
-
from .base_input import BaseInput
|
6
|
+
from zrb.config import DEFAULT_EDITOR
|
7
|
+
from zrb.context.any_shared_context import AnySharedContext
|
8
|
+
from zrb.input.base_input import BaseInput
|
8
9
|
|
9
10
|
|
10
11
|
class TextInput(BaseInput):
|
@@ -66,14 +67,15 @@ class TextInput(BaseInput):
|
|
66
67
|
|
67
68
|
def _prompt_cli_str(self, shared_ctx: AnySharedContext) -> str:
|
68
69
|
prompt_message = (
|
69
|
-
f"{self.comment_start}{super().prompt_message}{self.comment_end}
|
70
|
+
f"{self.comment_start}{super().prompt_message}{self.comment_end}"
|
70
71
|
)
|
72
|
+
prompt_message_eol = f"{prompt_message}\n"
|
71
73
|
default_value = self._get_default_str(shared_ctx)
|
72
74
|
with tempfile.NamedTemporaryFile(
|
73
75
|
delete=False, suffix=self._extension
|
74
76
|
) as temp_file:
|
75
77
|
temp_file_name = temp_file.name
|
76
|
-
temp_file.write(
|
78
|
+
temp_file.write(prompt_message_eol.encode())
|
77
79
|
# Pre-fill with default content
|
78
80
|
if default_value:
|
79
81
|
temp_file.write(default_value.encode())
|
@@ -82,8 +84,8 @@ class TextInput(BaseInput):
|
|
82
84
|
subprocess.call([self._editor, temp_file_name])
|
83
85
|
# Read the edited content
|
84
86
|
with open(temp_file_name, "r") as temp_file:
|
85
|
-
edited_content = temp_file.read()
|
86
|
-
parts = edited_content.split(prompt_message)
|
87
|
-
|
88
|
-
|
89
|
-
return edited_content
|
87
|
+
edited_content = temp_file.read()
|
88
|
+
parts = [text.strip() for text in edited_content.split(prompt_message, 1)]
|
89
|
+
edited_content = "\n".join(parts).lstrip()
|
90
|
+
os.remove(temp_file_name)
|
91
|
+
return edited_content
|