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.
@@ -15,7 +15,7 @@ class MessagebusCaller(Caller):
15
15
  publisher: Publisher,
16
16
  consumer_factory: Callable[[], Consumer],
17
17
  timeout: float = 30,
18
- check_reply_interval: float = 0.1,
18
+ check_reply_interval: float = 0.05,
19
19
  ):
20
20
  self.logger = logger
21
21
  self.admin = admin
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
- Contract/interface for all Zrb Task.
28
+ Abstraction for Zrb Task.
29
29
 
30
- This class acts as a template for creating new Zrb Task types.
30
+ This class acts as a template for creating new Task type.
31
31
 
32
- To define a new Zrb Task, you should extend this class and implement all its methods.
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
 
@@ -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.deepcopy(self)
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
- sub_tasks = [
252
+ self._remote_configs = list(remote_configs)
253
+ self._sub_tasks = [
251
254
  SingleBaseRemoteCmdTask(
252
- name=f"{name}-{remote_config.host}",
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 list(remote_configs)
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=sub_tasks,
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)
@@ -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 tasks.
41
- Every task definition should be extended from this class.
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.05
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 = copy.deepcopy(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(self._run_all(*new_args, **new_kwargs)),
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 = copy.deepcopy(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,
@@ -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=final_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 _step_to_tasks(self, node: Union[AnyTask, List[AnyTask]]) -> List[AnyTask]:
101
- if isinstance(node, AnyTask):
102
- return [node]
103
- return node
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 _get_embeded_tasks(
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 task in tasks:
115
- embeded_task = task.copy()
116
- embeded_task_root_upstreams = self._get_root_upstreams(tasks=[embeded_task])
117
- for embeded_task_root_upstream in embeded_task_root_upstreams:
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 _get_root_upstreams(self, tasks: List[AnyTask]):
127
- root_upstreams = []
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
- root_upstreams.append(task)
142
+ all_upstreams.append(task)
132
143
  continue
133
144
  for upstream in upstreams:
134
145
  if len(upstream._get_upstreams()) == 0:
135
- root_upstreams.append(upstream)
146
+ all_upstreams.append(upstream)
136
147
  continue
137
- root_upstreams += self._get_root_upstreams([upstream])
138
- return root_upstreams
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,
@@ -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.1)
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
@@ -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,
@@ -123,7 +123,7 @@ class ResourceMaker(BaseTask):
123
123
  on_retry=on_retry,
124
124
  on_failed=on_failed,
125
125
  checkers=[],
126
- checking_interval=0.1,
126
+ checking_interval=0.05,
127
127
  retry=0,
128
128
  retry_interval=0,
129
129
  should_execute=should_execute,
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
- is_remote_src: bool = False,
52
- is_remote_dst: bool = True,
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(is_remote_src, src)
81
- parsed_dst = self._get_parsed_path(is_remote_dst, dst)
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 = [trigger] if isinstance(trigger, AnyTask) else trigger
39
- self._actions = [action] if isinstance(action, AnyTask) else action
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 get_sub_env_files(self) -> Iterable[EnvFile]:
62
+ def get_original_env_files(self) -> Iterable[EnvFile]:
62
63
  env_files = []
63
64
  for trigger in self._triggers:
64
- env_files += trigger.copy()._get_env_files()
65
+ env_files += trigger._get_env_files()
65
66
  for action in self._actions:
66
- env_files += action.copy()._get_env_files()
67
+ env_files += action._get_env_files()
67
68
  return env_files
68
69
 
69
- def get_sub_envs(self) -> Iterable[Env]:
70
+ def get_original_envs(self) -> Iterable[Env]:
70
71
  envs = []
71
72
  for trigger in self._triggers:
72
- envs += trigger.copy()._get_envs()
73
+ envs += trigger._get_envs()
73
74
  for action in self._actions:
74
- envs += action.copy()._get_envs()
75
+ envs += action._get_envs()
75
76
  return envs
76
77
 
77
- def get_sub_inputs(self) -> Iterable[AnyInput]:
78
+ def get_original_inputs(self) -> Iterable[AnyInput]:
78
79
  inputs = []
79
80
  for trigger in self._triggers:
80
- inputs += trigger.copy()._get_combined_inputs()
81
+ inputs += trigger._get_combined_inputs()
81
82
  for action in self._actions:
82
- inputs += action.copy()._get_combined_inputs()
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: List[Controller],
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
- inputs += controller.get_sub_inputs()
153
- envs += controller.get_sub_envs()
154
- env_files += controller.get_sub_env_files()
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
- Alias for BaseTask.
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
- looper.register(self._identifier, self.create_loop_inspector())
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 Represents an environment configuration for a task, encapsulating details such as environment name, OS-specific
19
- environment name, default values, and rendering behavior.
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
- Determines whether the environment value should be rendered.
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
- Represents a handler for an environment file, facilitating the creation and management of environment variables
20
- (Env objects) based on the contents of the specified environment file.
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
- Represents a group of tasks and subgroups, facilitating organization and hierarchy.
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,
@@ -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
- Abstract base class representing a generalized input specification.
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
@@ -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
- A concrete implementation of the AnyInput abstract base class, representing a specific type of task input.
18
- This class allows for the creation of interactive and configurable inputs for tasks, with various attributes
19
- to customize its behavior and appearance.
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.
@@ -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
- Alias for BaseInput
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.17.2
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
  ![](https://raw.githubusercontent.com/state-alchemists/zrb/main/_images/zrb/android-chrome-192x192.png)
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/oops-i-did-it-again/README.md) | [❓ FAQ](https://github.com/state-alchemists/zrb/blob/main/docs/faq/README.md)
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
- - Etc.
46
+ - Deliver __faster__ with __fewer human errors__.
47
47
 
48
- You can also write custom task definitions in [Python](https://www.python.org/), enhancing Zrb's base capabilities. Defining your tasks in Zrb gives you several advantages because:
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 task has a __retry mechanism__.
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 create a file named `zrb_init.py` and define the tasks as follows:
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 accessbie from the CLI
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/oops-i-did-it-again/README.md)
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 report and feature request by creating a new [issue](https://github.com/state-alchemists/zrb/issues) on Zrb Github Repositories. When reporting a bug or requesting a feature, please be sure to:
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 try
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
- - [Flit](https://pypi.org/project/flit), [Twine](https://pypi.org/project/twine/), and many more. See the complete list of Zrb's requirements.txt
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=4C6bDNUm-cL-G_5R-GdaSCXht_bJM5q8lelnVftCdaQ,3201
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=lzCbrpm6Mo_isNW7KuHK7Rq0t59_9z0oOLAtaJYCEdg,39214
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=tZi3jODMXfTkDAmWiFR2YdA-b4-TDTP1uLtO0ulmM34,10101
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=3kwrxjz5EPRpBp2HAhdRHdgRDgyDTak01C6fQMjU1Pw,20446
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=YlEuvYSzlrK83Kds07bu2drKSw3rKyl7qIR1qwIPNZk,10376
1365
- zrb/task/base_task/component/common_task_model.py,sha256=JoAAf8EvuPx31fCK_TBxX_TBeHZrZyFDjLeK8ts0w3A,12285
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=Y8WnIZM23fGqZpxHw2Bnk5jb0MmEMS598WZiEB8OUFU,3381
1370
- zrb/task/cmd_task.py,sha256=_wjF9MbKGA0EAr_df47AMC0lROCiaJTUyxT-AFQKKJo,14181
1371
- zrb/task/decorator.py,sha256=WInQrxuVlejvZEGIiBMfkiMa0I5rT9lWRGjyyLu_hzw,3061
1372
- zrb/task/docker_compose_task.py,sha256=Cgk9ROW_xSnSYV0x1E2Xo1AphFoota-omrtLPocDaOU,14908
1373
- zrb/task/flow_task.py,sha256=QIIZgq9C7e-kvTRJ0Y1Slb5AQyy15N9H4NZxdFR3FI8,4867
1374
- zrb/task/http_checker.py,sha256=mStzoRlcDWCyeIP4sRAQSns_U_nEp19qYYE-DONZaA8,5690
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=19E4EcFgFZ0thU9p2P1dGUYR04721pa0K3lqsj6a4Xc,6217
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=Jn7tnaUiPUbWOPAH3TUgzaa9_uiU0dPkpKCkr2Tlruc,4671
1379
- zrb/task/path_watcher.py,sha256=xoQxfgsGDxzywPPFS2RirtwrK9-cnm_TCTabZRhZr84,7418
1380
- zrb/task/port_checker.py,sha256=KE1fr0NBiUCLplDOHot8RzPBP1h_BvxFzHIZiEOuGaM,4590
1381
- zrb/task/recurring_task.py,sha256=FNxV7n4h9AzUCU8oKXwAS_A9j1newS-esWjmMsC33vE,7430
1382
- zrb/task/remote_cmd_task.py,sha256=rmLB5uCcbbfZBy8-nAZI8mgnNd-J2d4SBemLEDwSlV4,3951
1383
- zrb/task/resource_maker.py,sha256=jQSO7PVIuTZi__JcrpRC4Ni_xmuJszJiMAxH_qfJPhs,7644
1384
- zrb/task/rsync_task.py,sha256=bgCeZQTG-4isvjZGGs_05oOEkkwGc930NTyuUYUm_cg,4187
1385
- zrb/task/server.py,sha256=w0gO73tt9PLWXVtgY-oe6qzvODtxVcizBGCUjRrhp5w,6478
1386
- zrb/task/task.py,sha256=dHv4cmnd0QFPT9PwrfmHpxTaXj86mm8xf7_jAj_engI,329
1387
- zrb/task/time_watcher.py,sha256=m0OKCtYHzO8nz-bmp-PuaHpmGwhPzy2riikjol-_7ZA,5119
1388
- zrb/task/watcher.py,sha256=2dxWgwSK8CrhiNF2JF1S9Pe_BXZPlfxU88n495vlIuY,3250
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=C9IzavEtWlpap4C92XONi1ID-RK9gDDLQKl5rYGBsyc,5195
1392
- zrb/task_env/env_file.py,sha256=NkPOjxi8lrvBjB13kc9LU3ODvjGsdw3sSGOyC9-GnzE,3087
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=RmYpnh1UGiCi0vKYoqLwlCmJzC5-VKkMgDrVR2y3wsk,6091
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=cZ2v8qjJ3B-L-jZgAz5EhpZii5sMoepwan5jAbJE0cM,2067
1397
- zrb/task_input/base_input.py,sha256=qNifwst3ArwAbQ9XBDoyo6whMeS2IP-VZ3Pw0vf8efE,5643
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=x1sGHsoSYAYMdQBrCLmcvZa_ZmGggMPj3goAQzewUKI,2181
1406
- zrb-0.17.2.dist-info/LICENSE,sha256=WfnGCl8G60EYOPAEkuc8C9m9pdXWDe08NsKj3TBbxsM,728
1407
- zrb-0.17.2.dist-info/METADATA,sha256=NNFpLM-mizatYOhAfnsi30eujgnhCA-KPs0KeCP4cRw,16460
1408
- zrb-0.17.2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
1409
- zrb-0.17.2.dist-info/entry_points.txt,sha256=xTgXc1kBKYhJHEujdaSPHUcJT3-hbyP1mLgwkv-5sSk,40
1410
- zrb-0.17.2.dist-info/RECORD,,
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