zrb 0.17.1__py3-none-any.whl → 0.17.3__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,14 +25,12 @@ TAnyTask = TypeVar("TAnyTask", bound="AnyTask")
25
25
 
26
26
  class AnyTask(ABC):
27
27
  """
28
- Abstract base class for defining tasks in a task management system.
28
+ Abstraction for Zrb Task.
29
29
 
30
- This class acts as a template for creating new task types. To define a new task,
31
- extend this class and implement all its abstract methods. The `AnyTask` class is
32
- considered atomic and is not broken into multiple interfaces.
30
+ This class acts as a template for creating new Task type.
33
31
 
34
- Subclasses should implement the abstract methods to define custom behavior for
35
- task execution, state transitions, and other functionalities.
32
+ To define a new Task type, you should extend this class and implement all its methods.
33
+ The easiest way to do so is by extending `Task`
36
34
  """
37
35
 
38
36
  @abstractmethod
@@ -74,7 +72,7 @@ class AnyTask(ABC):
74
72
  Examples:
75
73
  >>> from zrb import Task
76
74
  >>> class MyTask(Task):
77
- >>> async def run(self, *args: Any, **kwargs: Any) -> int:
75
+ >>> def run(self, *args: Any, **kwargs: Any) -> int:
78
76
  >>> self.print_out('Doing some calculation')
79
77
  >>> return 42
80
78
  """
@@ -88,8 +86,7 @@ class AnyTask(ABC):
88
86
  Any other tasks depends on the current task, will be `started` once the current task is `ready`.
89
87
 
90
88
  This method should be implemented to define the criteria for considering the task
91
- `ready`. The specifics of this completion depend on the task's
92
- nature and the subclass implementation.
89
+ `ready`. The specifics of this completion depend on the task's nature and the subclass implementation.
93
90
 
94
91
  Returns:
95
92
  bool: True if the task is completed, False otherwise.
@@ -91,7 +91,7 @@ class SingleBaseRemoteCmdTask(CmdTask):
91
91
  on_retry: Optional[OnRetry] = None,
92
92
  on_failed: Optional[OnFailed] = None,
93
93
  checkers: Iterable[AnyTask] = [],
94
- checking_interval: Union[float, int] = 0,
94
+ checking_interval: Union[float, int] = 0.05,
95
95
  retry: int = 2,
96
96
  retry_interval: Union[float, int] = 1,
97
97
  max_output_line: int = 1000,
@@ -235,7 +235,7 @@ class BaseRemoteCmdTask(BaseTask):
235
235
  on_retry: Optional[OnRetry] = None,
236
236
  on_failed: Optional[OnFailed] = None,
237
237
  checkers: Iterable[AnyTask] = [],
238
- checking_interval: Union[float, int] = 0,
238
+ checking_interval: Union[float, int] = 0.05,
239
239
  retry: int = 2,
240
240
  retry_interval: Union[float, int] = 1,
241
241
  max_output_line: int = 1000,
@@ -37,8 +37,44 @@ 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
+
43
+ Task is the smallest Zrb automation unit.
44
+
45
+ You can configure a Task by using several interfaces:
46
+ - `inputs`: interfaces to read user input at the beginning of the execution.
47
+ - `envs`: interfaces to read and use OS Environment Variables.
48
+ - `env_files`: interfaces to read and use Environment Files.
49
+
50
+ Moreover, you can define Task dependencies by specifying it's `upstreams` or by using shift-right operator.
51
+
52
+ Every Task has its own life-cycle state:
53
+ - `Triggered`: The Task is triggered.
54
+ - `Waiting`: The Task is waiting for all it's upstreams to be ready.
55
+ - `Skipped`: The Task is not executed and will immediately enter the `Ready` state.
56
+ - `Started`: The Task execution is started.
57
+ - `Failed`: The Task execution is failed. It will enter the `Retry` state if the current attempt is less than the maximum attempt.
58
+ - `Retry`: The task will be restarted.
59
+ - `Ready`: The task is ready.
60
+
61
+ There are several configurations related to Task's life cycle:
62
+ - `retry`: How many retries should be attempted.
63
+ - `retry_interval`: How long to wait before the next retry attempt.
64
+ - `fallbacks`: What to do if the Task is failed and no retry attempt will be performed.
65
+ - `checkers`: How to determine if a Task is `Ready`.
66
+ - `checking_interval`: How long to wait before checking for Task's readiness.
67
+ - `run`: What a Task should do.
68
+ - `on_triggered`: What to do when a Task is `Triggered`.
69
+ - `on_waiting`: What to do when a Task is `Waiting`.
70
+ - `on_skipped`: What to do when a Task is `Skipped`.
71
+ - `on_started`: What to do when a Task is `Started`.
72
+ - `on_ready`: What to do when a Task is `Ready`.
73
+ - `on_retry`: What to do when a Task is `Retry`.
74
+ - `on_failed`: What to do when a Task is `Failed`.
75
+ - `should_execute`: Whether a Task should be `Started` or not (`Skipped`).
76
+
77
+ Finally, you can put related Tasks under the same `group`.
42
78
  """
43
79
 
44
80
  __running_tasks: List[AnyTask] = []
@@ -58,7 +94,7 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
58
94
  upstreams: Iterable[AnyTask] = [],
59
95
  fallbacks: Iterable[AnyTask] = [],
60
96
  checkers: Iterable[AnyTask] = [],
61
- checking_interval: Union[float, int] = 0,
97
+ checking_interval: Union[float, int] = 0.05,
62
98
  run: Optional[Callable[..., Any]] = None,
63
99
  on_triggered: Optional[OnTriggered] = None,
64
100
  on_waiting: Optional[OnWaiting] = None,
@@ -72,10 +108,10 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
72
108
  ):
73
109
  # init properties
74
110
  retry_interval = retry_interval if retry_interval >= 0 else 0
75
- checking_interval = checking_interval if checking_interval > 0 else 0.1
111
+ checking_interval = checking_interval if checking_interval > 0 else 0
76
112
  retry = retry if retry >= 0 else 0
77
113
  # init parent classes
78
- FinishTracker.__init__(self)
114
+ FinishTracker.__init__(self, checking_interval=checking_interval)
79
115
  Renderer.__init__(self)
80
116
  AttemptTracker.__init__(self, retry=retry)
81
117
  BaseTaskModel.__init__(
@@ -233,7 +269,7 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
233
269
  await run_async(self._on_retry, self)
234
270
 
235
271
  async def check(self) -> bool:
236
- return await self._is_done()
272
+ return await run_async(self._is_done)
237
273
 
238
274
  def inject_envs(self):
239
275
  super().inject_envs()
@@ -273,15 +309,14 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
273
309
  new_args = copy.deepcopy(args)
274
310
  if len(args) == 0 and "_args" in kwargs:
275
311
  new_args = kwargs["_args"]
276
- new_kwargs["_args"] = new_args
277
- # inject self as input_map['_task']
278
- new_kwargs["_task"] = self
279
312
  self._set_args(new_args)
280
313
  self._set_kwargs(new_kwargs)
281
314
  # run the task
282
315
  coroutines = [
283
316
  asyncio.create_task(self._loop_check(show_done_info=show_done_info)),
284
- asyncio.create_task(self._run_all(*new_args, **new_kwargs)),
317
+ asyncio.create_task(
318
+ self._run_all(*new_args, _args=new_args, _task=self, **new_kwargs)
319
+ ),
285
320
  ]
286
321
  results = await asyncio.gather(*coroutines)
287
322
  result = results[-1]
@@ -315,7 +350,7 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
315
350
  if self.__is_check_triggered:
316
351
  self.log_debug("Waiting readiness flag to be set")
317
352
  while not self.__is_ready:
318
- await asyncio.sleep(0.1)
353
+ await asyncio.sleep(self._checking_interval)
319
354
  return True
320
355
  self.__is_check_triggered = True
321
356
  check_result = await self._check()
@@ -336,7 +371,7 @@ class BaseTask(FinishTracker, AttemptTracker, Renderer, BaseTaskModel, AnyTask):
336
371
  self.log_debug("Waiting execution to be started")
337
372
  while not self.__is_execution_started:
338
373
  # Don't start checking before the execution itself has been started
339
- await asyncio.sleep(0.05)
374
+ await asyncio.sleep(self._checking_interval / 2.0)
340
375
  check_coroutines: Iterable[asyncio.Task] = []
341
376
  for checker_task in self._get_checkers():
342
377
  checker_task._set_execution_id(self.get_execution_id())
@@ -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,
@@ -2,7 +2,7 @@ import asyncio
2
2
  import time
3
3
 
4
4
  from zrb.helper.typecheck import typechecked
5
- from zrb.helper.typing import Optional
5
+ from zrb.helper.typing import Optional, Union
6
6
 
7
7
  LOG_NAME_LENGTH = 20
8
8
 
@@ -51,9 +51,10 @@ class AttemptTracker:
51
51
 
52
52
  @typechecked
53
53
  class FinishTracker:
54
- def __init__(self):
54
+ def __init__(self, checking_interval: Union[float, int]):
55
55
  self.__execution_queue: Optional[asyncio.Queue] = None
56
56
  self.__counter = 0
57
+ self.__checking_interval = checking_interval
57
58
 
58
59
  async def _mark_awaited(self):
59
60
  if self.__execution_queue is None:
@@ -69,5 +70,5 @@ class FinishTracker:
69
70
 
70
71
  async def _is_done(self) -> bool:
71
72
  while self.__execution_queue is None:
72
- await asyncio.sleep(0.05)
73
+ await asyncio.sleep(self.__checking_interval / 2.0)
73
74
  return await self.__execution_queue.get()
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.1,
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,9 +43,9 @@ 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: float = 0.1,
46
+ checking_interval: Union[float, int] = 0.05,
47
47
  retry: int = 2,
48
- retry_interval: float = 1,
48
+ retry_interval: Union[float, int] = 1,
49
49
  should_execute: Union[bool, str, Callable[..., bool]] = True,
50
50
  return_upstream_result: bool = False,
51
51
  runner: Optional[Runner] = None,
@@ -115,9 +115,9 @@ 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: float = 0.1,
118
+ checking_interval: Union[float, int] = 0.05,
119
119
  retry: int = 2,
120
- retry_interval: float = 1,
120
+ retry_interval: Union[float, int] = 1,
121
121
  max_output_line: int = 1000,
122
122
  max_error_line: int = 1000,
123
123
  preexec_fn: Optional[Callable[[], Any]] = os.setsid,
zrb/task/flow_task.py CHANGED
@@ -45,9 +45,9 @@ 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,
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.1,
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.1,
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.1,
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.1,
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
@@ -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,
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
@@ -61,25 +62,25 @@ class Controller:
61
62
  def get_sub_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
70
  def get_sub_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
78
  def get_sub_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]:
@@ -141,17 +142,18 @@ class Server(BaseTask):
141
142
  on_retry: Optional[OnRetry] = None,
142
143
  on_failed: Optional[OnFailed] = None,
143
144
  checkers: Iterable[AnyTask] = [],
144
- checking_interval: float = 0,
145
+ checking_interval: Union[int, float] = 0.05,
145
146
  retry: int = 0,
146
- retry_interval: float = 1,
147
+ retry_interval: Union[int, float] = 1,
147
148
  should_execute: Union[bool, str, Callable[..., bool]] = True,
148
149
  return_upstream_result: bool = False,
149
150
  ):
150
151
  inputs, envs, env_files = list(inputs), list(envs), list(env_files)
151
152
  for controller in controllers:
152
- inputs += controller.get_sub_inputs()
153
- envs += controller.get_sub_envs()
154
- env_files += controller.get_sub_env_files()
153
+ controller_cp = copy.deepcopy(controller)
154
+ inputs += controller_cp.get_sub_inputs()
155
+ envs += controller_cp.get_sub_envs()
156
+ env_files += controller_cp.get_sub_env_files()
155
157
  BaseTask.__init__(
156
158
  self,
157
159
  name=name,
@@ -181,11 +183,12 @@ class Server(BaseTask):
181
183
  self._controllers = controllers
182
184
 
183
185
  async def run(self, *args: Any, **kwargs: Any):
184
- for controller in self._controllers:
186
+ controllers = [copy.deepcopy(controller) for controller in self._controllers]
187
+ for controller in controllers:
185
188
  controller.set_envs(self._get_envs())
186
189
  controller.set_env_files(self._get_env_files())
187
190
  controller.set_inputs(self._get_inputs())
188
191
  controller.set_args(args)
189
192
  controller.set_kwargs(kwargs)
190
- functions = [controller.to_function() for controller in self._controllers]
193
+ functions = [controller.to_function() for controller in controllers]
191
194
  await asyncio.gather(*[fn() for fn in functions])
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 it's `upstreams` or by using shift-right operator.
20
+
21
+ Every Task has its own life-cycle state:
22
+ - `Triggered`: The Task is triggered.
23
+ - `Waiting`: The Task is waiting for all it's upstreams to be ready.
24
+ - `Skipped`: The Task is not executed and will immediately enter the `Ready` state.
25
+ - `Started`: The Task execution is started.
26
+ - `Failed`: The Task execution is failed. It will enter the `Retry` state if the current attempt is less than the maximum attempt.
27
+ - `Retry`: The task will be restarted.
28
+ - `Ready`: The task is ready.
29
+
30
+ There are several configurations related to Task's life cycle:
31
+ - `retry`: How many retries should be attempted.
32
+ - `retry_interval`: How long to wait before the next retry attempt.
33
+ - `fallbacks`: What to do if the Task is failed and no retry attempt will be performed.
34
+ - `checkers`: How to determine if a Task is `Ready`.
35
+ - `checking_interval`: How long to wait before checking for Task's readiness.
36
+ - `run`: What a Task should do.
37
+ - `on_triggered`: What to do when a Task is `Triggered`.
38
+ - `on_waiting`: What to do when a Task is `Waiting`.
39
+ - `on_skipped`: What to do when a Task is `Skipped`.
40
+ - `on_started`: What to do when a Task is `Started`.
41
+ - `on_ready`: What to do when a Task is `Ready`.
42
+ - `on_retry`: What to do when a Task is `Retry`.
43
+ - `on_failed`: What to do when a Task is `Failed`.
44
+ - `should_execute`: Whether a Task should be `Started` or not (`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] = 1,
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
  ):
@@ -128,7 +128,7 @@ class TimeWatcher(Watcher):
128
128
 
129
129
  def create_loop_inspector(self) -> Callable[..., Optional[bool]]:
130
130
  async def loop_inspect() -> bool:
131
- await asyncio.sleep(0.1)
131
+ await asyncio.sleep(self._checking_interval)
132
132
  label = f"Watching {self._rendered_schedule}"
133
133
  identifier = self.get_identifier()
134
134
  scheduled_time = self.__scheduled_times[identifier]
@@ -148,7 +148,7 @@ class TimeWatcher(Watcher):
148
148
  return cron.get_next(datetime.datetime)
149
149
 
150
150
  def _get_cron(self) -> Any:
151
- margin = datetime.timedelta(seconds=0.001)
151
+ margin = datetime.timedelta(seconds=self._checking_interval / 2.0)
152
152
  slightly_before_now = datetime.datetime.now() - margin
153
153
  cron = croniter.croniter(self._rendered_schedule, slightly_before_now)
154
154
  return cron
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.1,
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.1
3
+ Version: 0.17.3
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 requirements.txt
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=1jc0qVZs1yIMfGuInktgH7EqDbI8IqmsaSlH5VijThc,39435
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=WHBT_mLEGDEyB28EeK9Qwqqe4B0JboyuQopC6DtnZqE,10107
1361
1361
  zrb/task/base_task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1362
- zrb/task/base_task/base_task.py,sha256=qnQSG-nAppmm38JY11wC03-0mZSOjjk-XJ62leco2rw,20354
1362
+ zrb/task/base_task/base_task.py,sha256=nQw61BsW6Si7X1Hu1HwqcD9BNq02NlQNoVYQkdtjOGY,22319
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
- zrb/task/base_task/component/trackers.py,sha256=gM9eOukMh6kvNJnRsHscQ_JN--Haa2YA4bIufqh8upE,1950
1369
- zrb/task/checker.py,sha256=fn6gmcCUHsar458NQ4Af4-kt2skcyibd0ewsPTRd5-w,3383
1370
- zrb/task/cmd_task.py,sha256=_wjF9MbKGA0EAr_df47AMC0lROCiaJTUyxT-AFQKKJo,14181
1371
- zrb/task/decorator.py,sha256=j62l7ITIRZtk_qE97d4naVl9gbbMoi2eEXOPOmYdF8M,3039
1372
- zrb/task/docker_compose_task.py,sha256=fnFEOAS9yEi2ve7pSzN9guXOVeYt8HYTdQvtjk-yoRQ,14886
1373
- zrb/task/flow_task.py,sha256=QIIZgq9C7e-kvTRJ0Y1Slb5AQyy15N9H4NZxdFR3FI8,4867
1374
- zrb/task/http_checker.py,sha256=DRIwXjC8StucHo2nP1duM3Ime3zzw1BQH8ib2bFZVmA,5692
1368
+ zrb/task/base_task/component/trackers.py,sha256=c5xhZ6agICxKPI5Va1sn66_9OqC92ebF5CNhcwVUNUE,2074
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=Lwbg-vCFSde4b-QR-sJGm28dpjKZFXl2Hbj2rEd0jwE,4894
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=yvMgGlmMQhlaX3Wlq5yI7-nzEpyCFoXHEOFOdlfI6-o,4673
1379
- zrb/task/path_watcher.py,sha256=UGaGYzWExoVQDK6smXEKsd0leO3FZOQYHnpHgZ9hiZU,7420
1380
- zrb/task/port_checker.py,sha256=IoVIP0QjxKz2SLgnK2GIaxn4WASk6ZKf4cQlKog0Fw8,4592
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=xx82w8ygpL-6pUbeuWjsxSVLSZhkWVWHsAoZUXPV7Jk,5075
1388
- zrb/task/watcher.py,sha256=m72YhUKtQsE4mZSm1y2MKiSdfj6HZo3rj9f3nQLU7Oo,3252
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=kusVfttM1H0OEpNpLuU1I25MqChYaJeZDNZiXWtuVbA,4190
1385
+ zrb/task/server.py,sha256=zWHHafsXvpUPmdwYxOt6THhJb124yyRmvvKJJdnws_c,6612
1386
+ zrb/task/task.py,sha256=AyF0U40Ub4zj1S5sOQE0TffGRWpU0CDx8TFCkrB3Tos,2241
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.1.dist-info/LICENSE,sha256=WfnGCl8G60EYOPAEkuc8C9m9pdXWDe08NsKj3TBbxsM,728
1407
- zrb-0.17.1.dist-info/METADATA,sha256=hswyEpXbHtSdNOnq4_PQPuDruzGo9795YOZpSi6lkfM,16460
1408
- zrb-0.17.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
1409
- zrb-0.17.1.dist-info/entry_points.txt,sha256=xTgXc1kBKYhJHEujdaSPHUcJT3-hbyP1mLgwkv-5sSk,40
1410
- zrb-0.17.1.dist-info/RECORD,,
1405
+ zrb/task_input/task_input.py,sha256=DcHgKie5Oo1sUxj41t1ZQjCIK1aAfTgGzaKr7_ap7ZI,2248
1406
+ zrb-0.17.3.dist-info/LICENSE,sha256=WfnGCl8G60EYOPAEkuc8C9m9pdXWDe08NsKj3TBbxsM,728
1407
+ zrb-0.17.3.dist-info/METADATA,sha256=ICpcf7AIoV-FxXKbALeApOKizXtmK5mOhpbLItC3McM,17010
1408
+ zrb-0.17.3.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
1409
+ zrb-0.17.3.dist-info/entry_points.txt,sha256=xTgXc1kBKYhJHEujdaSPHUcJT3-hbyP1mLgwkv-5sSk,40
1410
+ zrb-0.17.3.dist-info/RECORD,,
File without changes
File without changes