zrb 0.17.2__py3-none-any.whl → 0.18.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/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/component/rpc/messagebus/caller.py +1 -1
- zrb/task/any_task.py +3 -3
- zrb/task/base_remote_cmd_task.py +66 -8
- zrb/task/base_task/base_task.py +9 -10
- zrb/task/base_task/component/base_task_model.py +1 -1
- zrb/task/base_task/component/common_task_model.py +1 -1
- zrb/task/checker.py +1 -1
- zrb/task/cmd_task.py +1 -1
- zrb/task/decorator.py +1 -1
- zrb/task/docker_compose_task.py +1 -1
- zrb/task/flow_task.py +45 -34
- zrb/task/http_checker.py +1 -1
- zrb/task/notifier.py +1 -1
- zrb/task/path_checker.py +1 -1
- zrb/task/path_watcher.py +1 -1
- zrb/task/port_checker.py +1 -1
- zrb/task/recurring_task.py +2 -2
- zrb/task/remote_cmd_task.py +1 -1
- zrb/task/resource_maker.py +1 -1
- zrb/task/rsync_task.py +5 -5
- zrb/task/server.py +25 -18
- zrb/task/task.py +35 -1
- zrb/task/time_watcher.py +1 -1
- zrb/task/watcher.py +5 -2
- zrb/task_env/env.py +4 -3
- zrb/task_env/env_file.py +3 -2
- zrb/task_group/group.py +1 -1
- zrb/task_input/any_input.py +5 -3
- zrb/task_input/base_input.py +3 -3
- zrb/task_input/task_input.py +1 -1
- {zrb-0.17.2.dist-info → zrb-0.18.0.dist-info}/METADATA +14 -11
- {zrb-0.17.2.dist-info → zrb-0.18.0.dist-info}/RECORD +35 -35
- {zrb-0.17.2.dist-info → zrb-0.18.0.dist-info}/LICENSE +0 -0
- {zrb-0.17.2.dist-info → zrb-0.18.0.dist-info}/WHEEL +0 -0
- {zrb-0.17.2.dist-info → zrb-0.18.0.dist-info}/entry_points.txt +0 -0
zrb/task/any_task.py
CHANGED
@@ -25,11 +25,11 @@ TAnyTask = TypeVar("TAnyTask", bound="AnyTask")
|
|
25
25
|
|
26
26
|
class AnyTask(ABC):
|
27
27
|
"""
|
28
|
-
|
28
|
+
Abstraction for Zrb Task.
|
29
29
|
|
30
|
-
This class acts as a template for creating new
|
30
|
+
This class acts as a template for creating new Task type.
|
31
31
|
|
32
|
-
To define a new
|
32
|
+
To define a new Task type, you should extend this class and implement all its methods.
|
33
33
|
The easiest way to do so is by extending `Task`
|
34
34
|
"""
|
35
35
|
|
zrb/task/base_remote_cmd_task.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import copy
|
2
1
|
import os
|
3
2
|
import pathlib
|
4
3
|
|
@@ -50,8 +49,10 @@ class RemoteConfig:
|
|
50
49
|
password: JinjaTemplate = "",
|
51
50
|
ssh_key: JinjaTemplate = "",
|
52
51
|
port: Union[int, JinjaTemplate] = 22,
|
52
|
+
name: Optional[str] = None,
|
53
53
|
config_map: Optional[Mapping[str, JinjaTemplate]] = None,
|
54
54
|
):
|
55
|
+
self.name = name if name is not None else host
|
55
56
|
self.host = host
|
56
57
|
self.user = user
|
57
58
|
self.password = password
|
@@ -91,7 +92,7 @@ class SingleBaseRemoteCmdTask(CmdTask):
|
|
91
92
|
on_retry: Optional[OnRetry] = None,
|
92
93
|
on_failed: Optional[OnFailed] = None,
|
93
94
|
checkers: Iterable[AnyTask] = [],
|
94
|
-
checking_interval: Union[float, int] = 0,
|
95
|
+
checking_interval: Union[float, int] = 0.05,
|
95
96
|
retry: int = 2,
|
96
97
|
retry_interval: Union[float, int] = 1,
|
97
98
|
max_output_line: int = 1000,
|
@@ -146,7 +147,7 @@ class SingleBaseRemoteCmdTask(CmdTask):
|
|
146
147
|
self._remote_config = remote_config
|
147
148
|
|
148
149
|
def copy(self) -> TSingleBaseRemoteCmdTask:
|
149
|
-
return copy
|
150
|
+
return super().copy()
|
150
151
|
|
151
152
|
def inject_envs(self):
|
152
153
|
super().inject_envs()
|
@@ -227,6 +228,7 @@ class BaseRemoteCmdTask(BaseTask):
|
|
227
228
|
post_cmd_path: CmdVal = "",
|
228
229
|
cwd: Optional[Union[str, pathlib.Path]] = None,
|
229
230
|
upstreams: Iterable[AnyTask] = [],
|
231
|
+
fallbacks: Iterable[AnyTask] = [],
|
230
232
|
on_triggered: Optional[OnTriggered] = None,
|
231
233
|
on_waiting: Optional[OnWaiting] = None,
|
232
234
|
on_skipped: Optional[OnSkipped] = None,
|
@@ -235,7 +237,7 @@ class BaseRemoteCmdTask(BaseTask):
|
|
235
237
|
on_retry: Optional[OnRetry] = None,
|
236
238
|
on_failed: Optional[OnFailed] = None,
|
237
239
|
checkers: Iterable[AnyTask] = [],
|
238
|
-
checking_interval: Union[float, int] = 0,
|
240
|
+
checking_interval: Union[float, int] = 0.05,
|
239
241
|
retry: int = 2,
|
240
242
|
retry_interval: Union[float, int] = 1,
|
241
243
|
max_output_line: int = 1000,
|
@@ -247,9 +249,10 @@ class BaseRemoteCmdTask(BaseTask):
|
|
247
249
|
should_show_cmd: bool = True,
|
248
250
|
should_show_working_directory: bool = True,
|
249
251
|
):
|
250
|
-
|
252
|
+
self._remote_configs = list(remote_configs)
|
253
|
+
self._sub_tasks = [
|
251
254
|
SingleBaseRemoteCmdTask(
|
252
|
-
name=f"{name}-{remote_config.
|
255
|
+
name=f"{name}-{remote_config.name}",
|
253
256
|
remote_config=remote_config,
|
254
257
|
inputs=inputs,
|
255
258
|
envs=envs,
|
@@ -264,6 +267,7 @@ class BaseRemoteCmdTask(BaseTask):
|
|
264
267
|
post_cmd_path=post_cmd_path,
|
265
268
|
cwd=cwd,
|
266
269
|
upstreams=upstreams,
|
270
|
+
fallbacks=fallbacks,
|
267
271
|
on_triggered=on_triggered,
|
268
272
|
on_waiting=on_waiting,
|
269
273
|
on_skipped=on_skipped,
|
@@ -284,7 +288,7 @@ class BaseRemoteCmdTask(BaseTask):
|
|
284
288
|
should_show_cmd=should_show_cmd,
|
285
289
|
should_show_working_directory=should_show_working_directory,
|
286
290
|
)
|
287
|
-
for remote_config in
|
291
|
+
for remote_config in self._remote_configs
|
288
292
|
]
|
289
293
|
BaseTask.__init__(
|
290
294
|
self,
|
@@ -293,7 +297,61 @@ class BaseRemoteCmdTask(BaseTask):
|
|
293
297
|
color=color,
|
294
298
|
group=group,
|
295
299
|
description=description,
|
296
|
-
upstreams=
|
300
|
+
upstreams=self._sub_tasks,
|
297
301
|
retry=0,
|
298
302
|
return_upstream_result=True,
|
299
303
|
)
|
304
|
+
|
305
|
+
def insert_input(self, *inputs: AnyInput):
|
306
|
+
super().insert_input(*inputs)
|
307
|
+
for subtask in self._sub_tasks:
|
308
|
+
subtask.insert_input(*inputs)
|
309
|
+
|
310
|
+
def add_input(self, *inputs: AnyInput):
|
311
|
+
super().add_input(*inputs)
|
312
|
+
for subtask in self._sub_tasks:
|
313
|
+
subtask.add_input(*inputs)
|
314
|
+
|
315
|
+
def insert_env(self, *envs: Env):
|
316
|
+
super().insert_env(*envs)
|
317
|
+
for subtask in self._sub_tasks:
|
318
|
+
subtask.insert_env(*envs)
|
319
|
+
|
320
|
+
def add_env(self, *envs: Env):
|
321
|
+
super().add_env(*envs)
|
322
|
+
for subtask in self._sub_tasks:
|
323
|
+
subtask.add_env(*envs)
|
324
|
+
|
325
|
+
def insert_env_file(self, *env_files: EnvFile):
|
326
|
+
super().insert_env_file(*env_files)
|
327
|
+
for subtask in self._sub_tasks:
|
328
|
+
subtask.insert_env_file(*env_files)
|
329
|
+
|
330
|
+
def add_env_file(self, *env_files: Env):
|
331
|
+
super().add_env_file(*env_files)
|
332
|
+
for subtask in self._sub_tasks:
|
333
|
+
subtask.add_env_file(*env_files)
|
334
|
+
|
335
|
+
def insert_upstream(self, *upstreams: AnyTask):
|
336
|
+
for subtask in self._sub_tasks:
|
337
|
+
subtask.insert_upstream(*upstreams)
|
338
|
+
|
339
|
+
def add_upstream(self, *upstreams: AnyTask):
|
340
|
+
for subtask in self._sub_tasks:
|
341
|
+
subtask.add_upstream(*upstreams)
|
342
|
+
|
343
|
+
def insert_fallback(self, *fallbacks: AnyTask):
|
344
|
+
for subtask in self._sub_tasks:
|
345
|
+
subtask.insert_fallbacks(*fallbacks)
|
346
|
+
|
347
|
+
def add_fallback(self, *fallbacks: AnyTask):
|
348
|
+
for subtask in self._sub_tasks:
|
349
|
+
subtask.add_fallback(*fallbacks)
|
350
|
+
|
351
|
+
def insert_checker(self, *checkers: AnyTask):
|
352
|
+
for subtask in self._sub_tasks:
|
353
|
+
subtask.insert_checkers(*checkers)
|
354
|
+
|
355
|
+
def add_checker(self, *checkers: AnyTask):
|
356
|
+
for subtask in self._sub_tasks:
|
357
|
+
subtask.add_checker(*checkers)
|
zrb/task/base_task/base_task.py
CHANGED
@@ -37,8 +37,8 @@ from zrb.task_input.any_input import AnyInput
|
|
37
37
|
@typechecked
|
38
38
|
class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
|
39
39
|
"""
|
40
|
-
Base class for all
|
41
|
-
Every
|
40
|
+
Base class for all Tasks.
|
41
|
+
Every Task definition should be extended from this class.
|
42
42
|
"""
|
43
43
|
|
44
44
|
__running_tasks: List[AnyTask] = []
|
@@ -58,7 +58,7 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
|
|
58
58
|
upstreams: Iterable[AnyTask] = [],
|
59
59
|
fallbacks: Iterable[AnyTask] = [],
|
60
60
|
checkers: Iterable[AnyTask] = [],
|
61
|
-
checking_interval: Union[float, int] = 0,
|
61
|
+
checking_interval: Union[float, int] = 0.05,
|
62
62
|
run: Optional[Callable[..., Any]] = None,
|
63
63
|
on_triggered: Optional[OnTriggered] = None,
|
64
64
|
on_waiting: Optional[OnWaiting] = None,
|
@@ -72,7 +72,7 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
|
|
72
72
|
):
|
73
73
|
# init properties
|
74
74
|
retry_interval = retry_interval if retry_interval >= 0 else 0
|
75
|
-
checking_interval = checking_interval if checking_interval > 0 else 0
|
75
|
+
checking_interval = checking_interval if checking_interval > 0 else 0
|
76
76
|
retry = retry if retry >= 0 else 0
|
77
77
|
# init parent classes
|
78
78
|
FinishTracker.__init__(self, checking_interval=checking_interval)
|
@@ -270,18 +270,17 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
|
|
270
270
|
new_kwargs = self.get_input_map()
|
271
271
|
# make sure args and kwargs['_args'] are the same
|
272
272
|
self.log_info("Set run args")
|
273
|
-
new_args =
|
273
|
+
new_args = list(args)
|
274
274
|
if len(args) == 0 and "_args" in kwargs:
|
275
275
|
new_args = kwargs["_args"]
|
276
|
-
new_kwargs["_args"] = new_args
|
277
|
-
# inject self as input_map['_task']
|
278
|
-
new_kwargs["_task"] = self
|
279
276
|
self._set_args(new_args)
|
280
277
|
self._set_kwargs(new_kwargs)
|
281
278
|
# run the task
|
282
279
|
coroutines = [
|
283
280
|
asyncio.create_task(self._loop_check(show_done_info=show_done_info)),
|
284
|
-
asyncio.create_task(
|
281
|
+
asyncio.create_task(
|
282
|
+
self._run_all(*new_args, _args=new_args, _task=self, **new_kwargs)
|
283
|
+
),
|
285
284
|
]
|
286
285
|
results = await asyncio.gather(*coroutines)
|
287
286
|
result = results[-1]
|
@@ -456,7 +455,7 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
|
|
456
455
|
# set current task local keyval
|
457
456
|
await self._set_local_keyval(kwargs=kwargs, env_prefix=env_prefix)
|
458
457
|
# get new_kwargs for upstream and checkers
|
459
|
-
new_kwargs =
|
458
|
+
new_kwargs = {key: kwargs[key] for key in kwargs}
|
460
459
|
new_kwargs.update(self.get_input_map())
|
461
460
|
upstream_coroutines = []
|
462
461
|
# set upstreams keyval
|
@@ -58,7 +58,7 @@ class BaseTaskModel(CommonTaskModel, PidModel, TimeTracker):
|
|
58
58
|
upstreams: Iterable[AnyTask] = [],
|
59
59
|
fallbacks: Iterable[AnyTask] = [],
|
60
60
|
checkers: Iterable[AnyTask] = [],
|
61
|
-
checking_interval: Union[int, float] = 0,
|
61
|
+
checking_interval: Union[int, float] = 0.05,
|
62
62
|
run: Optional[Callable[..., Any]] = None,
|
63
63
|
on_triggered: Optional[OnTriggered] = None,
|
64
64
|
on_waiting: Optional[OnWaiting] = None,
|
@@ -49,7 +49,7 @@ class CommonTaskModel:
|
|
49
49
|
upstreams: Iterable[AnyTask] = [],
|
50
50
|
fallbacks: Iterable[AnyTask] = [],
|
51
51
|
checkers: Iterable[AnyTask] = [],
|
52
|
-
checking_interval: Union[float, int] = 0,
|
52
|
+
checking_interval: Union[float, int] = 0.05,
|
53
53
|
run: Optional[Callable[..., Any]] = None,
|
54
54
|
on_triggered: Optional[OnTriggered] = None,
|
55
55
|
on_waiting: Optional[OnWaiting] = None,
|
zrb/task/checker.py
CHANGED
@@ -44,7 +44,7 @@ class Checker(BaseTask):
|
|
44
44
|
on_ready: Optional[OnReady] = None,
|
45
45
|
on_retry: Optional[OnRetry] = None,
|
46
46
|
on_failed: Optional[OnFailed] = None,
|
47
|
-
checking_interval: Union[int, float] = 0,
|
47
|
+
checking_interval: Union[int, float] = 0.05,
|
48
48
|
progress_interval: Union[int, float] = 30,
|
49
49
|
expected_result: bool = True,
|
50
50
|
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
zrb/task/cmd_task.py
CHANGED
@@ -125,7 +125,7 @@ class CmdTask(BaseTask):
|
|
125
125
|
on_retry: Optional[OnRetry] = None,
|
126
126
|
on_failed: Optional[OnFailed] = None,
|
127
127
|
checkers: Iterable[AnyTask] = [],
|
128
|
-
checking_interval: Union[float, int] = 0,
|
128
|
+
checking_interval: Union[float, int] = 0.05,
|
129
129
|
retry: int = 2,
|
130
130
|
retry_interval: Union[float, int] = 1,
|
131
131
|
max_output_line: int = 1000,
|
zrb/task/decorator.py
CHANGED
@@ -43,7 +43,7 @@ def python_task(
|
|
43
43
|
on_retry: Optional[OnRetry] = None,
|
44
44
|
on_failed: Optional[OnFailed] = None,
|
45
45
|
checkers: Iterable[AnyTask] = [],
|
46
|
-
checking_interval: Union[float, int] = 0,
|
46
|
+
checking_interval: Union[float, int] = 0.05,
|
47
47
|
retry: int = 2,
|
48
48
|
retry_interval: Union[float, int] = 1,
|
49
49
|
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
zrb/task/docker_compose_task.py
CHANGED
@@ -115,7 +115,7 @@ class DockerComposeTask(CmdTask):
|
|
115
115
|
on_retry: Optional[OnRetry] = None,
|
116
116
|
on_failed: Optional[OnFailed] = None,
|
117
117
|
checkers: Iterable[AnyTask] = [],
|
118
|
-
checking_interval: Union[float, int] = 0,
|
118
|
+
checking_interval: Union[float, int] = 0.05,
|
119
119
|
retry: int = 2,
|
120
120
|
retry_interval: Union[float, int] = 1,
|
121
121
|
max_output_line: int = 1000,
|
zrb/task/flow_task.py
CHANGED
@@ -45,27 +45,13 @@ class FlowTask(BaseTask):
|
|
45
45
|
on_retry: Optional[OnRetry] = None,
|
46
46
|
on_failed: Optional[OnFailed] = None,
|
47
47
|
checkers: Iterable[AnyTask] = [],
|
48
|
-
checking_interval: float = 0,
|
48
|
+
checking_interval: Union[float, int] = 0.05,
|
49
49
|
retry: int = 2,
|
50
|
-
retry_interval: float = 1,
|
50
|
+
retry_interval: Union[float, int] = 1,
|
51
51
|
steps: List[Union[AnyTask, List[AnyTask]]] = [],
|
52
52
|
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
53
53
|
return_upstream_result: bool = False,
|
54
54
|
):
|
55
|
-
final_upstreams: List[AnyTask] = list(upstreams)
|
56
|
-
inputs: List[AnyInput] = list(inputs)
|
57
|
-
envs: List[Env] = list(envs)
|
58
|
-
env_files: List[EnvFile] = list(env_files)
|
59
|
-
for step in steps:
|
60
|
-
tasks = self._step_to_tasks(step)
|
61
|
-
new_upstreams = self._get_embeded_tasks(
|
62
|
-
tasks=tasks,
|
63
|
-
upstreams=final_upstreams,
|
64
|
-
inputs=inputs,
|
65
|
-
envs=envs,
|
66
|
-
env_files=env_files,
|
67
|
-
)
|
68
|
-
final_upstreams = new_upstreams
|
69
55
|
BaseTask.__init__(
|
70
56
|
self,
|
71
57
|
name=name,
|
@@ -76,7 +62,13 @@ class FlowTask(BaseTask):
|
|
76
62
|
icon=icon,
|
77
63
|
color=color,
|
78
64
|
description=description,
|
79
|
-
upstreams=
|
65
|
+
upstreams=self._create_flow_upstreams(
|
66
|
+
steps=steps,
|
67
|
+
upstreams=list(upstreams),
|
68
|
+
inputs=list(inputs),
|
69
|
+
envs=list(envs),
|
70
|
+
env_files=list(env_files),
|
71
|
+
),
|
80
72
|
fallbacks=fallbacks,
|
81
73
|
on_triggered=on_triggered,
|
82
74
|
on_waiting=on_waiting,
|
@@ -97,12 +89,33 @@ class FlowTask(BaseTask):
|
|
97
89
|
def copy(self) -> TFlowTask:
|
98
90
|
return super().copy()
|
99
91
|
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
92
|
+
def _create_flow_upstreams(
|
93
|
+
self,
|
94
|
+
steps: List[Union[AnyTask, List[AnyTask]]],
|
95
|
+
upstreams: List[AnyTask],
|
96
|
+
inputs: List[AnyInput],
|
97
|
+
envs: List[Env],
|
98
|
+
env_files: List[EnvFile],
|
99
|
+
) -> List[AnyTask]:
|
100
|
+
flow_upstreams = upstreams
|
101
|
+
for step in steps:
|
102
|
+
tasks = [task.copy() for task in self._step_to_tasks(step)]
|
103
|
+
new_upstreams = self._create_embeded_tasks(
|
104
|
+
tasks=tasks,
|
105
|
+
upstreams=flow_upstreams,
|
106
|
+
inputs=inputs,
|
107
|
+
envs=envs,
|
108
|
+
env_files=env_files,
|
109
|
+
)
|
110
|
+
flow_upstreams = new_upstreams
|
111
|
+
return flow_upstreams
|
112
|
+
|
113
|
+
def _step_to_tasks(self, step: Union[AnyTask, List[AnyTask]]) -> List[AnyTask]:
|
114
|
+
if isinstance(step, AnyTask):
|
115
|
+
return [step]
|
116
|
+
return step
|
104
117
|
|
105
|
-
def
|
118
|
+
def _create_embeded_tasks(
|
106
119
|
self,
|
107
120
|
tasks: List[AnyTask],
|
108
121
|
upstreams: List[AnyTask],
|
@@ -111,28 +124,26 @@ class FlowTask(BaseTask):
|
|
111
124
|
env_files: List[EnvFile],
|
112
125
|
) -> List[AnyTask]:
|
113
126
|
embeded_tasks: List[AnyTask] = []
|
114
|
-
for
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
embeded_task_root_upstream.add_upstream(*upstreams)
|
119
|
-
# embeded_task.add_upstream(*upstreams)
|
127
|
+
for embeded_task in tasks:
|
128
|
+
embeded_task_upstreams = self._get_all_upstreams(tasks=[embeded_task])
|
129
|
+
for embeded_task_upstream in embeded_task_upstreams:
|
130
|
+
embeded_task_upstream.add_upstream(*upstreams)
|
120
131
|
embeded_task.add_env(*envs)
|
121
132
|
embeded_task.add_env_file(*env_files)
|
122
133
|
embeded_task.add_input(*inputs)
|
123
134
|
embeded_tasks.append(embeded_task)
|
124
135
|
return embeded_tasks
|
125
136
|
|
126
|
-
def
|
127
|
-
|
137
|
+
def _get_all_upstreams(self, tasks: List[AnyTask]):
|
138
|
+
all_upstreams = []
|
128
139
|
for task in tasks:
|
129
140
|
upstreams = task._get_upstreams()
|
130
141
|
if len(upstreams) == 0:
|
131
|
-
|
142
|
+
all_upstreams.append(task)
|
132
143
|
continue
|
133
144
|
for upstream in upstreams:
|
134
145
|
if len(upstream._get_upstreams()) == 0:
|
135
|
-
|
146
|
+
all_upstreams.append(upstream)
|
136
147
|
continue
|
137
|
-
|
138
|
-
return
|
148
|
+
all_upstreams += self._get_all_upstreams([upstream])
|
149
|
+
return all_upstreams
|
zrb/task/http_checker.py
CHANGED
@@ -87,7 +87,7 @@ class HTTPChecker(Checker):
|
|
87
87
|
on_ready: Optional[OnReady] = None,
|
88
88
|
on_retry: Optional[OnRetry] = None,
|
89
89
|
on_failed: Optional[OnFailed] = None,
|
90
|
-
checking_interval: Union[int, float] = 0,
|
90
|
+
checking_interval: Union[int, float] = 0.05,
|
91
91
|
progress_interval: Union[int, float] = 5,
|
92
92
|
expected_result: bool = True,
|
93
93
|
should_execute: Union[bool, JinjaTemplate, Callable[..., bool]] = True,
|
zrb/task/notifier.py
CHANGED
@@ -58,7 +58,7 @@ class Notifier(BaseTask):
|
|
58
58
|
on_ready: Optional[OnReady] = None,
|
59
59
|
on_retry: Optional[OnRetry] = None,
|
60
60
|
on_failed: Optional[OnFailed] = None,
|
61
|
-
checking_interval: Union[int, float] = 0,
|
61
|
+
checking_interval: Union[int, float] = 0.05,
|
62
62
|
retry: int = 2,
|
63
63
|
retry_interval: Union[float, int] = 1,
|
64
64
|
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
zrb/task/path_checker.py
CHANGED
@@ -56,7 +56,7 @@ class PathChecker(Checker):
|
|
56
56
|
on_failed: Optional[OnFailed] = None,
|
57
57
|
path: JinjaTemplate = "",
|
58
58
|
ignored_path: Union[JinjaTemplate, Iterable[JinjaTemplate]] = [],
|
59
|
-
checking_interval: Union[int, float] = 0,
|
59
|
+
checking_interval: Union[int, float] = 0.05,
|
60
60
|
progress_interval: Union[int, float] = 5,
|
61
61
|
expected_result: bool = True,
|
62
62
|
should_execute: Union[bool, JinjaTemplate, Callable[..., bool]] = True,
|
zrb/task/path_watcher.py
CHANGED
@@ -72,7 +72,7 @@ class PathWatcher(Watcher):
|
|
72
72
|
on_failed: Optional[OnFailed] = None,
|
73
73
|
path: JinjaTemplate = "",
|
74
74
|
ignored_path: Union[JinjaTemplate, Iterable[JinjaTemplate]] = [],
|
75
|
-
checking_interval: Union[int, float] = 0,
|
75
|
+
checking_interval: Union[int, float] = 0.05,
|
76
76
|
progress_interval: Union[int, float] = 30,
|
77
77
|
watch_new_files: bool = True,
|
78
78
|
watch_modified_files: bool = True,
|
zrb/task/port_checker.py
CHANGED
@@ -66,7 +66,7 @@ class PortChecker(Checker):
|
|
66
66
|
on_ready: Optional[OnReady] = None,
|
67
67
|
on_retry: Optional[OnRetry] = None,
|
68
68
|
on_failed: Optional[OnFailed] = None,
|
69
|
-
checking_interval: Union[int, float] = 0,
|
69
|
+
checking_interval: Union[int, float] = 0.05,
|
70
70
|
progress_interval: Union[int, float] = 5,
|
71
71
|
expected_result: bool = True,
|
72
72
|
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
zrb/task/recurring_task.py
CHANGED
@@ -76,7 +76,7 @@ class RecurringTask(BaseTask):
|
|
76
76
|
on_retry: Optional[OnRetry] = None,
|
77
77
|
on_failed: Optional[OnFailed] = None,
|
78
78
|
checkers: Iterable[AnyTask] = [],
|
79
|
-
checking_interval: float = 0,
|
79
|
+
checking_interval: float = 0.05,
|
80
80
|
retry: int = 0,
|
81
81
|
retry_interval: float = 1,
|
82
82
|
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
@@ -185,7 +185,7 @@ class RecurringTask(BaseTask):
|
|
185
185
|
async def __run_from_queue(self):
|
186
186
|
while True:
|
187
187
|
if len(self._run_configs) == 0:
|
188
|
-
await asyncio.sleep(0.
|
188
|
+
await asyncio.sleep(0.05)
|
189
189
|
continue
|
190
190
|
if self._single_execution:
|
191
191
|
# Drain the queue, leave only the latest task
|
zrb/task/remote_cmd_task.py
CHANGED
@@ -66,7 +66,7 @@ class RemoteCmdTask(BaseRemoteCmdTask):
|
|
66
66
|
on_retry: Optional[OnRetry] = None,
|
67
67
|
on_failed: Optional[OnFailed] = None,
|
68
68
|
checkers: Iterable[AnyTask] = [],
|
69
|
-
checking_interval: Union[float, int] = 0,
|
69
|
+
checking_interval: Union[float, int] = 0.05,
|
70
70
|
retry: int = 2,
|
71
71
|
retry_interval: Union[float, int] = 1,
|
72
72
|
max_output_line: int = 1000,
|
zrb/task/resource_maker.py
CHANGED
zrb/task/rsync_task.py
CHANGED
@@ -48,8 +48,8 @@ class RsyncTask(BaseRemoteCmdTask):
|
|
48
48
|
remote_configs: Iterable[RemoteConfig],
|
49
49
|
src: JinjaTemplate,
|
50
50
|
dst: JinjaTemplate,
|
51
|
-
|
52
|
-
|
51
|
+
src_is_remote: bool = False,
|
52
|
+
dst_is_remote: bool = True,
|
53
53
|
group: Optional[Group] = None,
|
54
54
|
inputs: Iterable[AnyInput] = [],
|
55
55
|
envs: Iterable[Env] = [],
|
@@ -69,7 +69,7 @@ class RsyncTask(BaseRemoteCmdTask):
|
|
69
69
|
on_retry: Optional[OnRetry] = None,
|
70
70
|
on_failed: Optional[OnFailed] = None,
|
71
71
|
checkers: Iterable[AnyTask] = [],
|
72
|
-
checking_interval: Union[float, int] = 0,
|
72
|
+
checking_interval: Union[float, int] = 0.05,
|
73
73
|
retry: int = 2,
|
74
74
|
retry_interval: Union[float, int] = 1,
|
75
75
|
max_output_line: int = 1000,
|
@@ -77,8 +77,8 @@ class RsyncTask(BaseRemoteCmdTask):
|
|
77
77
|
preexec_fn: Optional[Callable[[], Any]] = os.setsid,
|
78
78
|
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
79
79
|
):
|
80
|
-
parsed_src = self._get_parsed_path(
|
81
|
-
parsed_dst = self._get_parsed_path(
|
80
|
+
parsed_src = self._get_parsed_path(src_is_remote, src)
|
81
|
+
parsed_dst = self._get_parsed_path(dst_is_remote, dst)
|
82
82
|
cmd = f'auth_rsync "{parsed_src}" "{parsed_dst}"'
|
83
83
|
BaseRemoteCmdTask.__init__(
|
84
84
|
self,
|
zrb/task/server.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import asyncio
|
2
|
+
import copy
|
2
3
|
|
3
4
|
from zrb.helper.accessories.color import colored
|
4
5
|
from zrb.helper.accessories.name import get_random_name
|
@@ -35,8 +36,8 @@ class Controller:
|
|
35
36
|
name: Optional[str] = None,
|
36
37
|
):
|
37
38
|
self._name = get_random_name() if name is None else name
|
38
|
-
self._triggers =
|
39
|
-
self._actions =
|
39
|
+
self._triggers = self._to_task_list(trigger)
|
40
|
+
self._actions = self._to_task_list(action)
|
40
41
|
self._args: List[Any] = []
|
41
42
|
self._kwargs: Mapping[str, Any] = {}
|
42
43
|
self._inputs: List[AnyInput] = []
|
@@ -58,28 +59,28 @@ class Controller:
|
|
58
59
|
def set_env_files(self, env_files: List[EnvFile]):
|
59
60
|
self._env_files = env_files
|
60
61
|
|
61
|
-
def
|
62
|
+
def get_original_env_files(self) -> Iterable[EnvFile]:
|
62
63
|
env_files = []
|
63
64
|
for trigger in self._triggers:
|
64
|
-
env_files += trigger.
|
65
|
+
env_files += trigger._get_env_files()
|
65
66
|
for action in self._actions:
|
66
|
-
env_files += action.
|
67
|
+
env_files += action._get_env_files()
|
67
68
|
return env_files
|
68
69
|
|
69
|
-
def
|
70
|
+
def get_original_envs(self) -> Iterable[Env]:
|
70
71
|
envs = []
|
71
72
|
for trigger in self._triggers:
|
72
|
-
envs += trigger.
|
73
|
+
envs += trigger._get_envs()
|
73
74
|
for action in self._actions:
|
74
|
-
envs += action.
|
75
|
+
envs += action._get_envs()
|
75
76
|
return envs
|
76
77
|
|
77
|
-
def
|
78
|
+
def get_original_inputs(self) -> Iterable[AnyInput]:
|
78
79
|
inputs = []
|
79
80
|
for trigger in self._triggers:
|
80
|
-
inputs += trigger.
|
81
|
+
inputs += trigger._get_combined_inputs()
|
81
82
|
for action in self._actions:
|
82
|
-
inputs += action.
|
83
|
+
inputs += action._get_combined_inputs()
|
83
84
|
return inputs
|
84
85
|
|
85
86
|
def to_function(self) -> Callable[..., Any]:
|
@@ -92,6 +93,11 @@ class Controller:
|
|
92
93
|
|
93
94
|
return fn
|
94
95
|
|
96
|
+
def _to_task_list(self, tasks: Union[AnyTask, List[AnyTask]]) -> List[AnyTask]:
|
97
|
+
if isinstance(tasks, AnyTask):
|
98
|
+
return [tasks.copy()]
|
99
|
+
return [task.copy() for task in tasks]
|
100
|
+
|
95
101
|
def _get_task(self) -> AnyTask:
|
96
102
|
actions = [action.copy() for action in self._actions]
|
97
103
|
actions.insert(0, self._get_remonitor_task())
|
@@ -123,7 +129,7 @@ class Server(BaseTask):
|
|
123
129
|
def __init__(
|
124
130
|
self,
|
125
131
|
name: str,
|
126
|
-
controllers:
|
132
|
+
controllers: Iterable[Controller],
|
127
133
|
group: Optional[Group] = None,
|
128
134
|
inputs: Iterable[AnyInput] = [],
|
129
135
|
envs: Iterable[Env] = [],
|
@@ -141,17 +147,18 @@ class Server(BaseTask):
|
|
141
147
|
on_retry: Optional[OnRetry] = None,
|
142
148
|
on_failed: Optional[OnFailed] = None,
|
143
149
|
checkers: Iterable[AnyTask] = [],
|
144
|
-
checking_interval: float = 0,
|
150
|
+
checking_interval: Union[int, float] = 0.05,
|
145
151
|
retry: int = 0,
|
146
|
-
retry_interval: float = 1,
|
152
|
+
retry_interval: Union[int, float] = 1,
|
147
153
|
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
148
154
|
return_upstream_result: bool = False,
|
149
155
|
):
|
150
156
|
inputs, envs, env_files = list(inputs), list(envs), list(env_files)
|
151
157
|
for controller in controllers:
|
152
|
-
|
153
|
-
|
154
|
-
|
158
|
+
controller_cp = copy.deepcopy(controller)
|
159
|
+
inputs += controller_cp.get_original_inputs()
|
160
|
+
envs += controller_cp.get_original_envs()
|
161
|
+
env_files += controller_cp.get_original_env_files()
|
155
162
|
BaseTask.__init__(
|
156
163
|
self,
|
157
164
|
name=name,
|
@@ -178,7 +185,7 @@ class Server(BaseTask):
|
|
178
185
|
should_execute=should_execute,
|
179
186
|
return_upstream_result=return_upstream_result,
|
180
187
|
)
|
181
|
-
self._controllers = controllers
|
188
|
+
self._controllers = list(controllers)
|
182
189
|
|
183
190
|
async def run(self, *args: Any, **kwargs: Any):
|
184
191
|
for controller in self._controllers:
|
zrb/task/task.py
CHANGED
@@ -9,7 +9,41 @@ logger.debug(colored("Loading zrb.task.task", attrs=["dark"]))
|
|
9
9
|
@typechecked
|
10
10
|
class Task(BaseTask):
|
11
11
|
"""
|
12
|
-
|
12
|
+
Task is the smallest Zrb automation unit.
|
13
|
+
|
14
|
+
You can configure a Task by using several interfaces:
|
15
|
+
- `inputs`: interfaces to read user input at the beginning of the execution.
|
16
|
+
- `envs`: interfaces to read and use OS Environment Variables.
|
17
|
+
- `env_files`: interfaces to read and use Environment Files.
|
18
|
+
|
19
|
+
Moreover, you can define Task dependencies by specifying its `upstreams` or by using shift-right operator.
|
20
|
+
|
21
|
+
Every Zrb Task has its life-cycle state:
|
22
|
+
- `Triggered`: The Task is triggered (either by the user or by the other Task).
|
23
|
+
- `Waiting`: Zrb has already triggered the Task. The Task is now waiting for all its upstreams to be ready.
|
24
|
+
- `Skipped`: Task upstreams are ready, but the Task is not executed and will immediately enter the `Ready` state.
|
25
|
+
- `Started`: The upstreams are ready, and Zrb is now starting the Task execution.
|
26
|
+
- `Failed`: Zrb failed to execute the Task. It will enter the `Retry` state if the current attempt does not exceed the maximum attempt.
|
27
|
+
- `Retry`: The task has already entered the `Failed` state. Now, Zrb will try to start the Task execution.
|
28
|
+
- `Ready`: The task is ready.
|
29
|
+
|
30
|
+
There are several configurations related to Task's life cycle:
|
31
|
+
- `retry`: Maximum retry attempt.
|
32
|
+
- `retry_interval`: The duration is to wait before Zrb starts the next attempt.
|
33
|
+
- `fallbacks`: Action to take if the Task has failed for good.
|
34
|
+
- `checkers`: How to determine if a Task is `Ready`.
|
35
|
+
- `checking_interval`: The duration to wait before Zrb checks for the Task's readiness.
|
36
|
+
- `run`: Action to do when Zrb executes the Task.
|
37
|
+
- `on_triggered`: Action to do when a Task is `Triggered`.
|
38
|
+
- `on_waiting`: Action to do when a Task is `Waiting`.
|
39
|
+
- `on_skipped`: Action to do when a Task is `Skipped`.
|
40
|
+
- `on_started`: Action to do when a Task is `Started`.
|
41
|
+
- `on_ready`: Action to do when a Task is `Ready`.
|
42
|
+
- `on_retry`: Action to do when a Task is `Retry`.
|
43
|
+
- `on_failed`: Action to do when a Task is `Failed`.
|
44
|
+
- `should_execute`: Condition to determine whether a Task should be `Started` or `Skipped`.
|
45
|
+
|
46
|
+
Finally, you can put related Tasks under the same `group`.
|
13
47
|
"""
|
14
48
|
|
15
49
|
pass
|
zrb/task/time_watcher.py
CHANGED
@@ -68,7 +68,7 @@ class TimeWatcher(Watcher):
|
|
68
68
|
on_retry: Optional[OnRetry] = None,
|
69
69
|
on_failed: Optional[OnFailed] = None,
|
70
70
|
schedule: JinjaTemplate = "",
|
71
|
-
checking_interval: Union[int, float] = 0,
|
71
|
+
checking_interval: Union[int, float] = 0.05,
|
72
72
|
progress_interval: Union[int, float] = 30,
|
73
73
|
should_execute: Union[bool, JinjaTemplate, Callable[..., bool]] = True,
|
74
74
|
):
|
zrb/task/watcher.py
CHANGED
@@ -2,6 +2,7 @@ import asyncio
|
|
2
2
|
|
3
3
|
from zrb.helper.accessories.color import colored
|
4
4
|
from zrb.helper.accessories.name import get_random_name
|
5
|
+
from zrb.helper.callable import run_async
|
5
6
|
from zrb.helper.log import logger
|
6
7
|
from zrb.helper.typecheck import typechecked
|
7
8
|
from zrb.helper.typing import Any, Callable, Iterable, Optional, Union
|
@@ -48,7 +49,7 @@ class Watcher(Checker):
|
|
48
49
|
on_ready: Optional[OnReady] = None,
|
49
50
|
on_retry: Optional[OnRetry] = None,
|
50
51
|
on_failed: Optional[OnFailed] = None,
|
51
|
-
checking_interval: Union[int, float] = 0,
|
52
|
+
checking_interval: Union[int, float] = 0.05,
|
52
53
|
progress_interval: Union[int, float] = 30,
|
53
54
|
expected_result: bool = True,
|
54
55
|
should_execute: Union[bool, str, Callable[..., bool]] = True,
|
@@ -85,7 +86,9 @@ class Watcher(Checker):
|
|
85
86
|
async def run(self, *args: Any, **kwargs: Any) -> bool:
|
86
87
|
if not looper.is_registered(self._identifier):
|
87
88
|
asyncio.create_task(
|
88
|
-
|
89
|
+
run_async(
|
90
|
+
looper.register, self._identifier, self.create_loop_inspector()
|
91
|
+
)
|
89
92
|
)
|
90
93
|
return await super().run(*args, **kwargs)
|
91
94
|
|
zrb/task_env/env.py
CHANGED
@@ -15,8 +15,9 @@ logger.debug(colored("Loading zrb.task_env.env", attrs=["dark"]))
|
|
15
15
|
@typechecked
|
16
16
|
class Env:
|
17
17
|
"""
|
18
|
-
Env
|
19
|
-
|
18
|
+
Env is an interface for a Task to read and use OS Environment Variable.
|
19
|
+
|
20
|
+
Env encapsulating details such as environment name, OS environment name, default values, and rendering behavior.
|
20
21
|
|
21
22
|
Attributes:
|
22
23
|
name (str): Environment name as recognized by the task.
|
@@ -77,7 +78,7 @@ class Env:
|
|
77
78
|
|
78
79
|
def should_render(self) -> bool:
|
79
80
|
"""
|
80
|
-
|
81
|
+
Retrieves whether the environment value should be rendered.
|
81
82
|
|
82
83
|
Returns:
|
83
84
|
bool: True if the environment value should be rendered, False otherwise.
|
zrb/task_env/env_file.py
CHANGED
@@ -16,8 +16,9 @@ logger.debug(colored("Loading zrb.task_env.env_file", attrs=["dark"]))
|
|
16
16
|
@typechecked
|
17
17
|
class EnvFile:
|
18
18
|
"""
|
19
|
-
|
20
|
-
|
19
|
+
Env is an interface for a Task to read and use OS Environment File.
|
20
|
+
|
21
|
+
Under the hood, EnvFile creates list of Env based on its `path` property.
|
21
22
|
|
22
23
|
Attributes:
|
23
24
|
path (str): The path to the environment file.
|
zrb/task_group/group.py
CHANGED
@@ -15,7 +15,7 @@ TGroup = TypeVar("TGroup", bound="Group")
|
|
15
15
|
@typechecked
|
16
16
|
class Group:
|
17
17
|
"""
|
18
|
-
|
18
|
+
Group is an umbrella of several related Tasks or sub-groups, facilitating organization and hierarchy.
|
19
19
|
|
20
20
|
This class allows the creation of a hierarchical structure by grouping tasks and
|
21
21
|
other task groups together. It provides methods to add tasks, retrieve tasks,
|
zrb/task_input/any_input.py
CHANGED
@@ -11,10 +11,12 @@ logger.debug(colored("Loading zrb.task_input.any_input", attrs=["dark"]))
|
|
11
11
|
|
12
12
|
class AnyInput(ABC):
|
13
13
|
"""
|
14
|
-
|
15
|
-
This class serves as a template for creating various input types,
|
16
|
-
providing a standardized interface for input handling and processing.
|
14
|
+
Abstraction for Zrb Input.
|
17
15
|
|
16
|
+
This class acts as a template for creating new Inputs.
|
17
|
+
|
18
|
+
To define a new Input type, you should extend this class and implement all its methods.
|
19
|
+
The easiest way to do so is by extending `Input`
|
18
20
|
"""
|
19
21
|
|
20
22
|
@abstractmethod
|
zrb/task_input/base_input.py
CHANGED
@@ -14,9 +14,9 @@ logger.debug(colored("Loading zrb.task_input.base_input", attrs=["dark"]))
|
|
14
14
|
@typechecked
|
15
15
|
class BaseInput(AnyInput):
|
16
16
|
"""
|
17
|
-
|
18
|
-
|
19
|
-
to
|
17
|
+
Base class for all Input.
|
18
|
+
|
19
|
+
Input is an interface for a Task to read user input at the beginning of the execution.
|
20
20
|
|
21
21
|
Attributes:
|
22
22
|
name (str): The name of the input, used as a unique identifier.
|
zrb/task_input/task_input.py
CHANGED
@@ -9,7 +9,7 @@ logger.debug(colored("Loading zrb.task_input.task_input", attrs=["dark"]))
|
|
9
9
|
|
10
10
|
class Input(BaseInput):
|
11
11
|
"""
|
12
|
-
|
12
|
+
Input is an interface for a Task to read user input at the beginning of the execution.
|
13
13
|
|
14
14
|
Attributes:
|
15
15
|
name (str): The name of the input, used as a unique identifier.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: zrb
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.18.0
|
4
4
|
Summary: A Framework to Enhance Your Workflow
|
5
5
|
Home-page: https://github.com/state-alchemists/zrb
|
6
6
|
License: AGPL-3.0-or-later
|
@@ -33,7 +33,7 @@ Description-Content-Type: text/markdown
|
|
33
33
|

|
34
34
|
|
35
35
|
|
36
|
-
[🫰 Installation](https://github.com/state-alchemists/zrb/blob/main/docs/installation.md) | [📖 Documentation](https://github.com/state-alchemists/zrb/blob/main/docs/README.md) | [🏁 Getting Started](https://github.com/state-alchemists/zrb/blob/main/docs/getting-started.md) | [💃 Common Mistakes](https://github.com/state-alchemists/zrb/blob/main/docs/
|
36
|
+
[🫰 Installation](https://github.com/state-alchemists/zrb/blob/main/docs/installation.md) | [📖 Documentation](https://github.com/state-alchemists/zrb/blob/main/docs/README.md) | [🏁 Getting Started](https://github.com/state-alchemists/zrb/blob/main/docs/getting-started.md) | [💃 Common Mistakes](https://github.com/state-alchemists/zrb/blob/main/docs/common-mistakes/README.md) | [❓ FAQ](https://github.com/state-alchemists/zrb/blob/main/docs/faq/README.md)
|
37
37
|
|
38
38
|
|
39
39
|
# 🤖 Zrb: A Framework to Enhance Your Workflow
|
@@ -43,11 +43,12 @@ Zrb is a [CLI-based](https://en.wikipedia.org/wiki/Command-line_interface) autom
|
|
43
43
|
- __Automate__ day-to-day tasks.
|
44
44
|
- __Generate__ projects or applications.
|
45
45
|
- __Prepare__, __run__, and __deploy__ your applications with a single command.
|
46
|
-
-
|
46
|
+
- Deliver __faster__ with __fewer human errors__.
|
47
47
|
|
48
|
-
|
48
|
+
Zrb allows you to write custom task definitions in [Python](https://www.python.org/), further enhancing Zrb's capabilities. Defining your tasks in Zrb gives you several advantages because:
|
49
49
|
|
50
|
-
- Every
|
50
|
+
- Every Zrb Task has a __retry mechanism__.
|
51
|
+
- Every Zrb Task is __configurable__ via __environment variables__ or __user inputs__.
|
51
52
|
- Zrb handles your __task dependencies__ automatically.
|
52
53
|
- Zrb runs your task dependencies __concurrently__.
|
53
54
|
|
@@ -85,7 +86,9 @@ Download Datasets ──┘
|
|
85
86
|
⬇️
|
86
87
|
```
|
87
88
|
|
88
|
-
You can
|
89
|
+
Zrb Task is the smallest automation unit. You can configure a Zrb Task using user input (`inputs`) or environment variables (`envs` or `env_files`). Every Zrb Task has a configurable `retry` mechanism. Moreover, you can also define Zrb Task dependencies using the shift right operator `>>` or `upstreams` parameter.
|
90
|
+
|
91
|
+
You can create a file named `zrb_init.py` and define your Zrb Tasks as follows:
|
89
92
|
|
90
93
|
```python
|
91
94
|
# File name: zrb_init.py
|
@@ -129,7 +132,7 @@ def show_stats(*args, **kwargs):
|
|
129
132
|
# Define dependencies: `show_stat` depends on both, `download_dataset` and `install_pandas`
|
130
133
|
Parallel(download_dataset, install_pandas) >> show_stats
|
131
134
|
|
132
|
-
# Register the tasks so that they are
|
135
|
+
# Register the tasks so that they are accessble from the CLI
|
133
136
|
runner.register(install_pandas, download_dataset, show_stats)
|
134
137
|
```
|
135
138
|
|
@@ -286,15 +289,15 @@ Visit [our tutorials](https://github.com/state-alchemists/zrb/blob/main/docs/tut
|
|
286
289
|
- [🫰 Installation](https://github.com/state-alchemists/zrb/blob/main/docs/installation.md)
|
287
290
|
- [🏁 Getting Started](https://github.com/state-alchemists/zrb/blob/main/docs/getting-started.md)
|
288
291
|
- [📖 Documentation](https://github.com/state-alchemists/zrb/blob/main/docs/README.md)
|
289
|
-
- [💃 Common Mistakes](https://github.com/state-alchemists/zrb/blob/main/docs/
|
292
|
+
- [💃 Common Mistakes](https://github.com/state-alchemists/zrb/blob/main/docs/common-mistakes/README.md)
|
290
293
|
- [❓ FAQ](https://github.com/state-alchemists/zrb/blob/main/docs/faq/README.md)
|
291
294
|
|
292
295
|
# 🐞 Bug Report + Feature Request
|
293
296
|
|
294
|
-
You can submit bug
|
297
|
+
You can submit bug reports and feature requests by creating a new [issue](https://github.com/state-alchemists/zrb/issues) on Zrb's GitHub Repositories. When reporting a bug or requesting a feature, please be sure to:
|
295
298
|
|
296
299
|
- Include the version of Zrb you are using (i.e., `zrb version`)
|
297
|
-
- Tell us what you have
|
300
|
+
- Tell us what you have tried
|
298
301
|
- Tell us what you expect
|
299
302
|
- Tell us what you get
|
300
303
|
|
@@ -326,7 +329,7 @@ We are thankful for the following libraries and services. They accelerate Zrb de
|
|
326
329
|
- [Jsons](https://pypi.org.project/jsons/): Parse JSON. This package should be part of the standard library.
|
327
330
|
- [Libcst](https://pypi.org/project/libcst/): Turn Python code into a Concrete Syntax Tree.
|
328
331
|
- [Croniter](https://pypi.org/project/croniter/): Parse cron pattern.
|
329
|
-
- [
|
332
|
+
- [Poetry](https://pypi.org/project/poetry), [flake8](https://pypi.org/project/flake8/), [black](https://pypi.org/project/black), [isort](https://pypi.org/project/isort), and many more. See the complete list of Zrb's [pyproject.toml](https://github.com/state-alchemists/zrb/blob/main/pyproject.toml)
|
330
333
|
- Services
|
331
334
|
- [asciiflow.com](https://asciiflow.com/): Creates beautiful ASCII-based diagrams.
|
332
335
|
- [emojipedia.org](https://emojipedia.org/): Find emoji.
|
@@ -965,7 +965,7 @@ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/componen
|
|
965
965
|
zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/component/repo/search_filter.py,sha256=lYquQLR4_qr43AlKGNBBNzcGOEOASQHteuLdiewOBoE,147
|
966
966
|
zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/component/rpc/__init__.py,sha256=i5QOPDiwAwp0EskPSVwJDuVH6pq_DWRi3XN1hMFFw4A,244
|
967
967
|
zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/component/rpc/messagebus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
968
|
-
zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/component/rpc/messagebus/caller.py,sha256=
|
968
|
+
zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/component/rpc/messagebus/caller.py,sha256=P90X3d6et457EwD4NohOsPNIcz9lFQmzqTbZubmR9aA,3202
|
969
969
|
zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/component/rpc/messagebus/server.py,sha256=KFVErPpkRDetDokMAR16thaKtOTqk_xRp4lmM1iQNFo,2197
|
970
970
|
zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/component/rpc/rpc.py,sha256=obJ8ksA9Io5nRpGoTQE506hj82dPwRZIUWTq2JEOLRo,1625
|
971
971
|
zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/component/schema/__init__.py,sha256=g1CrqtQukcTOnNaKFLj6j-iVaNQ_cvpmdzROtbeteck,127
|
@@ -1355,46 +1355,46 @@ zrb/shell-scripts/notify.ps1,sha256=6_xPoIwuxARpYljcjVV-iRJS3gJqGfx-B6kj719cJ9o,
|
|
1355
1355
|
zrb/shell-scripts/rsync-util.sh,sha256=QzdhSBvUNMxB4U2B4m0Dxg9czGckRjB7Vk4A1ObG0-k,353
|
1356
1356
|
zrb/shell-scripts/ssh-util.sh,sha256=9lXDzw6oO8HuA4vdbfps_uQMMwKyNYX9fZkZgpK52g8,401
|
1357
1357
|
zrb/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1358
|
-
zrb/task/any_task.py,sha256=
|
1358
|
+
zrb/task/any_task.py,sha256=hrgsYikSe_C6JDSWeHNGCCvefNrkVioJWUunrqSFGLE,39199
|
1359
1359
|
zrb/task/any_task_event_handler.py,sha256=AjTC6lIcprutRusNBGl83EifQe4TbZzxdlVIR4ndWN4,524
|
1360
|
-
zrb/task/base_remote_cmd_task.py,sha256=
|
1360
|
+
zrb/task/base_remote_cmd_task.py,sha256=q2Kwo5OMahL5gPSxwp_9zZLYouFfFc6Ru_p6ApOI-pk,12124
|
1361
1361
|
zrb/task/base_task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1362
|
-
zrb/task/base_task/base_task.py,sha256=
|
1362
|
+
zrb/task/base_task/base_task.py,sha256=IvOBbuzIHLWP3RrlkK0NZXa1L7XlO1m0uLEYIxJt8sU,20388
|
1363
1363
|
zrb/task/base_task/component/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1364
|
-
zrb/task/base_task/component/base_task_model.py,sha256=
|
1365
|
-
zrb/task/base_task/component/common_task_model.py,sha256=
|
1364
|
+
zrb/task/base_task/component/base_task_model.py,sha256=i6TrtTusZ71ZnOnx8yM0aJl8uF6R1hKdAf62bEdpdCs,10379
|
1365
|
+
zrb/task/base_task/component/common_task_model.py,sha256=h81BGqplsaWJCQl0Zigl24LLkCUKPEfJikSbITREQnM,12288
|
1366
1366
|
zrb/task/base_task/component/pid_model.py,sha256=RjJIqOpavucDssnd3q3gT4q8QnP8I9SUdlv1b9pR7kU,292
|
1367
1367
|
zrb/task/base_task/component/renderer.py,sha256=9wP2IW811Ta81IoPWmeQ7yVc7eG-uaSnOVbEyeaOIuk,4439
|
1368
1368
|
zrb/task/base_task/component/trackers.py,sha256=c5xhZ6agICxKPI5Va1sn66_9OqC92ebF5CNhcwVUNUE,2074
|
1369
|
-
zrb/task/checker.py,sha256=
|
1370
|
-
zrb/task/cmd_task.py,sha256=
|
1371
|
-
zrb/task/decorator.py,sha256=
|
1372
|
-
zrb/task/docker_compose_task.py,sha256=
|
1373
|
-
zrb/task/flow_task.py,sha256=
|
1374
|
-
zrb/task/http_checker.py,sha256=
|
1369
|
+
zrb/task/checker.py,sha256=raYNBHgeyEqkyfBRsPPgSV7ukEfMlJOCUn97WQNl6mU,3384
|
1370
|
+
zrb/task/cmd_task.py,sha256=Bfu29x5Cy10gCazIItCEOzrafU7r7z5WlWS4_wD7Znk,14184
|
1371
|
+
zrb/task/decorator.py,sha256=stxrl6aXbuUDK83lVf8m8uni3Ii6egLl0TCR0vxslUQ,3064
|
1372
|
+
zrb/task/docker_compose_task.py,sha256=hUKF7W3GwxFuEWmlPPFxa7h8npEnig2sm7KjlidHFBI,14911
|
1373
|
+
zrb/task/flow_task.py,sha256=QBOoyIrqc6ToSf3RF8xu8h4yxCWCerUAu2Ba0GxAqgg,5147
|
1374
|
+
zrb/task/http_checker.py,sha256=y0cWa2t4YtGQr6FWno5sZ6Ej9gQiLDF-Z1kLU1rijRw,5693
|
1375
1375
|
zrb/task/looper.py,sha256=0eM3wEIC_RbThg60MRbK4Az16vt81O5p12cORAYTfnI,1430
|
1376
|
-
zrb/task/notifier.py,sha256=
|
1376
|
+
zrb/task/notifier.py,sha256=GbvnndQ-3-1vfGpOIIQ0IMS1ddqDxzgTSYThs_zg1xU,6220
|
1377
1377
|
zrb/task/parallel.py,sha256=-coMuiFlS29GpBgW6plPVaCLesgzzD0bYib29OvhXFg,1193
|
1378
|
-
zrb/task/path_checker.py,sha256=
|
1379
|
-
zrb/task/path_watcher.py,sha256=
|
1380
|
-
zrb/task/port_checker.py,sha256=
|
1381
|
-
zrb/task/recurring_task.py,sha256=
|
1382
|
-
zrb/task/remote_cmd_task.py,sha256=
|
1383
|
-
zrb/task/resource_maker.py,sha256=
|
1384
|
-
zrb/task/rsync_task.py,sha256=
|
1385
|
-
zrb/task/server.py,sha256=
|
1386
|
-
zrb/task/task.py,sha256=
|
1387
|
-
zrb/task/time_watcher.py,sha256=
|
1388
|
-
zrb/task/watcher.py,sha256=
|
1378
|
+
zrb/task/path_checker.py,sha256=SHpwtlS5YbO1jFGNnP7SuswkuDNHMOy52Fr4IzdIG98,4674
|
1379
|
+
zrb/task/path_watcher.py,sha256=x2SdgdgaZm2wiAyfBJoMVa625ufHtf8oHKmKhhEqAQk,7421
|
1380
|
+
zrb/task/port_checker.py,sha256=Za02E0xzR7xvHEujxuPszaydJCpwl_hJa1S9U4j25XQ,4593
|
1381
|
+
zrb/task/recurring_task.py,sha256=6JN7YkAY-NQ_zU2EAzqaQAxvfkGssbxvzNtL_foNA3Q,7434
|
1382
|
+
zrb/task/remote_cmd_task.py,sha256=DzAt5Vq8YekqAfu9PflGP0XcdLWX_gLKI64dGVgtL6s,3954
|
1383
|
+
zrb/task/resource_maker.py,sha256=wvq8Gv11epA_OYeLY071hIfFYkJ0rMcmcnXUAbd3TRg,7645
|
1384
|
+
zrb/task/rsync_task.py,sha256=4CB4AEvf8RoZOV2eTpMIH2h-b3cH_AqmcI4fv1Gln40,4190
|
1385
|
+
zrb/task/server.py,sha256=inWjVd8rSrSaH6W-0hn2xYCeJVtlGM8eePZtGm8z-Hs,6731
|
1386
|
+
zrb/task/task.py,sha256=iHDyUMUh1uVGlMCQdVewdT3epCOHKNRKblC3G1WSKS0,2493
|
1387
|
+
zrb/task/time_watcher.py,sha256=D3_rr5Dlaw8xOg9iZMAGzPiEC2VDvIIvNTluQsZeBHo,5122
|
1388
|
+
zrb/task/watcher.py,sha256=7yDAS7kxST4Gd_PLyg_7XU6uXed5qbojE-B5X5z9EY4,3344
|
1389
1389
|
zrb/task/wiki_task.py,sha256=Mcugk_6Pd7pzubi2ZP4eegJs8e9niYKh-9mCrNHXE_g,4330
|
1390
1390
|
zrb/task_env/constant.py,sha256=ySdHv2dawWE-UoeBHl8FEOmrBl4vfkRI67TIBdkK6l8,220
|
1391
|
-
zrb/task_env/env.py,sha256=
|
1392
|
-
zrb/task_env/env_file.py,sha256=
|
1391
|
+
zrb/task_env/env.py,sha256=WoxPlUgD33p6-y2EJU0oXAXBAnPL65k55hAbv6kO-Zs,5206
|
1392
|
+
zrb/task_env/env_file.py,sha256=D5cHJBY1DFcBa3KI3ujTe7Gxk7y_WB1zXCzkZNlDexE,3047
|
1393
1393
|
zrb/task_group/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1394
|
-
zrb/task_group/group.py,sha256=
|
1394
|
+
zrb/task_group/group.py,sha256=uF3tyLABTyyBNyE9FUCfJeYSDnaLFQCis3tuEn5FYho,6109
|
1395
1395
|
zrb/task_input/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1396
|
-
zrb/task_input/any_input.py,sha256
|
1397
|
-
zrb/task_input/base_input.py,sha256=
|
1396
|
+
zrb/task_input/any_input.py,sha256=-uOq1ONXdhW20FRkC3pzqX081tbfmWjvCc_-d-gCNGY,2087
|
1397
|
+
zrb/task_input/base_input.py,sha256=kxt2184s8ppC2dsa69J2uLUOUqsdCmXEJiNUIJxKcuQ,5495
|
1398
1398
|
zrb/task_input/bool_input.py,sha256=xlWjqPvHi52TLiFP13wB1SayJlbzmxv31AS-sZJ0jw4,4040
|
1399
1399
|
zrb/task_input/choice_input.py,sha256=GU28ATSayZsmqCW-euAPoWyA-Kh6d5Wf6FwWLXffk5w,4290
|
1400
1400
|
zrb/task_input/constant.py,sha256=VEsnrI0BDdCJ1Z58EJgxXUhZBe5CA8TfURo0cNu5CaQ,200
|
@@ -1402,9 +1402,9 @@ zrb/task_input/float_input.py,sha256=rtaowHp8RpiQS8a24ULgtydRu6wkYT1Q7Q_IRcCPD7s
|
|
1402
1402
|
zrb/task_input/int_input.py,sha256=d2fXcm5fCo09472eMAm6PdzLQD82ZBV9ARq5CjKepAo,4198
|
1403
1403
|
zrb/task_input/password_input.py,sha256=g_g8ZWAzDaHx4h2EHY3UCGvTigC6esAUBzXU0T9nDUk,4192
|
1404
1404
|
zrb/task_input/str_input.py,sha256=BNflOhrJvST9bWK0rGdCi7C7y-QDvHj9ISQMRmujIWU,4200
|
1405
|
-
zrb/task_input/task_input.py,sha256=
|
1406
|
-
zrb-0.
|
1407
|
-
zrb-0.
|
1408
|
-
zrb-0.
|
1409
|
-
zrb-0.
|
1410
|
-
zrb-0.
|
1405
|
+
zrb/task_input/task_input.py,sha256=DcHgKie5Oo1sUxj41t1ZQjCIK1aAfTgGzaKr7_ap7ZI,2248
|
1406
|
+
zrb-0.18.0.dist-info/LICENSE,sha256=WfnGCl8G60EYOPAEkuc8C9m9pdXWDe08NsKj3TBbxsM,728
|
1407
|
+
zrb-0.18.0.dist-info/METADATA,sha256=qEsdwPUflSN8YiBhgngtzvaQLXQemLtihXgGeSpKyPk,17076
|
1408
|
+
zrb-0.18.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
1409
|
+
zrb-0.18.0.dist-info/entry_points.txt,sha256=xTgXc1kBKYhJHEujdaSPHUcJT3-hbyP1mLgwkv-5sSk,40
|
1410
|
+
zrb-0.18.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|