zrb 0.15.0__py3-none-any.whl → 0.17.0__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 +5 -0
- zrb/__main__.py +0 -3
- zrb/action/runner.py +12 -3
- zrb/advertisement.py +4 -0
- zrb/builtin/_helper/reccuring_action.py +0 -23
- zrb/builtin/devtool/install/_input.py +2 -4
- zrb/builtin/devtool/install/helix/resource/config.toml +2 -1
- zrb/builtin/process/pid/get_by_name.py +1 -1
- zrb/builtin/project/create/template/project.sh +1 -0
- zrb/builtin/schedule.py +14 -10
- zrb/builtin/watch_changes.py +15 -14
- zrb/config/config.py +21 -14
- zrb/helper/accessories/color.py +5 -2
- zrb/helper/accessories/icon.py +4 -0
- zrb/helper/accessories/name.py +4 -0
- zrb/helper/accessories/untyped_color.py +10 -0
- zrb/helper/advertisement.py +3 -0
- zrb/helper/callable.py +9 -1
- zrb/helper/cli.py +2 -0
- zrb/helper/codemod/add_argument_to_function.py +6 -0
- zrb/helper/codemod/add_argument_to_function_call.py +6 -0
- zrb/helper/codemod/add_assert_resource.py +4 -0
- zrb/helper/codemod/add_function_call.py +4 -0
- zrb/helper/codemod/add_import_module.py +4 -0
- zrb/helper/codemod/add_key_value_to_dict.py +6 -0
- zrb/helper/codemod/add_property_to_class.py +6 -0
- zrb/helper/codemod/add_upstream_to_task.py +4 -0
- zrb/helper/codemod/append_code_to_function.py +6 -0
- zrb/helper/codemod/format_code.py +4 -0
- zrb/helper/default_env.py +2 -0
- zrb/helper/docker_compose/fetch_external_env.py +6 -0
- zrb/helper/docker_compose/file.py +4 -0
- zrb/helper/docstring.py +5 -0
- zrb/helper/env_map/fetch.py +4 -0
- zrb/helper/file/copy_tree.py +3 -0
- zrb/helper/file/match.py +4 -0
- zrb/helper/file/text.py +4 -0
- zrb/helper/git/detect_changes.py +4 -0
- zrb/helper/loader/load_module.py +2 -0
- zrb/helper/log.py +1 -1
- zrb/helper/map/conversion.py +4 -0
- zrb/helper/python_task.py +3 -0
- zrb/helper/render_data.py +4 -0
- zrb/helper/string/conversion.py +13 -36
- zrb/helper/string/jinja.py +4 -0
- zrb/helper/string/modification.py +4 -0
- zrb/helper/string/parse_replacement.py +4 -0
- zrb/helper/string/untyped_conversion.py +49 -0
- zrb/helper/task.py +4 -0
- zrb/helper/typecheck.py +6 -7
- zrb/helper/typing.py +32 -12
- zrb/helper/util.py +4 -0
- zrb/runner.py +3 -0
- zrb/task/any_task.py +5 -0
- zrb/task/any_task_event_handler.py +4 -0
- zrb/task/base_remote_cmd_task.py +4 -0
- zrb/task/base_task/base_task.py +5 -1
- zrb/task/checker.py +7 -3
- zrb/task/cmd_task.py +14 -2
- zrb/task/decorator.py +4 -0
- zrb/task/docker_compose_task.py +4 -0
- zrb/task/flow_task.py +4 -0
- zrb/task/http_checker.py +14 -1
- zrb/task/looper.py +40 -0
- zrb/task/notifier.py +4 -0
- zrb/task/parallel.py +4 -0
- zrb/task/path_checker.py +14 -1
- zrb/task/path_watcher.py +65 -41
- zrb/task/port_checker.py +14 -1
- zrb/task/recurring_task.py +5 -0
- zrb/task/remote_cmd_task.py +4 -0
- zrb/task/resource_maker.py +14 -1
- zrb/task/rsync_task.py +4 -0
- zrb/task/server.py +190 -0
- zrb/task/task.py +4 -0
- zrb/task/time_watcher.py +50 -18
- zrb/task/watcher.py +100 -0
- zrb/task/wiki_task.py +4 -0
- zrb/task_env/constant.py +5 -0
- zrb/task_env/env.py +4 -0
- zrb/task_env/env_file.py +4 -0
- zrb/task_group/group.py +4 -0
- zrb/task_input/any_input.py +4 -0
- zrb/task_input/base_input.py +4 -0
- zrb/task_input/bool_input.py +4 -0
- zrb/task_input/choice_input.py +4 -0
- zrb/task_input/constant.py +5 -0
- zrb/task_input/float_input.py +4 -0
- zrb/task_input/int_input.py +4 -0
- zrb/task_input/password_input.py +4 -0
- zrb/task_input/str_input.py +4 -0
- zrb/task_input/task_input.py +4 -0
- {zrb-0.15.0.dist-info → zrb-0.17.0.dist-info}/METADATA +1 -1
- {zrb-0.15.0.dist-info → zrb-0.17.0.dist-info}/RECORD +97 -92
- {zrb-0.15.0.dist-info → zrb-0.17.0.dist-info}/LICENSE +0 -0
- {zrb-0.15.0.dist-info → zrb-0.17.0.dist-info}/WHEEL +0 -0
- {zrb-0.15.0.dist-info → zrb-0.17.0.dist-info}/entry_points.txt +0 -0
zrb/task/notifier.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
import os
|
2
2
|
import subprocess
|
3
3
|
|
4
|
+
from zrb.helper.accessories.color import colored
|
4
5
|
from zrb.helper.accessories.icon import get_random_icon
|
6
|
+
from zrb.helper.log import logger
|
5
7
|
from zrb.helper.string.modification import double_quote
|
6
8
|
from zrb.helper.typecheck import typechecked
|
7
9
|
from zrb.helper.typing import Any, Callable, Iterable, JinjaTemplate, Optional, Union
|
@@ -21,6 +23,8 @@ from zrb.task_env.env_file import EnvFile
|
|
21
23
|
from zrb.task_group.group import Group
|
22
24
|
from zrb.task_input.any_input import AnyInput
|
23
25
|
|
26
|
+
logger.debug(colored("Loading zrb.task.notifier", attrs=["dark"]))
|
27
|
+
|
24
28
|
_CURRENT_DIR = os.path.dirname(__file__)
|
25
29
|
_NOTIFY_PS1_PATH = os.path.realpath(
|
26
30
|
os.path.abspath(
|
zrb/task/parallel.py
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
from abc import ABC, abstractmethod
|
2
2
|
|
3
|
+
from zrb.helper.accessories.color import colored
|
4
|
+
from zrb.helper.log import logger
|
3
5
|
from zrb.helper.typecheck import typechecked
|
4
6
|
from zrb.helper.typing import List, TypeVar, Union
|
5
7
|
from zrb.task.any_task import AnyTask
|
6
8
|
|
9
|
+
logger.debug(colored("Loading zrb.task.parallel", attrs=["dark"]))
|
10
|
+
|
7
11
|
TParallel = TypeVar("TParallel", bound="Parallel")
|
8
12
|
|
9
13
|
|
zrb/task/path_checker.py
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
+
from zrb.helper.accessories.color import colored
|
1
2
|
from zrb.helper.file.match import get_file_names
|
3
|
+
from zrb.helper.log import logger
|
2
4
|
from zrb.helper.typecheck import typechecked
|
3
5
|
from zrb.helper.typing import (
|
4
6
|
Any,
|
@@ -26,6 +28,8 @@ from zrb.task_env.env_file import EnvFile
|
|
26
28
|
from zrb.task_group.group import Group
|
27
29
|
from zrb.task_input.any_input import AnyInput
|
28
30
|
|
31
|
+
logger.debug(colored("Loading zrb.task.path_checker", attrs=["dark"]))
|
32
|
+
|
29
33
|
TPathChecker = TypeVar("TPathChecker", bound="PathChecker")
|
30
34
|
|
31
35
|
|
@@ -95,8 +99,17 @@ class PathChecker(Checker):
|
|
95
99
|
raise_error: bool = True,
|
96
100
|
is_async: bool = False,
|
97
101
|
show_done_info: bool = True,
|
102
|
+
should_clear_xcom: bool = False,
|
103
|
+
should_stop_looper: bool = False,
|
98
104
|
) -> Callable[..., bool]:
|
99
|
-
return super().to_function(
|
105
|
+
return super().to_function(
|
106
|
+
env_prefix=env_prefix,
|
107
|
+
raise_error=raise_error,
|
108
|
+
is_async=is_async,
|
109
|
+
show_done_info=show_done_info,
|
110
|
+
should_clear_xcom=should_clear_xcom,
|
111
|
+
should_stop_looper=should_stop_looper,
|
112
|
+
)
|
100
113
|
|
101
114
|
async def run(self, *args: Any, **kwargs: Any) -> bool:
|
102
115
|
self._rendered_path = self.render_str(self._path)
|
zrb/task/path_watcher.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
import os
|
2
2
|
|
3
|
+
from zrb.helper.accessories.color import colored
|
3
4
|
from zrb.helper.file.match import get_file_names
|
5
|
+
from zrb.helper.log import logger
|
4
6
|
from zrb.helper.typecheck import typechecked
|
5
7
|
from zrb.helper.typing import (
|
6
8
|
Any,
|
@@ -23,17 +25,19 @@ from zrb.task.any_task_event_handler import (
|
|
23
25
|
OnTriggered,
|
24
26
|
OnWaiting,
|
25
27
|
)
|
26
|
-
from zrb.task.
|
28
|
+
from zrb.task.watcher import Watcher
|
27
29
|
from zrb.task_env.env import Env
|
28
30
|
from zrb.task_env.env_file import EnvFile
|
29
31
|
from zrb.task_group.group import Group
|
30
32
|
from zrb.task_input.any_input import AnyInput
|
31
33
|
|
34
|
+
logger.debug(colored("Loading zrb.task.path_watcher", attrs=["dark"]))
|
35
|
+
|
32
36
|
TPathWatcher = TypeVar("TPathWatcher", bound="PathWatcher")
|
33
37
|
|
34
38
|
|
35
39
|
@typechecked
|
36
|
-
class PathWatcher(
|
40
|
+
class PathWatcher(Watcher):
|
37
41
|
"""
|
38
42
|
PathWatcher will wait for any changes specified on path.
|
39
43
|
|
@@ -45,6 +49,8 @@ class PathWatcher(Checker):
|
|
45
49
|
- <task-name>.deleted-file
|
46
50
|
"""
|
47
51
|
|
52
|
+
__init_times: Mapping[str, Mapping[str, float]] = {}
|
53
|
+
|
48
54
|
def __init__(
|
49
55
|
self,
|
50
56
|
name: str = "watch-path",
|
@@ -73,7 +79,7 @@ class PathWatcher(Checker):
|
|
73
79
|
watch_deleted_files: bool = True,
|
74
80
|
should_execute: Union[bool, JinjaTemplate, Callable[..., bool]] = True,
|
75
81
|
):
|
76
|
-
|
82
|
+
Watcher.__init__(
|
77
83
|
self,
|
78
84
|
name=name,
|
79
85
|
group=group,
|
@@ -103,7 +109,6 @@ class PathWatcher(Checker):
|
|
103
109
|
self._watch_deleted_files = watch_deleted_files
|
104
110
|
self._rendered_path: str = ""
|
105
111
|
self._rendered_ignored_paths: List[str] = []
|
106
|
-
self._init_times: Mapping[str, float] = {}
|
107
112
|
|
108
113
|
def copy(self) -> TPathWatcher:
|
109
114
|
return super().copy()
|
@@ -114,8 +119,17 @@ class PathWatcher(Checker):
|
|
114
119
|
raise_error: bool = True,
|
115
120
|
is_async: bool = False,
|
116
121
|
show_done_info: bool = True,
|
122
|
+
should_clear_xcom: bool = False,
|
123
|
+
should_stop_looper: bool = False,
|
117
124
|
) -> Callable[..., bool]:
|
118
|
-
return super().to_function(
|
125
|
+
return super().to_function(
|
126
|
+
env_prefix=env_prefix,
|
127
|
+
raise_error=raise_error,
|
128
|
+
is_async=is_async,
|
129
|
+
show_done_info=show_done_info,
|
130
|
+
should_clear_xcom=should_clear_xcom,
|
131
|
+
should_stop_looper=should_stop_looper,
|
132
|
+
)
|
119
133
|
|
120
134
|
async def run(self, *args: Any, **kwargs: Any) -> bool:
|
121
135
|
self._rendered_path = self.render_str(self._path)
|
@@ -124,7 +138,9 @@ class PathWatcher(Checker):
|
|
124
138
|
for ignored_path in self._get_rendered_ignored_paths()
|
125
139
|
if ignored_path != ""
|
126
140
|
]
|
127
|
-
|
141
|
+
identifier = self.get_identifier()
|
142
|
+
if identifier not in self.__init_times:
|
143
|
+
self.__init_times[identifier] = self._get_mod_times()
|
128
144
|
return await super().run(*args, **kwargs)
|
129
145
|
|
130
146
|
def _get_rendered_ignored_paths(self) -> List[str]:
|
@@ -132,41 +148,49 @@ class PathWatcher(Checker):
|
|
132
148
|
return [self.render_str(self._ignored_path)]
|
133
149
|
return [self.render_str(ignored_path) for ignored_path in self._ignored_path]
|
134
150
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
151
|
+
def create_loop_inspector(self) -> Callable[..., Optional[bool]]:
|
152
|
+
def loop_inspect() -> bool:
|
153
|
+
label = f"Watching {self._rendered_path}"
|
154
|
+
identifier = self.get_identifier()
|
155
|
+
try:
|
156
|
+
init_times = self.__init_times[identifier]
|
157
|
+
mod_times = self._get_mod_times()
|
158
|
+
except Exception as e:
|
159
|
+
self.show_progress(f"{label} Cannot inspect")
|
160
|
+
raise e
|
161
|
+
# watch changes
|
162
|
+
if self._watch_new_files:
|
163
|
+
new_files = mod_times.keys() - init_times.keys()
|
164
|
+
for file in new_files:
|
165
|
+
self.print_out_dark(f"{label} [+] New file detected: {file}")
|
166
|
+
self.set_task_xcom("new-file", file)
|
167
|
+
self.set_task_xcom("file", file)
|
168
|
+
self.__init_times[identifier] = self._get_mod_times()
|
169
|
+
return True
|
170
|
+
if self._watch_deleted_files:
|
171
|
+
deleted_files = init_times.keys() - mod_times.keys()
|
172
|
+
for file in deleted_files:
|
173
|
+
self.print_out_dark(f"{label} [-] File deleted: {file}")
|
174
|
+
self.set_task_xcom("deleted-file", file)
|
175
|
+
self.set_task_xcom("file", file)
|
176
|
+
self.__init_times[identifier] = self._get_mod_times()
|
177
|
+
return True
|
178
|
+
if self._watch_modified_files:
|
179
|
+
modified_files = {
|
180
|
+
file
|
181
|
+
for file, mod_time in mod_times.items()
|
182
|
+
if file in mod_times and init_times[file] != mod_time
|
183
|
+
}
|
184
|
+
for file in modified_files:
|
185
|
+
self.print_out_dark(f"{label} [/] File modified: {file}")
|
186
|
+
self.set_task_xcom("modified-file", file)
|
187
|
+
self.set_task_xcom("file", file)
|
188
|
+
self.__init_times[identifier] = self._get_mod_times()
|
189
|
+
return True
|
190
|
+
self.show_progress(f"{label} (Nothing changed)")
|
191
|
+
return False
|
192
|
+
|
193
|
+
return loop_inspect
|
170
194
|
|
171
195
|
def _get_mod_times(self) -> Mapping[str, float]:
|
172
196
|
matches = get_file_names(
|
zrb/task/port_checker.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
import socket
|
2
2
|
|
3
|
+
from zrb.helper.accessories.color import colored
|
4
|
+
from zrb.helper.log import logger
|
3
5
|
from zrb.helper.typecheck import typechecked
|
4
6
|
from zrb.helper.typing import (
|
5
7
|
Any,
|
@@ -26,6 +28,8 @@ from zrb.task_env.env_file import EnvFile
|
|
26
28
|
from zrb.task_group.group import Group
|
27
29
|
from zrb.task_input.any_input import AnyInput
|
28
30
|
|
31
|
+
logger.debug(colored("Loading zrb.task.port_checker", attrs=["dark"]))
|
32
|
+
|
29
33
|
TPortChecker = TypeVar("TPortChecker", bound="PortChecker")
|
30
34
|
|
31
35
|
|
@@ -105,8 +109,17 @@ class PortChecker(Checker):
|
|
105
109
|
raise_error: bool = True,
|
106
110
|
is_async: bool = False,
|
107
111
|
show_done_info: bool = True,
|
112
|
+
should_clear_xcom: bool = False,
|
113
|
+
should_stop_looper: bool = False,
|
108
114
|
) -> Callable[..., bool]:
|
109
|
-
return super().to_function(
|
115
|
+
return super().to_function(
|
116
|
+
env_prefix=env_prefix,
|
117
|
+
raise_error=raise_error,
|
118
|
+
is_async=is_async,
|
119
|
+
show_done_info=show_done_info,
|
120
|
+
should_clear_xcom=should_clear_xcom,
|
121
|
+
should_stop_looper=should_stop_looper,
|
122
|
+
)
|
110
123
|
|
111
124
|
async def run(self, *args: Any, **kwargs: Any) -> bool:
|
112
125
|
self._config = PortConfig(
|
zrb/task/recurring_task.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
import asyncio
|
2
2
|
import copy
|
3
3
|
|
4
|
+
from zrb.helper.accessories.color import colored
|
4
5
|
from zrb.helper.accessories.name import get_random_name
|
6
|
+
from zrb.helper.log import logger
|
5
7
|
from zrb.helper.typecheck import typechecked
|
6
8
|
from zrb.helper.typing import Any, Callable, Iterable, List, Mapping, Optional, Union
|
7
9
|
from zrb.task.any_task import AnyTask
|
@@ -20,6 +22,8 @@ from zrb.task_env.env_file import EnvFile
|
|
20
22
|
from zrb.task_group.group import Group
|
21
23
|
from zrb.task_input.any_input import AnyInput
|
22
24
|
|
25
|
+
logger.debug(colored("Loading zrb.task.recurring_task", attrs=["dark"]))
|
26
|
+
|
23
27
|
|
24
28
|
class RunConfig:
|
25
29
|
def __init__(
|
@@ -111,6 +115,7 @@ class RecurringTask(BaseTask):
|
|
111
115
|
self._triggers: List[AnyTask] = [trigger.copy() for trigger in triggers]
|
112
116
|
self._run_configs: List[RunConfig] = []
|
113
117
|
self._single_execution = single_execution
|
118
|
+
self.print_err("Deprecated, please use Server instead")
|
114
119
|
|
115
120
|
async def _set_keyval(self, kwargs: Mapping[str, Any], env_prefix: str):
|
116
121
|
await super()._set_keyval(kwargs=kwargs, env_prefix=env_prefix)
|
zrb/task/remote_cmd_task.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
import os
|
2
2
|
import pathlib
|
3
3
|
|
4
|
+
from zrb.helper.accessories.color import colored
|
5
|
+
from zrb.helper.log import logger
|
4
6
|
from zrb.helper.typecheck import typechecked
|
5
7
|
from zrb.helper.typing import Any, Callable, Iterable, Optional, Union
|
6
8
|
from zrb.task.any_task import AnyTask
|
@@ -20,6 +22,8 @@ from zrb.task_env.env_file import EnvFile
|
|
20
22
|
from zrb.task_group.group import Group
|
21
23
|
from zrb.task_input.any_input import AnyInput
|
22
24
|
|
25
|
+
logger.debug(colored("Loading zrb.task.remote_cmd_task", attrs=["dark"]))
|
26
|
+
|
23
27
|
_CURRENT_DIR = os.path.dirname(__file__)
|
24
28
|
_SHELL_SCRIPT_DIR = os.path.join(_CURRENT_DIR, "..", "shell-scripts")
|
25
29
|
with open(os.path.join(_SHELL_SCRIPT_DIR, "ssh-util.sh")) as file:
|
zrb/task/resource_maker.py
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
+
from zrb.helper.accessories.color import colored
|
1
2
|
from zrb.helper.file.copy_tree import copy_tree
|
3
|
+
from zrb.helper.log import logger
|
2
4
|
from zrb.helper.typecheck import typechecked
|
3
5
|
from zrb.helper.typing import (
|
4
6
|
Any,
|
@@ -35,6 +37,8 @@ from zrb.task_env.env_file import EnvFile
|
|
35
37
|
from zrb.task_group.group import Group
|
36
38
|
from zrb.task_input.any_input import AnyInput
|
37
39
|
|
40
|
+
logger.debug(colored("Loading zrb.task.resource_maker", attrs=["dark"]))
|
41
|
+
|
38
42
|
Replacement = Mapping[str, JinjaTemplate]
|
39
43
|
ReplacementMutator = Callable[[AnyTask, Replacement], Replacement]
|
40
44
|
TResourceMaker = TypeVar("TResourceMaker", bound="ResourceMaker")
|
@@ -140,8 +144,17 @@ class ResourceMaker(BaseTask):
|
|
140
144
|
raise_error: bool = True,
|
141
145
|
is_async: bool = False,
|
142
146
|
show_done_info: bool = True,
|
147
|
+
should_clear_xcom: bool = False,
|
148
|
+
should_stop_looper: bool = False,
|
143
149
|
) -> Callable[..., bool]:
|
144
|
-
return super().to_function(
|
150
|
+
return super().to_function(
|
151
|
+
env_prefix=env_prefix,
|
152
|
+
raise_error=raise_error,
|
153
|
+
is_async=is_async,
|
154
|
+
show_done_info=show_done_info,
|
155
|
+
should_clear_xcom=should_clear_xcom,
|
156
|
+
should_stop_looper=should_stop_looper,
|
157
|
+
)
|
145
158
|
|
146
159
|
async def run(self, *args: Any, **kwargs: Any) -> bool:
|
147
160
|
# render parameters
|
zrb/task/rsync_task.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
import os
|
2
2
|
import pathlib
|
3
3
|
|
4
|
+
from zrb.helper.accessories.color import colored
|
5
|
+
from zrb.helper.log import logger
|
4
6
|
from zrb.helper.typecheck import typechecked
|
5
7
|
from zrb.helper.typing import Any, Callable, Iterable, JinjaTemplate, Optional, Union
|
6
8
|
from zrb.task.any_task import AnyTask
|
@@ -20,6 +22,8 @@ from zrb.task_env.env_file import EnvFile
|
|
20
22
|
from zrb.task_group.group import Group
|
21
23
|
from zrb.task_input.any_input import AnyInput
|
22
24
|
|
25
|
+
logger.debug(colored("Loading zrb.task.rsync_task", attrs=["dark"]))
|
26
|
+
|
23
27
|
_CURRENT_DIR = os.path.dirname(__file__)
|
24
28
|
_SHELL_SCRIPT_DIR = os.path.join(_CURRENT_DIR, "..", "shell-scripts")
|
25
29
|
with open(os.path.join(_SHELL_SCRIPT_DIR, "rsync-util.sh")) as file:
|
zrb/task/server.py
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
import asyncio
|
2
|
+
|
3
|
+
from zrb.helper.accessories.color import colored
|
4
|
+
from zrb.helper.accessories.name import get_random_name
|
5
|
+
from zrb.helper.log import logger
|
6
|
+
from zrb.helper.typecheck import typechecked
|
7
|
+
from zrb.helper.typing import Any, Callable, Iterable, List, Mapping, Optional, Union
|
8
|
+
from zrb.helper.util import to_kebab_case
|
9
|
+
from zrb.task.any_task import AnyTask
|
10
|
+
from zrb.task.any_task_event_handler import (
|
11
|
+
OnFailed,
|
12
|
+
OnReady,
|
13
|
+
OnRetry,
|
14
|
+
OnSkipped,
|
15
|
+
OnStarted,
|
16
|
+
OnTriggered,
|
17
|
+
OnWaiting,
|
18
|
+
)
|
19
|
+
from zrb.task.base_task.base_task import BaseTask
|
20
|
+
from zrb.task.flow_task import FlowTask
|
21
|
+
from zrb.task_env.env import Env
|
22
|
+
from zrb.task_env.env_file import EnvFile
|
23
|
+
from zrb.task_group.group import Group
|
24
|
+
from zrb.task_input.any_input import AnyInput
|
25
|
+
|
26
|
+
logger.debug(colored("Loading zrb.task.server", attrs=["dark"]))
|
27
|
+
|
28
|
+
|
29
|
+
@typechecked
|
30
|
+
class Controller:
|
31
|
+
def __init__(
|
32
|
+
self,
|
33
|
+
trigger: Union[AnyTask, List[AnyTask]],
|
34
|
+
action: Union[AnyTask, List[AnyTask]],
|
35
|
+
name: Optional[str] = None,
|
36
|
+
):
|
37
|
+
self._name = get_random_name() if name is None else name
|
38
|
+
self._triggers = [trigger] if isinstance(trigger, AnyTask) else trigger
|
39
|
+
self._actions = [action] if isinstance(action, AnyTask) else action
|
40
|
+
self._args: List[Any] = []
|
41
|
+
self._kwargs: Mapping[str, Any] = {}
|
42
|
+
self._inputs: List[AnyInput] = []
|
43
|
+
self._envs: List[Env] = []
|
44
|
+
self._env_files: List[EnvFile] = []
|
45
|
+
|
46
|
+
def set_args(self, args: List[Any]):
|
47
|
+
self._args = args
|
48
|
+
|
49
|
+
def set_kwargs(self, kwargs: Mapping[str, Any]):
|
50
|
+
self._kwargs = kwargs
|
51
|
+
|
52
|
+
def set_inputs(self, inputs: List[AnyInput]):
|
53
|
+
self._inputs = inputs
|
54
|
+
|
55
|
+
def set_envs(self, envs: List[Env]):
|
56
|
+
self._envs = envs
|
57
|
+
|
58
|
+
def set_env_files(self, env_files: List[EnvFile]):
|
59
|
+
self._env_files = env_files
|
60
|
+
|
61
|
+
def get_sub_env_files(self) -> Iterable[EnvFile]:
|
62
|
+
env_files = []
|
63
|
+
for trigger in self._triggers:
|
64
|
+
env_files += trigger.copy()._get_env_files()
|
65
|
+
for action in self._actions:
|
66
|
+
env_files += action.copy()._get_env_files()
|
67
|
+
return env_files
|
68
|
+
|
69
|
+
def get_sub_envs(self) -> Iterable[Env]:
|
70
|
+
envs = []
|
71
|
+
for trigger in self._triggers:
|
72
|
+
envs += trigger.copy()._get_envs()
|
73
|
+
for action in self._actions:
|
74
|
+
envs += action.copy()._get_envs()
|
75
|
+
return envs
|
76
|
+
|
77
|
+
def get_sub_inputs(self) -> Iterable[AnyInput]:
|
78
|
+
inputs = []
|
79
|
+
for trigger in self._triggers:
|
80
|
+
inputs += trigger.copy()._get_combined_inputs()
|
81
|
+
for action in self._actions:
|
82
|
+
inputs += action.copy()._get_combined_inputs()
|
83
|
+
return inputs
|
84
|
+
|
85
|
+
def to_function(self) -> Callable[..., Any]:
|
86
|
+
task = self._get_task()
|
87
|
+
|
88
|
+
async def fn() -> Any:
|
89
|
+
task_fn = task.to_function(is_async=True)
|
90
|
+
return await task_fn(*self._args, **self._kwargs)
|
91
|
+
|
92
|
+
return fn
|
93
|
+
|
94
|
+
def _get_task(self) -> AnyTask:
|
95
|
+
actions = [action.copy() for action in self._actions]
|
96
|
+
actions.insert(0, self._get_remonitor_task())
|
97
|
+
triggers = [trigger.copy() for trigger in self._triggers]
|
98
|
+
task: AnyTask = FlowTask(
|
99
|
+
name=to_kebab_case(self._name),
|
100
|
+
inputs=self._inputs,
|
101
|
+
envs=self._envs,
|
102
|
+
env_files=self._env_files,
|
103
|
+
steps=[triggers, actions],
|
104
|
+
)
|
105
|
+
return task
|
106
|
+
|
107
|
+
def _get_remonitor_task(self) -> AnyTask:
|
108
|
+
async def on_ready(task: AnyTask):
|
109
|
+
task = self._get_task()
|
110
|
+
fn = task.to_function(is_async=True)
|
111
|
+
await fn()
|
112
|
+
|
113
|
+
return BaseTask(
|
114
|
+
name=f"monitor-{to_kebab_case(self._name)}",
|
115
|
+
on_ready=on_ready,
|
116
|
+
)
|
117
|
+
|
118
|
+
|
119
|
+
@typechecked
|
120
|
+
class Server(BaseTask):
|
121
|
+
|
122
|
+
def __init__(
|
123
|
+
self,
|
124
|
+
name: str,
|
125
|
+
controllers: List[Controller],
|
126
|
+
group: Optional[Group] = None,
|
127
|
+
inputs: Iterable[AnyInput] = [],
|
128
|
+
envs: Iterable[Env] = [],
|
129
|
+
env_files: Iterable[EnvFile] = [],
|
130
|
+
icon: Optional[str] = None,
|
131
|
+
color: Optional[str] = None,
|
132
|
+
description: str = "",
|
133
|
+
upstreams: Iterable[AnyTask] = [],
|
134
|
+
fallbacks: Iterable[AnyTask] = [],
|
135
|
+
on_triggered: Optional[OnTriggered] = None,
|
136
|
+
on_waiting: Optional[OnWaiting] = None,
|
137
|
+
on_skipped: Optional[OnSkipped] = None,
|
138
|
+
on_started: Optional[OnStarted] = None,
|
139
|
+
on_ready: Optional[OnReady] = None,
|
140
|
+
on_retry: Optional[OnRetry] = None,
|
141
|
+
on_failed: Optional[OnFailed] = None,
|
142
|
+
checkers: Iterable[AnyTask] = [],
|
143
|
+
checking_interval: float = 0,
|
144
|
+
retry: int = 0,
|
145
|
+
retry_interval: float = 1,
|
146
|
+
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
147
|
+
return_upstream_result: bool = False,
|
148
|
+
):
|
149
|
+
inputs, envs, env_files = list(inputs), list(envs), list(env_files)
|
150
|
+
for controller in controllers:
|
151
|
+
inputs += controller.get_sub_inputs()
|
152
|
+
envs += controller.get_sub_envs()
|
153
|
+
env_files += controller.get_sub_env_files()
|
154
|
+
BaseTask.__init__(
|
155
|
+
self,
|
156
|
+
name=name,
|
157
|
+
group=group,
|
158
|
+
inputs=inputs,
|
159
|
+
envs=envs,
|
160
|
+
env_files=env_files,
|
161
|
+
icon=icon,
|
162
|
+
color=color,
|
163
|
+
description=description,
|
164
|
+
upstreams=upstreams,
|
165
|
+
fallbacks=fallbacks,
|
166
|
+
on_triggered=on_triggered,
|
167
|
+
on_waiting=on_waiting,
|
168
|
+
on_skipped=on_skipped,
|
169
|
+
on_started=on_started,
|
170
|
+
on_ready=on_ready,
|
171
|
+
on_retry=on_retry,
|
172
|
+
on_failed=on_failed,
|
173
|
+
checkers=checkers,
|
174
|
+
checking_interval=checking_interval,
|
175
|
+
retry=retry,
|
176
|
+
retry_interval=retry_interval,
|
177
|
+
should_execute=should_execute,
|
178
|
+
return_upstream_result=return_upstream_result,
|
179
|
+
)
|
180
|
+
self._controllers = controllers
|
181
|
+
|
182
|
+
async def run(self, *args: Any, **kwargs: Any):
|
183
|
+
for controller in self._controllers:
|
184
|
+
controller.set_envs(self._get_envs())
|
185
|
+
controller.set_env_files(self._get_env_files())
|
186
|
+
controller.set_inputs(self._get_inputs())
|
187
|
+
controller.set_args(args)
|
188
|
+
controller.set_kwargs(kwargs)
|
189
|
+
functions = [controller.to_function() for controller in self._controllers]
|
190
|
+
await asyncio.gather(*[fn() for fn in functions])
|
zrb/task/task.py
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
from zrb.helper.accessories.color import colored
|
2
|
+
from zrb.helper.log import logger
|
1
3
|
from zrb.helper.typecheck import typechecked
|
2
4
|
from zrb.task.base_task.base_task import BaseTask
|
3
5
|
|
6
|
+
logger.debug(colored("Loading zrb.task.task", attrs=["dark"]))
|
7
|
+
|
4
8
|
|
5
9
|
@typechecked
|
6
10
|
class Task(BaseTask):
|