zrb 0.0.108__py3-none-any.whl → 0.0.110__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zrb/action/runner.py +3 -3
- zrb/builtin/git.py +1 -3
- zrb/helper/accessories/name.py +21 -11
- zrb/helper/env_map/fetch.py +13 -13
- zrb/shell-scripts/rsync-util.sh +3 -3
- zrb/task/any_task.py +51 -17
- zrb/task/base_remote_cmd_task.py +43 -18
- zrb/task/base_task.py +39 -41
- zrb/task/base_task_composite.py +97 -28
- zrb/task/cmd_task.py +22 -19
- zrb/task/docker_compose_task.py +21 -34
- zrb/task/flow_task.py +4 -4
- zrb/task_env/constant.py +1 -0
- zrb/task_env/env.py +3 -0
- zrb/task_env/env_file.py +3 -0
- zrb/task_input/constant.py +1 -1
- {zrb-0.0.108.dist-info → zrb-0.0.110.dist-info}/METADATA +19 -19
- {zrb-0.0.108.dist-info → zrb-0.0.110.dist-info}/RECORD +21 -20
- {zrb-0.0.108.dist-info → zrb-0.0.110.dist-info}/LICENSE +0 -0
- {zrb-0.0.108.dist-info → zrb-0.0.110.dist-info}/WHEEL +0 -0
- {zrb-0.0.108.dist-info → zrb-0.0.110.dist-info}/entry_points.txt +0 -0
zrb/action/runner.py
CHANGED
@@ -27,10 +27,10 @@ class Runner():
|
|
27
27
|
logger.info(colored('Runner created', attrs=['dark']))
|
28
28
|
|
29
29
|
def register(self, task: AnyTask):
|
30
|
-
|
30
|
+
task.set_has_cli_interface()
|
31
|
+
cmd_name = task.get_full_cmd_name()
|
31
32
|
logger.debug(colored(f'Register task: {cmd_name}', attrs=['dark']))
|
32
33
|
self._tasks.append(task)
|
33
|
-
task.set_has_cli_interface()
|
34
34
|
logger.debug(colored(f'Task registered: {cmd_name}', attrs=['dark']))
|
35
35
|
|
36
36
|
def serve(self, cli: click.Group) -> click.Group:
|
@@ -77,7 +77,7 @@ class Runner():
|
|
77
77
|
return group
|
78
78
|
|
79
79
|
def _create_cli_command(self, task: AnyTask) -> click.Command:
|
80
|
-
task_inputs = task.
|
80
|
+
task_inputs = task._get_combined_inputs()
|
81
81
|
task_cmd_name = task.get_cmd_name()
|
82
82
|
task_description = task.get_description()
|
83
83
|
task_function = task.to_function(
|
zrb/builtin/git.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
from zrb.helper.typing import Any
|
2
2
|
from zrb.builtin.group import git_group
|
3
3
|
from zrb.task.decorator import python_task
|
4
|
-
from zrb.task.task import Task
|
5
4
|
from zrb.task_input.str_input import StrInput
|
6
5
|
from zrb.task_input.bool_input import BoolInput
|
7
6
|
from zrb.runner import runner
|
@@ -26,7 +25,7 @@ from zrb.helper.python_task import show_lines
|
|
26
25
|
prompt='Commit hash/Tag',
|
27
26
|
default='HEAD'
|
28
27
|
),
|
29
|
-
|
28
|
+
BoolInput(
|
30
29
|
name='include-new',
|
31
30
|
description='include new files',
|
32
31
|
prompt='Include new files',
|
@@ -52,7 +51,6 @@ async def get_file_changes(*args: Any, **kwargs: Any):
|
|
52
51
|
include_new = kwargs.get('include_new', True)
|
53
52
|
include_removed = kwargs.get('include_removed', True)
|
54
53
|
include_updated = kwargs.get('include_updated', True)
|
55
|
-
task: Task = kwargs['_task']
|
56
54
|
modified_file_states = get_modified_file_states(commit)
|
57
55
|
modified_file_keys = []
|
58
56
|
output = []
|
zrb/helper/accessories/name.py
CHANGED
@@ -10,19 +10,29 @@ def get_random_name(
|
|
10
10
|
digit_count: int = 4
|
11
11
|
) -> str:
|
12
12
|
prefixes = [
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
'albedo', 'argent', 'argentum', 'aurora', 'aurum', 'azure',
|
14
|
+
'basilisk', 'cerulean', 'chimeric', 'citrin', 'coral', 'crimson',
|
15
|
+
'diamond', 'draco', 'dragon', 'emerald', 'ethereal', 'ferrum',
|
16
|
+
'flammeus', 'garnet', 'glacial', 'glimmering', 'glistening', 'golden',
|
17
|
+
'helios', 'igneous', 'imperial', 'jade', 'luminous', 'luna', 'lunar',
|
18
|
+
'mystic', 'nephrite', 'nocturnal', 'obsidian', 'opal', 'pearl',
|
19
|
+
'platinum', 'prismatic', 'ruby', 'sapphire', 'serpentine', 'silver',
|
20
|
+
'sol', 'solar', 'spiritual', 'stellar', 'tempest', 'topaz',
|
21
|
+
'turquoise', 'verde', 'vermillion', 'vitreous', 'zephyr', 'zircon'
|
18
22
|
]
|
19
23
|
suffixes = [
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
'aether', 'albedo', 'alchemy', 'arcana', 'aureum', 'aetheris',
|
25
|
+
'anima', 'astralis', 'caelestis', 'chrysopoeia', 'cosmicum',
|
26
|
+
'crystallum', 'deum', 'divinitas', 'draconis', 'elementorum', 'elixir',
|
27
|
+
'essentia', 'eternis', 'ethereus', 'fatum', 'flamma', 'fulgur',
|
28
|
+
'hermetica', 'ignis', 'illuminationis', 'imperium', 'incantatum',
|
29
|
+
'infinitum', 'lapis', 'lux', 'magicae', 'magnum', 'materia',
|
30
|
+
'metallum', 'mysticum', 'natura', 'occultum', 'omnipotentis',
|
31
|
+
'opulentia', 'philosophia', 'philosophorum', 'praeparatum',
|
32
|
+
'praestantissimum', 'prima', 'primordium', 'quintessentia',
|
33
|
+
'regeneratio', 'ritualis', 'sanctum', 'spiritus', 'tenebris',
|
34
|
+
'terra', 'tinctura', 'transmutationis', 'universalis', 'vapores',
|
35
|
+
'venenum', 'veritas', 'vitae', 'volatus'
|
26
36
|
]
|
27
37
|
prefix = random.choice(prefixes)
|
28
38
|
suffix = random.choice(suffixes)
|
zrb/helper/env_map/fetch.py
CHANGED
@@ -16,7 +16,7 @@ def fetch_env_map_from_group(
|
|
16
16
|
sub_env_map: Mapping[str, str] = fetch_env_map_from_group(
|
17
17
|
env_map, sub_group
|
18
18
|
)
|
19
|
-
env_map =
|
19
|
+
env_map = _cascade_env_map(env_map, sub_env_map)
|
20
20
|
return env_map
|
21
21
|
|
22
22
|
|
@@ -25,33 +25,33 @@ def fetch_env_map_from_task(
|
|
25
25
|
env_map: Mapping[str, str], task: AnyTask
|
26
26
|
):
|
27
27
|
task_env_map: Mapping[str, str] = {}
|
28
|
-
for env_file in task.
|
28
|
+
for env_file in task._get_env_files():
|
29
29
|
envs = env_file.get_envs()
|
30
|
-
task_env_map =
|
31
|
-
task_env_map =
|
32
|
-
env_map =
|
33
|
-
for upstream in task.
|
30
|
+
task_env_map = _add_envs_to_env_map(task_env_map, envs)
|
31
|
+
task_env_map = _add_envs_to_env_map(task_env_map, task._envs)
|
32
|
+
env_map = _cascade_env_map(env_map, task_env_map)
|
33
|
+
for upstream in task._get_upstreams():
|
34
34
|
task_env_map = fetch_env_map_from_task(env_map, upstream)
|
35
|
-
for checker in task.
|
35
|
+
for checker in task._get_checkers():
|
36
36
|
task_env_map = fetch_env_map_from_task(env_map, checker)
|
37
37
|
return env_map
|
38
38
|
|
39
39
|
|
40
40
|
@typechecked
|
41
|
-
def
|
41
|
+
def _add_envs_to_env_map(
|
42
42
|
env_map: Mapping[str, str], envs: List[Env]
|
43
43
|
) -> Mapping[str, str]:
|
44
44
|
for env in envs:
|
45
45
|
if env.os_name == '':
|
46
46
|
continue
|
47
|
-
env_name =
|
48
|
-
env_default =
|
47
|
+
env_name = _get_env_name(env)
|
48
|
+
env_default = _get_env_default(env)
|
49
49
|
env_map[env_name] = env_default
|
50
50
|
return env_map
|
51
51
|
|
52
52
|
|
53
53
|
@typechecked
|
54
|
-
def
|
54
|
+
def _cascade_env_map(
|
55
55
|
env_map: Mapping[str, str],
|
56
56
|
other_env_map: Mapping[str, str]
|
57
57
|
) -> Mapping[str, str]:
|
@@ -63,14 +63,14 @@ def cascade_env_map(
|
|
63
63
|
|
64
64
|
|
65
65
|
@typechecked
|
66
|
-
def
|
66
|
+
def _get_env_name(env: Env) -> str:
|
67
67
|
if env.os_name is None:
|
68
68
|
return env.name
|
69
69
|
return env.os_name
|
70
70
|
|
71
71
|
|
72
72
|
@typechecked
|
73
|
-
def
|
73
|
+
def _get_env_default(env: Env) -> str:
|
74
74
|
if is_probably_jinja(env.default):
|
75
75
|
return ''
|
76
76
|
return env.default
|
zrb/shell-scripts/rsync-util.sh
CHANGED
@@ -2,11 +2,11 @@ set -e
|
|
2
2
|
auth_rsync(){
|
3
3
|
if [ "$_CONFIG_SSH_KEY" != "" ]
|
4
4
|
then
|
5
|
-
rsync -avz -e "ssh -i $_CONFIG_SSH_KEY -p $_CONFIG_PORT" $@
|
5
|
+
rsync --mkpath -avz -e "ssh -i $_CONFIG_SSH_KEY -p $_CONFIG_PORT" $@
|
6
6
|
elif [ "$_CONFIG_PASSWORD" != "" ]
|
7
7
|
then
|
8
|
-
sshpass -p "$_CONFIG_PASSWORD" rsync -avz -e "ssh -p $_CONFIG_PORT" $@
|
8
|
+
sshpass -p "$_CONFIG_PASSWORD" rsync --mkpath -avz -e "ssh -p $_CONFIG_PORT" $@
|
9
9
|
else
|
10
|
-
rsync -avz -e "ssh -p $_CONFIG_PORT" $@
|
10
|
+
rsync --mkpath -avz -e "ssh -p $_CONFIG_PORT" $@
|
11
11
|
fi
|
12
12
|
}
|
zrb/task/any_task.py
CHANGED
@@ -65,19 +65,35 @@ class AnyTask(ABC):
|
|
65
65
|
pass
|
66
66
|
|
67
67
|
@abstractmethod
|
68
|
-
def
|
68
|
+
def add_upstream(self, *upstreams: TAnyTask):
|
69
69
|
pass
|
70
70
|
|
71
71
|
@abstractmethod
|
72
|
-
def
|
72
|
+
def insert_input(self, *inputs: AnyInput):
|
73
73
|
pass
|
74
74
|
|
75
75
|
@abstractmethod
|
76
|
-
def
|
76
|
+
def add_input(self, *inputs: AnyInput):
|
77
77
|
pass
|
78
78
|
|
79
79
|
@abstractmethod
|
80
|
-
def
|
80
|
+
def insert_env(self, *envs: Env):
|
81
|
+
pass
|
82
|
+
|
83
|
+
@abstractmethod
|
84
|
+
def add_env(self, *envs: Env):
|
85
|
+
pass
|
86
|
+
|
87
|
+
@abstractmethod
|
88
|
+
def insert_env_file(self, *env_files: EnvFile):
|
89
|
+
pass
|
90
|
+
|
91
|
+
@abstractmethod
|
92
|
+
def add_env_file(self, *env_files: EnvFile):
|
93
|
+
pass
|
94
|
+
|
95
|
+
@abstractmethod
|
96
|
+
def _set_execution_id(self, execution_id: str):
|
81
97
|
pass
|
82
98
|
|
83
99
|
@abstractmethod
|
@@ -114,6 +130,10 @@ class AnyTask(ABC):
|
|
114
130
|
def set_checking_interval(self, new_checking_interval: Union[float, int]):
|
115
131
|
pass
|
116
132
|
|
133
|
+
@abstractmethod
|
134
|
+
def get_execution_id(self) -> str:
|
135
|
+
pass
|
136
|
+
|
117
137
|
@abstractmethod
|
118
138
|
def get_icon(self) -> str:
|
119
139
|
pass
|
@@ -131,31 +151,51 @@ class AnyTask(ABC):
|
|
131
151
|
pass
|
132
152
|
|
133
153
|
@abstractmethod
|
134
|
-
def
|
154
|
+
def get_full_cmd_name(self) -> str:
|
155
|
+
pass
|
156
|
+
|
157
|
+
@abstractmethod
|
158
|
+
def inject_env_files(self):
|
135
159
|
pass
|
136
160
|
|
137
161
|
@abstractmethod
|
138
|
-
def
|
162
|
+
def _get_env_files(self) -> List[EnvFile]:
|
139
163
|
pass
|
140
164
|
|
141
165
|
@abstractmethod
|
142
|
-
def
|
166
|
+
def inject_envs(self):
|
143
167
|
pass
|
144
168
|
|
145
169
|
@abstractmethod
|
146
|
-
def
|
170
|
+
def _get_envs(self) -> List[Env]:
|
147
171
|
pass
|
148
172
|
|
149
173
|
@abstractmethod
|
150
|
-
def
|
174
|
+
def inject_inputs(self):
|
151
175
|
pass
|
152
176
|
|
153
177
|
@abstractmethod
|
154
|
-
def
|
178
|
+
def _get_inputs(self) -> List[AnyInput]:
|
155
179
|
pass
|
156
180
|
|
157
181
|
@abstractmethod
|
158
|
-
def
|
182
|
+
def inject_checkers(self):
|
183
|
+
pass
|
184
|
+
|
185
|
+
@abstractmethod
|
186
|
+
def _get_checkers(self) -> Iterable[TAnyTask]:
|
187
|
+
pass
|
188
|
+
|
189
|
+
@abstractmethod
|
190
|
+
def inject_upstreams(self):
|
191
|
+
pass
|
192
|
+
|
193
|
+
@abstractmethod
|
194
|
+
def _get_upstreams(self) -> Iterable[TAnyTask]:
|
195
|
+
pass
|
196
|
+
|
197
|
+
@abstractmethod
|
198
|
+
def _get_combined_inputs(self) -> Iterable[AnyInput]:
|
159
199
|
pass
|
160
200
|
|
161
201
|
@abstractmethod
|
@@ -198,12 +238,6 @@ class AnyTask(ABC):
|
|
198
238
|
def get_env_map(self) -> Mapping[str, Any]:
|
199
239
|
pass
|
200
240
|
|
201
|
-
@abstractmethod
|
202
|
-
def inject_env_map(
|
203
|
-
self, env_map: Mapping[str, str], override: bool = False
|
204
|
-
):
|
205
|
-
pass
|
206
|
-
|
207
241
|
@abstractmethod
|
208
242
|
def render_any(
|
209
243
|
self, val: Any, data: Optional[Mapping[str, Any]] = None
|
zrb/task/base_remote_cmd_task.py
CHANGED
@@ -2,6 +2,7 @@ from zrb.helper.typing import (
|
|
2
2
|
Any, Callable, Iterable, Mapping, Optional, Union, TypeVar
|
3
3
|
)
|
4
4
|
from zrb.helper.typecheck import typechecked
|
5
|
+
from zrb.helper.util import to_snake_case
|
5
6
|
from zrb.task.any_task import AnyTask
|
6
7
|
from zrb.task.any_task_event_handler import (
|
7
8
|
OnTriggered, OnWaiting, OnSkipped, OnStarted, OnReady, OnRetry, OnFailed
|
@@ -34,13 +35,15 @@ class RemoteConfig:
|
|
34
35
|
user: str = '',
|
35
36
|
password: str = '',
|
36
37
|
ssh_key: str = '',
|
37
|
-
port: int = 22
|
38
|
+
port: int = 22,
|
39
|
+
config_map: Optional[Mapping[str, str]] = None
|
38
40
|
):
|
39
41
|
self.host = host
|
40
42
|
self.user = user
|
41
43
|
self.password = password
|
42
44
|
self.ssh_key = ssh_key
|
43
45
|
self.port = port
|
46
|
+
self.config_map = {} if config_map is None else config_map
|
44
47
|
|
45
48
|
|
46
49
|
@typechecked
|
@@ -123,28 +126,50 @@ class SingleBaseRemoteCmdTask(CmdTask):
|
|
123
126
|
def copy(self) -> TSingleBaseRemoteCmdTask:
|
124
127
|
return copy.deepcopy(self)
|
125
128
|
|
126
|
-
def
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
129
|
+
def inject_envs(self):
|
130
|
+
super().inject_envs()
|
131
|
+
# add remote config properties as env
|
132
|
+
self.add_env(
|
133
|
+
Env(
|
134
|
+
name='_CONFIG_HOST', os_name='',
|
135
|
+
default=self.render_str(self._remote_config.host)
|
136
|
+
),
|
137
|
+
Env(
|
138
|
+
name='_CONFIG_PORT', os_name='',
|
139
|
+
default=str(self.render_int(self._remote_config.port))
|
140
|
+
),
|
141
|
+
Env(
|
142
|
+
name='_CONFIG_SSH_KEY', os_name='',
|
143
|
+
default=self.render_str(self._remote_config.ssh_key)
|
144
|
+
),
|
145
|
+
Env(
|
146
|
+
name='_CONFIG_USER', os_name='',
|
147
|
+
default=self.render_str(self._remote_config.user)
|
148
|
+
),
|
149
|
+
Env(
|
150
|
+
name='_CONFIG_PASSWORD', os_name='',
|
151
|
+
default=self.render_str(self._remote_config.password)
|
152
|
+
),
|
138
153
|
)
|
139
|
-
|
154
|
+
for key, val in self._remote_config.config_map.items():
|
155
|
+
upper_snake_key = to_snake_case(key).upper()
|
156
|
+
rendered_val = self.render_str(val)
|
157
|
+
# add remote config map as env
|
158
|
+
self.add_env(
|
159
|
+
Env(
|
160
|
+
name='_CONFIG_MAP_' + upper_snake_key,
|
161
|
+
os_name='',
|
162
|
+
default=rendered_val
|
163
|
+
)
|
164
|
+
)
|
140
165
|
|
141
|
-
def
|
166
|
+
def get_cmd_script(self, *args: Any, **kwargs: Any) -> str:
|
142
167
|
cmd_str = '\n'.join([
|
143
|
-
self.
|
168
|
+
self._create_cmd_script(
|
144
169
|
self._pre_cmd_path, self._pre_cmd, *args, **kwargs
|
145
170
|
),
|
146
|
-
super().
|
147
|
-
self.
|
171
|
+
super().get_cmd_script(*args, **kwargs),
|
172
|
+
self._create_cmd_script(
|
148
173
|
self._post_cmd_path, self._post_cmd, *args, **kwargs
|
149
174
|
),
|
150
175
|
])
|
zrb/task/base_task.py
CHANGED
@@ -12,11 +12,13 @@ from zrb.task.base_task_composite import (
|
|
12
12
|
)
|
13
13
|
from zrb.advertisement import advertisements
|
14
14
|
from zrb.task_group.group import Group
|
15
|
+
from zrb.task_env.constant import RESERVED_ENV_NAMES
|
15
16
|
from zrb.task_env.env import Env
|
16
17
|
from zrb.task_env.env_file import EnvFile
|
17
18
|
from zrb.task_input.any_input import AnyInput
|
18
19
|
from zrb.task_input.constant import RESERVED_INPUT_NAMES
|
19
20
|
from zrb.helper.accessories.color import colored
|
21
|
+
from zrb.helper.accessories.name import get_random_name
|
20
22
|
from zrb.helper.advertisement import get_advertisement
|
21
23
|
from zrb.helper.string.modification import double_quote
|
22
24
|
from zrb.helper.string.conversion import to_variable_name
|
@@ -108,30 +110,28 @@ class BaseTask(
|
|
108
110
|
self._is_execution_started: bool = False
|
109
111
|
self._args: List[Any] = []
|
110
112
|
self._kwargs: Mapping[str, Any] = {}
|
111
|
-
self._allow_add_upstreams: bool = True
|
112
113
|
|
113
114
|
def copy(self) -> AnyTask:
|
114
115
|
return copy.deepcopy(self)
|
115
116
|
|
116
|
-
def
|
117
|
+
def _get_combined_inputs(self) -> Iterable[AnyInput]:
|
117
118
|
''''
|
118
119
|
Getting all inputs of this task and all its upstream, non-duplicated.
|
119
120
|
'''
|
120
121
|
if self._all_inputs is not None:
|
121
122
|
return self._all_inputs
|
122
|
-
self._allow_add_upstreams = False
|
123
|
-
self._allow_add_inputs = False
|
124
123
|
self._all_inputs: List[AnyInput] = []
|
125
124
|
existing_input_names: Mapping[str, bool] = {}
|
126
125
|
# Add task inputs
|
127
|
-
|
126
|
+
inputs = self._get_inputs()
|
127
|
+
for input_index, first_occurence_task_input in enumerate(inputs):
|
128
128
|
input_name = first_occurence_task_input.get_name()
|
129
129
|
if input_name in existing_input_names:
|
130
130
|
continue
|
131
131
|
# Look for all input with the same name in the current task
|
132
132
|
task_inputs = [
|
133
133
|
candidate
|
134
|
-
for candidate in
|
134
|
+
for candidate in inputs[input_index:]
|
135
135
|
if candidate.get_name() == input_name
|
136
136
|
]
|
137
137
|
# Get the last input, and add it to _all_inputs
|
@@ -139,13 +139,15 @@ class BaseTask(
|
|
139
139
|
self._all_inputs.append(task_input)
|
140
140
|
existing_input_names[input_name] = True
|
141
141
|
# Add upstream inputs
|
142
|
-
for upstream in self.
|
143
|
-
upstream_inputs = upstream.
|
142
|
+
for upstream in self._get_upstreams():
|
143
|
+
upstream_inputs = upstream._get_combined_inputs()
|
144
144
|
for upstream_input in upstream_inputs:
|
145
145
|
if upstream_input.get_name() in existing_input_names:
|
146
146
|
continue
|
147
147
|
self._all_inputs.append(upstream_input)
|
148
148
|
existing_input_names[upstream_input.get_name()] = True
|
149
|
+
self._allow_add_upstreams = False
|
150
|
+
self._allow_add_inputs = False
|
149
151
|
return self._all_inputs
|
150
152
|
|
151
153
|
def to_function(
|
@@ -165,21 +167,6 @@ class BaseTask(
|
|
165
167
|
))
|
166
168
|
return function
|
167
169
|
|
168
|
-
def add_upstreams(self, *upstreams: AnyTask):
|
169
|
-
if not self._allow_add_upstreams:
|
170
|
-
raise Exception(f'Cannot add upstreams on `{self._name}`')
|
171
|
-
self._upstreams += upstreams
|
172
|
-
|
173
|
-
def inject_env_map(
|
174
|
-
self, env_map: Mapping[str, str], override: bool = False
|
175
|
-
):
|
176
|
-
'''
|
177
|
-
Set new values for current task's env map
|
178
|
-
'''
|
179
|
-
for key, val in env_map.items():
|
180
|
-
if override or key not in self.get_env_map():
|
181
|
-
self._set_env_map(key, val)
|
182
|
-
|
183
170
|
async def run(self, *args: Any, **kwargs: Any) -> Any:
|
184
171
|
'''
|
185
172
|
Do task execution
|
@@ -257,38 +244,42 @@ class BaseTask(
|
|
257
244
|
return True
|
258
245
|
self._is_keyval_set = True
|
259
246
|
self.log_info('Set input map')
|
260
|
-
for task_input in self.
|
247
|
+
for task_input in self._get_combined_inputs():
|
261
248
|
input_name = self._get_normalized_input_key(task_input.get_name())
|
262
249
|
input_value = self.render_any(
|
263
250
|
kwargs.get(input_name, task_input.get_default())
|
264
251
|
)
|
265
252
|
self._set_input_map(input_name, input_value)
|
253
|
+
self._set_input_map('_execution_id', self._execution_id)
|
266
254
|
self.log_debug(
|
267
255
|
'Input map:\n' + map_to_str(self.get_input_map(), item_prefix=' ')
|
268
256
|
)
|
269
257
|
self.log_info('Merging task envs, task env files, and native envs')
|
270
|
-
for env_name, env in self.
|
258
|
+
for env_name, env in self._get_combined_env().items():
|
271
259
|
env_value = env.get(env_prefix)
|
272
260
|
if env.renderable:
|
273
261
|
env_value = self.render_any(env_value)
|
274
262
|
self._set_env_map(env_name, env_value)
|
263
|
+
self._set_env_map('_ZRB_EXECUTION_ID', self._execution_id)
|
275
264
|
self.log_debug(
|
276
265
|
'Env map:\n' + map_to_str(self.get_env_map(), item_prefix=' ')
|
277
266
|
)
|
278
267
|
|
279
|
-
def
|
280
|
-
self._allow_add_envs = False
|
281
|
-
self._allow_add_env_files = False
|
268
|
+
def _get_combined_env(self) -> Mapping[str, Env]:
|
282
269
|
all_envs: Mapping[str, Env] = {}
|
283
270
|
for env_name in os.environ:
|
271
|
+
if env_name in RESERVED_ENV_NAMES:
|
272
|
+
continue
|
284
273
|
all_envs[env_name] = Env(
|
285
274
|
name=env_name, os_name=env_name, renderable=False
|
286
275
|
)
|
287
|
-
for env_file in self.
|
276
|
+
for env_file in self._get_env_files():
|
288
277
|
for env in env_file.get_envs():
|
289
278
|
all_envs[env.name] = env
|
290
|
-
for env in self.
|
279
|
+
for env in self._get_envs():
|
291
280
|
all_envs[env.name] = env
|
281
|
+
self._allow_add_envs = False
|
282
|
+
self._allow_add_env_files = False
|
292
283
|
return all_envs
|
293
284
|
|
294
285
|
def _get_normalized_input_key(self, key: str) -> str:
|
@@ -305,6 +296,10 @@ class BaseTask(
|
|
305
296
|
):
|
306
297
|
try:
|
307
298
|
self._start_timer()
|
299
|
+
if self.get_execution_id() == '':
|
300
|
+
self._set_execution_id(
|
301
|
+
get_random_name(add_random_digit=True, digit_count=5)
|
302
|
+
)
|
308
303
|
self.log_info('Set input and env map')
|
309
304
|
await self._set_keyval(kwargs=kwargs, env_prefix=env_prefix)
|
310
305
|
self.log_info('Set run kwargs')
|
@@ -342,9 +337,10 @@ class BaseTask(
|
|
342
337
|
return
|
343
338
|
if self._return_upstream_result:
|
344
339
|
# if _return_upstream_result, result is list (see: self._run_all)
|
340
|
+
upstreams = self._get_upstreams()
|
345
341
|
upstream_results = list(result)
|
346
342
|
for upstream_index, upstream_result in enumerate(upstream_results):
|
347
|
-
|
343
|
+
upstreams[upstream_index]._print_result(upstream_result)
|
348
344
|
return
|
349
345
|
self.print_result(result)
|
350
346
|
|
@@ -382,14 +378,14 @@ class BaseTask(
|
|
382
378
|
|
383
379
|
def _show_run_command(self):
|
384
380
|
params: List[str] = [double_quote(arg) for arg in self._args]
|
385
|
-
for task_input in self.
|
381
|
+
for task_input in self._get_combined_inputs():
|
386
382
|
if task_input.is_hidden():
|
387
383
|
continue
|
388
384
|
key = task_input.get_name()
|
389
385
|
kwarg_key = self._get_normalized_input_key(key)
|
390
386
|
quoted_value = double_quote(str(self._kwargs[kwarg_key]))
|
391
387
|
params.append(f'--{key} {quoted_value}')
|
392
|
-
run_cmd = self.
|
388
|
+
run_cmd = self.get_full_cmd_name()
|
393
389
|
run_cmd_with_param = run_cmd
|
394
390
|
if len(params) > 0:
|
395
391
|
param_str = ' '.join(params)
|
@@ -426,6 +422,7 @@ class BaseTask(
|
|
426
422
|
await asyncio.sleep(0.1)
|
427
423
|
check_coroutines: Iterable[asyncio.Task] = []
|
428
424
|
for checker_task in self._checkers:
|
425
|
+
checker_task._set_execution_id(self.get_execution_id())
|
429
426
|
check_coroutines.append(
|
430
427
|
asyncio.create_task(checker_task._run_all())
|
431
428
|
)
|
@@ -437,7 +434,8 @@ class BaseTask(
|
|
437
434
|
coroutines: Iterable[asyncio.Task] = []
|
438
435
|
# Add upstream tasks to processes
|
439
436
|
self._allow_add_upstreams = False
|
440
|
-
for upstream_task in self.
|
437
|
+
for upstream_task in self._get_upstreams():
|
438
|
+
upstream_task._set_execution_id(self.get_execution_id())
|
441
439
|
coroutines.append(asyncio.create_task(
|
442
440
|
upstream_task._run_all(**kwargs)
|
443
441
|
))
|
@@ -459,7 +457,7 @@ class BaseTask(
|
|
459
457
|
# get upstream checker
|
460
458
|
upstream_check_processes: Iterable[asyncio.Task] = []
|
461
459
|
self._allow_add_upstreams = False
|
462
|
-
for upstream_task in self.
|
460
|
+
for upstream_task in self._get_upstreams():
|
463
461
|
upstream_check_processes.append(asyncio.create_task(
|
464
462
|
upstream_task._loop_check()
|
465
463
|
))
|
@@ -503,7 +501,7 @@ class BaseTask(
|
|
503
501
|
|
504
502
|
async def _set_keyval(self, kwargs: Mapping[str, Any], env_prefix: str):
|
505
503
|
# if input is not in input_map, add default values
|
506
|
-
for task_input in self.
|
504
|
+
for task_input in self._get_combined_inputs():
|
507
505
|
key = self._get_normalized_input_key(task_input.get_name())
|
508
506
|
if key in kwargs:
|
509
507
|
continue
|
@@ -514,20 +512,20 @@ class BaseTask(
|
|
514
512
|
new_kwargs = copy.deepcopy(kwargs)
|
515
513
|
new_kwargs.update(self.get_input_map())
|
516
514
|
upstream_coroutines = []
|
517
|
-
# set
|
515
|
+
# set upstreams keyval
|
518
516
|
self._allow_add_upstreams = False
|
519
|
-
for upstream_task in self.
|
517
|
+
for upstream_task in self._get_upstreams():
|
520
518
|
upstream_coroutines.append(asyncio.create_task(
|
521
519
|
upstream_task._set_keyval(
|
522
520
|
kwargs=new_kwargs, env_prefix=env_prefix
|
523
521
|
)
|
524
522
|
))
|
525
523
|
# set checker keyval
|
526
|
-
local_env_map = self.get_env_map()
|
524
|
+
# local_env_map = self.get_env_map()
|
527
525
|
checker_coroutines = []
|
528
526
|
for checker_task in self._checkers:
|
529
|
-
checker_task.
|
530
|
-
checker_task.
|
527
|
+
checker_task.add_input(*self._get_inputs())
|
528
|
+
checker_task.add_env(*self._get_envs())
|
531
529
|
checker_coroutines.append(asyncio.create_task(
|
532
530
|
checker_task._set_keyval(
|
533
531
|
kwargs=new_kwargs, env_prefix=env_prefix
|
zrb/task/base_task_composite.py
CHANGED
@@ -66,6 +66,17 @@ class CommonTaskModel():
|
|
66
66
|
self._allow_add_envs = True
|
67
67
|
self._allow_add_env_files = True
|
68
68
|
self._allow_add_inputs = True
|
69
|
+
self._allow_add_upstreams: bool = True
|
70
|
+
self._has_already_inject_env_files: bool = False
|
71
|
+
self._has_already_inject_envs: bool = False
|
72
|
+
self._has_already_inject_inputs: bool = False
|
73
|
+
self._has_already_inject_checkers: bool = False
|
74
|
+
self._has_already_inject_upstreams: bool = False
|
75
|
+
self._execution_id = ''
|
76
|
+
|
77
|
+
def _set_execution_id(self, execution_id: str):
|
78
|
+
if self._execution_id != '':
|
79
|
+
self._execution_id = execution_id
|
69
80
|
|
70
81
|
def set_name(self, new_name: str):
|
71
82
|
if self._description == self._name:
|
@@ -95,20 +106,48 @@ class CommonTaskModel():
|
|
95
106
|
def set_checking_interval(self, new_checking_interval: Union[float, int]):
|
96
107
|
self._checking_interval = new_checking_interval
|
97
108
|
|
98
|
-
def
|
109
|
+
def insert_input(self, *inputs: AnyInput):
|
99
110
|
if not self._allow_add_inputs:
|
100
|
-
raise Exception(f'Cannot
|
101
|
-
self._inputs
|
111
|
+
raise Exception(f'Cannot insert inputs for `{self._name}`')
|
112
|
+
self._inputs = list(inputs) + list(self._inputs)
|
102
113
|
|
103
|
-
def
|
114
|
+
def add_input(self, *inputs: AnyInput):
|
115
|
+
if not self._allow_add_inputs:
|
116
|
+
raise Exception(f'Cannot add inputs for `{self._name}`')
|
117
|
+
self._inputs = list(self._inputs) + list(inputs)
|
118
|
+
|
119
|
+
def insert_env(self, *envs: Env):
|
120
|
+
if not self._allow_add_envs:
|
121
|
+
raise Exception(f'Cannot insert envs to `{self._name}`')
|
122
|
+
self._envs = list(envs) + list(self._envs)
|
123
|
+
|
124
|
+
def add_env(self, *envs: Env):
|
104
125
|
if not self._allow_add_envs:
|
105
|
-
raise Exception(f'Cannot add envs
|
106
|
-
self._envs
|
126
|
+
raise Exception(f'Cannot add envs to `{self._name}`')
|
127
|
+
self._envs = list(self._envs) + list(envs)
|
107
128
|
|
108
|
-
def
|
129
|
+
def insert_env_file(self, *env_files: EnvFile):
|
109
130
|
if not self._allow_add_env_files:
|
110
|
-
raise Exception(f'Cannot
|
111
|
-
self._env_files
|
131
|
+
raise Exception(f'Cannot insert env_files to `{self._name}`')
|
132
|
+
self._env_files = list(env_files) + list(self._env_files)
|
133
|
+
|
134
|
+
def add_env_file(self, *env_files: EnvFile):
|
135
|
+
if not self._allow_add_env_files:
|
136
|
+
raise Exception(f'Cannot add env_files to `{self._name}`')
|
137
|
+
self._env_files = list(self._env_files) + list(env_files)
|
138
|
+
|
139
|
+
def insert_upstream(self, *upstreams: AnyTask):
|
140
|
+
if not self._allow_add_upstreams:
|
141
|
+
raise Exception(f'Cannot insert upstreams to `{self._name}`')
|
142
|
+
self._upstreams = list(upstreams) + list(self._upstreams)
|
143
|
+
|
144
|
+
def add_upstream(self, *upstreams: AnyTask):
|
145
|
+
if not self._allow_add_upstreams:
|
146
|
+
raise Exception(f'Cannot add upstreams to `{self._name}`')
|
147
|
+
self._upstreams = list(self._upstreams) + list(upstreams)
|
148
|
+
|
149
|
+
def get_execution_id(self) -> str:
|
150
|
+
return self._execution_id
|
112
151
|
|
113
152
|
def get_icon(self) -> str:
|
114
153
|
return self._icon
|
@@ -116,20 +155,50 @@ class CommonTaskModel():
|
|
116
155
|
def get_color(self) -> str:
|
117
156
|
return self._color
|
118
157
|
|
119
|
-
def
|
158
|
+
def inject_env_files(self):
|
159
|
+
pass
|
160
|
+
|
161
|
+
def _get_env_files(self) -> List[EnvFile]:
|
162
|
+
if not self._has_already_inject_env_files:
|
163
|
+
self.inject_env_files()
|
164
|
+
self._has_already_inject_env_files = True
|
120
165
|
return self._env_files
|
121
166
|
|
122
|
-
def
|
123
|
-
|
167
|
+
def inject_envs(self):
|
168
|
+
pass
|
169
|
+
|
170
|
+
def _get_envs(self) -> List[Env]:
|
171
|
+
if not self._has_already_inject_envs:
|
172
|
+
self.inject_envs()
|
173
|
+
self._has_already_inject_envs = True
|
174
|
+
return list(self._envs)
|
175
|
+
|
176
|
+
def inject_inputs(self):
|
177
|
+
pass
|
178
|
+
|
179
|
+
def _get_inputs(self) -> List[AnyInput]:
|
180
|
+
if not self._has_already_inject_inputs:
|
181
|
+
self.inject_inputs()
|
182
|
+
self._has_already_inject_inputs = True
|
183
|
+
return list(self._inputs)
|
184
|
+
|
185
|
+
def inject_checkers(self):
|
186
|
+
pass
|
124
187
|
|
125
|
-
def
|
126
|
-
|
188
|
+
def _get_checkers(self) -> List[AnyTask]:
|
189
|
+
if not self._has_already_inject_checkers:
|
190
|
+
self.inject_checkers()
|
191
|
+
self._has_already_inject_checkers = True
|
192
|
+
return list(self._checkers)
|
127
193
|
|
128
|
-
def
|
129
|
-
|
194
|
+
def inject_upstreams(self):
|
195
|
+
pass
|
130
196
|
|
131
|
-
def
|
132
|
-
|
197
|
+
def _get_upstreams(self) -> List[AnyTask]:
|
198
|
+
if not self._has_already_inject_upstreams:
|
199
|
+
self.inject_upstreams()
|
200
|
+
self._has_already_inject_upstreams = True
|
201
|
+
return list(self._upstreams)
|
133
202
|
|
134
203
|
def get_description(self) -> str:
|
135
204
|
return self._description
|
@@ -354,7 +423,7 @@ class TaskModelWithPrinterAndTracker(
|
|
354
423
|
run: Optional[Callable[..., Any]] = None,
|
355
424
|
should_execute: Union[bool, str, Callable[..., bool]] = True
|
356
425
|
):
|
357
|
-
self.
|
426
|
+
self._rjust_full_cmd_name: Optional[str] = None
|
358
427
|
self._has_cli_interface = False
|
359
428
|
self._complete_name: Optional[str] = None
|
360
429
|
CommonTaskModel.__init__(
|
@@ -441,13 +510,13 @@ class TaskModelWithPrinterAndTracker(
|
|
441
510
|
def _get_print_prefix(self) -> str:
|
442
511
|
common_prefix = self._get_common_prefix(show_time=show_time)
|
443
512
|
icon = self.get_icon()
|
444
|
-
truncated_name = self.
|
513
|
+
truncated_name = self._get_rjust_full_cmd_name()
|
445
514
|
return f'{common_prefix} {icon} {truncated_name}'
|
446
515
|
|
447
516
|
def _get_log_prefix(self) -> str:
|
448
517
|
common_prefix = self._get_common_prefix(show_time=False)
|
449
518
|
icon = self.get_icon()
|
450
|
-
filled_name = self.
|
519
|
+
filled_name = self._get_rjust_full_cmd_name()
|
451
520
|
return f'{common_prefix} {icon} {filled_name}'
|
452
521
|
|
453
522
|
def _get_common_prefix(self, show_time: bool) -> str:
|
@@ -459,14 +528,14 @@ class TaskModelWithPrinterAndTracker(
|
|
459
528
|
return f'◷ {now} ❁ {pid} → {attempt}/{max_attempt}'
|
460
529
|
return f'❁ {pid} → {attempt}/{max_attempt}'
|
461
530
|
|
462
|
-
def
|
463
|
-
if self.
|
464
|
-
return self.
|
465
|
-
complete_name = self.
|
466
|
-
self.
|
467
|
-
return self.
|
531
|
+
def _get_rjust_full_cmd_name(self) -> str:
|
532
|
+
if self._rjust_full_cmd_name is not None:
|
533
|
+
return self._rjust_full_cmd_name
|
534
|
+
complete_name = self.get_full_cmd_name()
|
535
|
+
self._rjust_full_cmd_name = complete_name.rjust(LOG_NAME_LENGTH, ' ')
|
536
|
+
return self._rjust_full_cmd_name
|
468
537
|
|
469
|
-
def
|
538
|
+
def get_full_cmd_name(self) -> str:
|
470
539
|
if self._complete_name is not None:
|
471
540
|
return self._complete_name
|
472
541
|
executable_prefix = ''
|
zrb/task/cmd_task.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from zrb.helper.typing import (
|
2
|
-
Any, Callable, Iterable, List,
|
2
|
+
Any, Callable, Iterable, List, Optional, Union, TypeVar
|
3
3
|
)
|
4
4
|
from zrb.helper.typecheck import typechecked
|
5
5
|
from zrb.task.any_task import AnyTask
|
@@ -182,18 +182,17 @@ class CmdTask(BaseTask):
|
|
182
182
|
return
|
183
183
|
print(result.output)
|
184
184
|
|
185
|
-
def
|
186
|
-
|
185
|
+
def inject_envs(self):
|
186
|
+
super().inject_envs()
|
187
187
|
input_map = self.get_input_map()
|
188
188
|
for input_name, input_value in input_map.items():
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
189
|
+
env_name = '_INPUT_' + input_name.upper()
|
190
|
+
self.add_env(
|
191
|
+
Env(name=env_name, os_name='', default=str(input_value))
|
192
|
+
)
|
193
193
|
|
194
194
|
async def run(self, *args: Any, **kwargs: Any) -> CmdResult:
|
195
|
-
cmd = self.
|
196
|
-
env_map = self._get_shell_env_map()
|
195
|
+
cmd = self.get_cmd_script(*args, **kwargs)
|
197
196
|
self.print_out_dark('Run script: ' + self._get_multiline_repr(cmd))
|
198
197
|
self.print_out_dark('Working directory: ' + self._cwd)
|
199
198
|
self._output_buffer = []
|
@@ -203,7 +202,7 @@ class CmdTask(BaseTask):
|
|
203
202
|
cwd=self._cwd,
|
204
203
|
stdout=asyncio.subprocess.PIPE,
|
205
204
|
stderr=asyncio.subprocess.PIPE,
|
206
|
-
env=
|
205
|
+
env=self.get_env_map(),
|
207
206
|
shell=True,
|
208
207
|
executable=self._executable,
|
209
208
|
close_fds=True,
|
@@ -314,21 +313,25 @@ class CmdTask(BaseTask):
|
|
314
313
|
await stdout_log_process
|
315
314
|
await stderr_log_process
|
316
315
|
|
317
|
-
def
|
318
|
-
return self.
|
316
|
+
def get_cmd_script(self, *args: Any, **kwargs: Any) -> str:
|
317
|
+
return self._create_cmd_script(
|
318
|
+
self._cmd_path, self._cmd, *args, **kwargs
|
319
|
+
)
|
319
320
|
|
320
|
-
def
|
321
|
+
def _create_cmd_script(
|
321
322
|
self, cmd_path: CmdVal, cmd: CmdVal, *args: Any, **kwargs: Any
|
322
323
|
) -> str:
|
323
324
|
if not isinstance(cmd_path, str) or cmd_path != '':
|
324
325
|
if callable(cmd_path):
|
325
|
-
return self.
|
326
|
-
return self.
|
326
|
+
return self._get_rendered_cmd_path(cmd_path(*args, **kwargs))
|
327
|
+
return self._get_rendered_cmd_path(cmd_path)
|
327
328
|
if callable(cmd):
|
328
|
-
return self.
|
329
|
-
return self.
|
329
|
+
return self._get_rendered_cmd(cmd(*args, **kwargs))
|
330
|
+
return self._get_rendered_cmd(cmd)
|
330
331
|
|
331
|
-
def
|
332
|
+
def _get_rendered_cmd_path(
|
333
|
+
self, cmd_path: Union[str, Iterable[str]]
|
334
|
+
) -> str:
|
332
335
|
if isinstance(cmd_path, str):
|
333
336
|
return self.render_file(cmd_path)
|
334
337
|
return '\n'.join([
|
@@ -336,7 +339,7 @@ class CmdTask(BaseTask):
|
|
336
339
|
for cmd_path_str in cmd_path
|
337
340
|
])
|
338
341
|
|
339
|
-
def
|
342
|
+
def _get_rendered_cmd(self, cmd: Union[str, Iterable[str]]) -> str:
|
340
343
|
if isinstance(cmd, str):
|
341
344
|
return self.render_str(cmd)
|
342
345
|
return self.render_str('\n'.join(list(cmd)))
|
zrb/task/docker_compose_task.py
CHANGED
@@ -7,6 +7,7 @@ from zrb.task.any_task import AnyTask
|
|
7
7
|
from zrb.task.any_task_event_handler import (
|
8
8
|
OnTriggered, OnWaiting, OnSkipped, OnStarted, OnReady, OnRetry, OnFailed
|
9
9
|
)
|
10
|
+
from zrb.task_env.constant import RESERVED_ENV_NAMES
|
10
11
|
from zrb.task_env.env import Env
|
11
12
|
from zrb.task_env.env_file import EnvFile
|
12
13
|
from zrb.task_group.group import Group
|
@@ -152,7 +153,8 @@ class DockerComposeTask(CmdTask):
|
|
152
153
|
)
|
153
154
|
# Flag to make mark whether service config and compose environments
|
154
155
|
# has been added to this task's envs and env_files
|
155
|
-
self.
|
156
|
+
self._is_compose_additional_env_added = False
|
157
|
+
self._is_compose_additional_env_file_added = False
|
156
158
|
|
157
159
|
def copy(self) -> TDockerComposeTask:
|
158
160
|
return super().copy()
|
@@ -165,45 +167,30 @@ class DockerComposeTask(CmdTask):
|
|
165
167
|
os.remove(self._compose_runtime_file)
|
166
168
|
return result
|
167
169
|
|
168
|
-
def
|
169
|
-
|
170
|
-
|
171
|
-
Whenever _get_all_envs is called, we want to make sure that:
|
172
|
-
- Service config's envs and env_files are included
|
173
|
-
- Any environment defined in docker compose file is also included
|
174
|
-
'''
|
175
|
-
if self._is_additional_env_added:
|
176
|
-
return super()._get_all_envs()
|
177
|
-
self._is_additional_env_added = True
|
178
|
-
# define additional envs and additonal env_files
|
179
|
-
additional_envs: List[Env] = []
|
180
|
-
additional_env_files: List[EnvFile] = []
|
181
|
-
# populate additional envs and additional env_files
|
182
|
-
# with service configs
|
170
|
+
def inject_envs(self):
|
171
|
+
super().inject_envs()
|
172
|
+
# inject envs from service_configs
|
183
173
|
for _, service_config in self._compose_service_configs.items():
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
env_map = fetch_compose_file_env_map(data)
|
190
|
-
registered_env_map: Mapping[str, bool] = {}
|
174
|
+
self.insert_env(*service_config.get_envs())
|
175
|
+
# inject envs from docker compose file
|
176
|
+
compose_data = read_compose_file(self._compose_template_file)
|
177
|
+
env_map = fetch_compose_file_env_map(compose_data)
|
178
|
+
added_env_map: Mapping[str, bool] = {}
|
191
179
|
for key, value in env_map.items():
|
192
180
|
# Need to get this everytime because we only want
|
193
181
|
# the first compose file env value for a certain key
|
194
|
-
if key in
|
182
|
+
if key in RESERVED_ENV_NAMES or key in added_env_map:
|
195
183
|
continue
|
184
|
+
added_env_map[key] = True
|
196
185
|
os_name = key
|
197
186
|
if self._compose_env_prefix != '':
|
198
187
|
os_name = f'{self._compose_env_prefix}_{os_name}'
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
#
|
203
|
-
|
204
|
-
|
205
|
-
# get all envs
|
206
|
-
return super()._get_all_envs()
|
188
|
+
self.insert_env(Env(name=key, os_name=os_name, default=value))
|
189
|
+
|
190
|
+
def inject_env_files(self):
|
191
|
+
# inject env_files from service_configs
|
192
|
+
for _, service_config in self._compose_service_configs.items():
|
193
|
+
self.insert_env_file(*service_config.get_env_files())
|
207
194
|
|
208
195
|
def _generate_compose_runtime_file(self):
|
209
196
|
compose_data = read_compose_file(self._compose_template_file)
|
@@ -310,8 +297,8 @@ class DockerComposeTask(CmdTask):
|
|
310
297
|
return os.path.join(self._cwd, compose_file)
|
311
298
|
raise Exception(f'Invalid compose file: {compose_file}')
|
312
299
|
|
313
|
-
def
|
314
|
-
setup_cmd_str = self.
|
300
|
+
def get_cmd_script(self, *args: Any, **kwargs: Any) -> str:
|
301
|
+
setup_cmd_str = self._create_cmd_script(
|
315
302
|
self._setup_cmd_path, self._setup_cmd, *args, **kwargs
|
316
303
|
)
|
317
304
|
command_options = dict(self._compose_options)
|
zrb/task/flow_task.py
CHANGED
@@ -107,10 +107,10 @@ class FlowTask(BaseTask):
|
|
107
107
|
embeded_tasks: List[AnyTask] = []
|
108
108
|
for task in tasks:
|
109
109
|
embeded_task = task.copy()
|
110
|
-
embeded_task.
|
111
|
-
embeded_task.
|
112
|
-
embeded_task.
|
113
|
-
embeded_task.
|
110
|
+
embeded_task.add_upstream(*upstreams)
|
111
|
+
embeded_task.add_env(*envs)
|
112
|
+
embeded_task.add_env_file(*env_files)
|
113
|
+
embeded_task.add_input(*inputs)
|
114
114
|
embeded_tasks.append(embeded_task)
|
115
115
|
return embeded_tasks
|
116
116
|
|
zrb/task_env/constant.py
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
RESERVED_ENV_NAMES = ('_ZRB_EXECUTION_ID',)
|
zrb/task_env/env.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from zrb.helper.typing import Optional
|
2
2
|
from zrb.helper.typecheck import typechecked
|
3
|
+
from zrb.task_env.constant import RESERVED_ENV_NAMES
|
3
4
|
import os
|
4
5
|
|
5
6
|
|
@@ -16,6 +17,8 @@ class Env():
|
|
16
17
|
default: str = '',
|
17
18
|
renderable: bool = True,
|
18
19
|
):
|
20
|
+
if name in RESERVED_ENV_NAMES:
|
21
|
+
raise ValueError(f'Forbidden input name: {name}')
|
19
22
|
self.name: str = name
|
20
23
|
self.os_name: str = os_name if os_name is not None else name
|
21
24
|
self.default: str = default
|
zrb/task_env/env_file.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from zrb.helper.typing import List, Optional
|
2
2
|
from zrb.helper.typecheck import typechecked
|
3
3
|
from dotenv import dotenv_values
|
4
|
+
from zrb.task_env.constant import RESERVED_ENV_NAMES
|
4
5
|
from zrb.task_env.env import Env
|
5
6
|
|
6
7
|
|
@@ -25,6 +26,8 @@ class EnvFile():
|
|
25
26
|
env_list: List[Env] = []
|
26
27
|
env_map = dotenv_values(self.env_file)
|
27
28
|
for key, value in env_map.items():
|
29
|
+
if key in RESERVED_ENV_NAMES:
|
30
|
+
continue
|
28
31
|
os_name: Optional[str] = None
|
29
32
|
if self.prefix is not None and self.prefix != '':
|
30
33
|
os_name = f'{self.prefix}_{key}'
|
zrb/task_input/constant.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
RESERVED_INPUT_NAMES = ('_task', '_args')
|
1
|
+
RESERVED_INPUT_NAMES = ('_task', '_args', '_execution_id')
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: zrb
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.110
|
4
4
|
Summary: Super framework for your super app
|
5
5
|
Author-email: Go Frendi Gunawan <gofrendiasgard@gmail.com>
|
6
6
|
Requires-Python: >=3.10.0
|
@@ -30,9 +30,9 @@ Provides-Extra: test
|
|
30
30
|
|
31
31
|
# 🤖 Zrb (Read: Zaruba) : A Super Framework for Your Super App
|
32
32
|
|
33
|
-

|
34
34
|
|
35
|
-
[📖 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) | [💃 Oops, I did it Again](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)
|
35
|
+
[📖 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) | [💃 Oops, I did it Again](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
36
|
|
37
37
|
Zrb is a [CLI-based](https://en.wikipedia.org/wiki/Command-line_interface) automation [tool](https://en.wikipedia.org/wiki/Programming_tool) and [low-code](https://en.wikipedia.org/wiki/Low-code_development_platform) platform. Once installed, Zrb will help you automate day-to-day tasks, generate projects and applications, and even deploy your applications to Kubernetes with a few commands.
|
38
38
|
|
@@ -40,7 +40,7 @@ To use Zrb, you need to be familiar with CLI.
|
|
40
40
|
|
41
41
|
Zrb task definitions are written in [Python](https://www.python.org/), and we have a [very good reason](https://github.com/state-alchemists/zrb/blob/main/docs/faq/why-python.md) behind the decision.
|
42
42
|
|
43
|
-
## Zrb
|
43
|
+
## Zrb is A Low-Code Framework
|
44
44
|
|
45
45
|
Let's see how you can build and run a [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) application.
|
46
46
|
|
@@ -69,9 +69,9 @@ zrb project start-fastapp --fastapp-run-mode "monolith"
|
|
69
69
|
|
70
70
|
You will be able to access the application by pointing your browser to [http://localhost:3000](http://localhost:3000)
|
71
71
|
|
72
|
-

|
73
73
|
|
74
|
-
Furthermore, you can
|
74
|
+
Furthermore, you can run the same application as `microservices`, run the application as `docker containers`, and even do some deployments into your `kubernetes cluster`.
|
75
75
|
|
76
76
|
|
77
77
|
```bash
|
@@ -90,9 +90,9 @@ zrb project deploy-fastapp --fastapp-deploy-mode "microservices"
|
|
90
90
|
You can visit [our tutorials](https://github.com/state-alchemists/zrb/blob/main/docs/tutorials/README.md) to see more cool tricks.
|
91
91
|
|
92
92
|
|
93
|
-
## Zrb
|
93
|
+
## Zrb is A Task-Automation Tool
|
94
94
|
|
95
|
-
Aside from the
|
95
|
+
Aside from the built-in capabilities, Zrb also allows you to define your automation commands in Python. To do so, you must create/modify a file named `zrb_init.py`.
|
96
96
|
|
97
97
|
```python
|
98
98
|
# filename: zrb_init.py
|
@@ -133,7 +133,7 @@ To learn more about this, you can visit [our getting started guide](https://gith
|
|
133
133
|
|
134
134
|
# 🫰 Installation
|
135
135
|
|
136
|
-
## ⚙️ In
|
136
|
+
## ⚙️ In Local Machine
|
137
137
|
|
138
138
|
Installing Zrb in your system is as easy as typing the following command in your terminal:
|
139
139
|
|
@@ -141,11 +141,11 @@ Installing Zrb in your system is as easy as typing the following command in your
|
|
141
141
|
pip install zrb
|
142
142
|
```
|
143
143
|
|
144
|
-
|
144
|
+
Like any other Python package, you can install Zrb in your [virtual environment](https://docs.python.org/3/library/venv.html). This will allow you to have many versions of Zrb on the same computer.
|
145
145
|
|
146
146
|
> ⚠️ If the command doesn't work, you probably don't have Pip/Python on your computer. See `Main prerequisites` subsection to install them.
|
147
147
|
|
148
|
-
## 🐋 With
|
148
|
+
## 🐋 With Docker
|
149
149
|
|
150
150
|
If you prefer to work with Docker, you can create a file named `docker-compose.yml`
|
151
151
|
|
@@ -184,7 +184,7 @@ You will be able to access Zrb by using docker exec:
|
|
184
184
|
docker exec -it zrb zsh
|
185
185
|
```
|
186
186
|
|
187
|
-
# ✅ Main
|
187
|
+
# ✅ Main Prerequisites
|
188
188
|
|
189
189
|
Since Zrb is written in Python, you need to install a few things before installing Zrb:
|
190
190
|
|
@@ -209,11 +209,11 @@ ln -s venv/bin/python3 /usr/local/bin/python
|
|
209
209
|
|
210
210
|
If you prefer Python distribution like [conda](https://docs.conda.io/en/latest/), that might work as well.
|
211
211
|
|
212
|
-
# ✔️ Other
|
212
|
+
# ✔️ Other Prerequisites
|
213
213
|
|
214
214
|
If you want to generate applications using Zrb and run them on your computer, you will also need:
|
215
215
|
|
216
|
-
- 🐸 `Node.Js` and `Npm`.
|
216
|
+
- 🐸 `Node.Js` and `Npm`.
|
217
217
|
- You need Node.Js to modify/transpile frontend code into static files.
|
218
218
|
- You can visit the [Node.Js website](https://nodejs.org/en) for installation instructions.
|
219
219
|
- 🐋 `Docker` and `Docker-compose` plugin.
|
@@ -228,9 +228,9 @@ If you want to generate applications using Zrb and run them on your computer, yo
|
|
228
228
|
- 🦆 `Pulumi`
|
229
229
|
- You need Pulumi to deploy your applications
|
230
230
|
|
231
|
-
# 🏁 Getting
|
231
|
+
# 🏁 Getting Started
|
232
232
|
|
233
|
-
We have
|
233
|
+
We have an excellent [getting started guide](https://github.com/state-alchemists/zrb/blob/main/docs/getting-started.md) to help you cover the basics. Make sure to check it out😉.
|
234
234
|
|
235
235
|
# 📖 Documentation
|
236
236
|
|
@@ -240,11 +240,11 @@ You can visit [Zrb documentation](https://github.com/state-alchemists/zrb/blob/m
|
|
240
240
|
|
241
241
|
Help Red Skull to click the donation button:
|
242
242
|
|
243
|
-
[](https://stalchmst.com/donation)
|
244
244
|
|
245
|
-
# 🎉 Fun
|
245
|
+
# 🎉 Fun Fact
|
246
246
|
|
247
247
|
> Madou Ring Zaruba (魔導輪ザルバ, Madōrin Zaruba) is a Madougu which supports bearers of the Garo Armor. [(Garo Wiki | Fandom)](https://garo.fandom.com/wiki/Zaruba)
|
248
248
|
|
249
|
-

|
250
250
|
|
@@ -3,13 +3,13 @@ zrb/__main__.py,sha256=CdfuYSxqlJhnsJPOBOL2_uzEaTZHC3MtpyTuz8QUfUI,314
|
|
3
3
|
zrb/advertisement.py,sha256=e-1tFPlmEuz8IqaIJ_9-2p9x5cuGsxssJGu5F0wHthI,505
|
4
4
|
zrb/runner.py,sha256=MPCNPMCyiYNZeubSxd1eM2Zr6PCIKF-9pkG385AXElw,118
|
5
5
|
zrb/action/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
zrb/action/runner.py,sha256
|
6
|
+
zrb/action/runner.py,sha256=JPWERMBRS7FW9Z1m1P2pI0farvdmA6fwX9NyZGJr6Dg,4476
|
7
7
|
zrb/builtin/__init__.py,sha256=VpmpsDJmL2Qe1MDiVTaGgGgW9MxRz8sR21Blclg6MDE,580
|
8
8
|
zrb/builtin/base64.py,sha256=_Ff8eQi0pMa4qqDUqZqA-u-2LpSA5s3AN0Nj2M7ibnQ,1318
|
9
9
|
zrb/builtin/env.py,sha256=hEjQios0i-3DantczxQnZnolzwZAGIQOE0Ygka330EU,1146
|
10
10
|
zrb/builtin/eval.py,sha256=FjAeWuD6KdvSKwsoUo8qbSO9qgc0rQVmRNib-XKOfVc,745
|
11
11
|
zrb/builtin/explain.py,sha256=ee2UjBS-J5-Hf9JDEQR_vs056NiMZCCHtLvE_rrW4AU,5377
|
12
|
-
zrb/builtin/git.py,sha256=
|
12
|
+
zrb/builtin/git.py,sha256=VIhXv8LV12vysSJYitW26mU5p6x9bmTCYknAM4Qu1h0,2616
|
13
13
|
zrb/builtin/group.py,sha256=ncUsZcGRUF9QKNMt-_1zDNDi4Z2KA5jpjwEuYIzhKmo,1077
|
14
14
|
zrb/builtin/md5.py,sha256=IWN0uroXRiuyF0wD05BzGqAkMA3p6q9EbtWmJOPdOc0,1376
|
15
15
|
zrb/builtin/process.py,sha256=h7uMfEIqbOaNe8aTINZYYbHWw7mmUF8DkeiylPeWzSE,1281
|
@@ -1102,7 +1102,7 @@ zrb/helper/util.py,sha256=82LBcWV8vAnMnYYIfnKq27EfaY_ATxLNJpcePe7VwQI,3469
|
|
1102
1102
|
zrb/helper/accessories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1103
1103
|
zrb/helper/accessories/color.py,sha256=2G_Ys_iFF7hnnbeLqO3YRBGiYdxnduk0CMcyz4Y8dgg,709
|
1104
1104
|
zrb/helper/accessories/icon.py,sha256=hCL8tSvxxRy7PTKQXsvS4oTPyrP87Zn5RoBgsCq-NLs,347
|
1105
|
-
zrb/helper/accessories/name.py,sha256=
|
1105
|
+
zrb/helper/accessories/name.py,sha256=DoSTf6SjWOP0GEzWvIalcJeuft8C19v09vfJ1MotTuE,2043
|
1106
1106
|
zrb/helper/codemod/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1107
1107
|
zrb/helper/codemod/add_argument_to_function.py,sha256=5tuDqcMMozANchrHuUspH5MlRdQj5nw_mwhCzEXb0qY,1265
|
1108
1108
|
zrb/helper/codemod/add_argument_to_function_call.py,sha256=aqQxpmbFbtejJPdjG7v1QIwsaBUT0v_M9ZGhTSxIFKU,1041
|
@@ -1117,7 +1117,7 @@ zrb/helper/codemod/format_code.py,sha256=ymxZtZm-5RuaddLUu8LJgguX0n8CJSbHb-McQDU
|
|
1117
1117
|
zrb/helper/docker_compose/fetch_external_env.py,sha256=pIXkMCXtDXVWdNPlpMolqdj4Q0Y73dhCeqwByCB6mWg,2042
|
1118
1118
|
zrb/helper/docker_compose/file.py,sha256=aBtQMV57TWtMO9AwsZ2OyBn16MhElZaDlq54zBqYBnA,685
|
1119
1119
|
zrb/helper/env_map/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1120
|
-
zrb/helper/env_map/fetch.py,sha256=
|
1120
|
+
zrb/helper/env_map/fetch.py,sha256=Nl243-dcIEpbImAveZAXo2l0IGNXxD5RN_CyxGYTZeo,2173
|
1121
1121
|
zrb/helper/file/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1122
1122
|
zrb/helper/file/copy_tree.py,sha256=4kVqupzLYyF_neiRsedAFbxkeiK0VYsW45Z2zCkWLXA,1804
|
1123
1123
|
zrb/helper/file/text.py,sha256=_S1uYToMw3lcI95-op_kM_SWNJUyvYNc32XHIcokDWU,807
|
@@ -1137,18 +1137,18 @@ zrb/shell-scripts/_common-util.sh,sha256=6WPPOp_NBUgIMd1K2qlVZ6iYzZ-Xl3lUTzi4Rqr
|
|
1137
1137
|
zrb/shell-scripts/ensure-docker-is-installed.sh,sha256=CpfGjfoXFXoTWXsONIGZCMnmtFrk6ZamvO_8Fqp_WJ0,2893
|
1138
1138
|
zrb/shell-scripts/ensure-rsync-is-installed.sh,sha256=vHJWNEidemIrM2tQ17r5qwSUjz9hVKcjYbUEMo3pPJI,987
|
1139
1139
|
zrb/shell-scripts/ensure-ssh-is-installed.sh,sha256=TM0PLXT2vNfgv2ffcW_l-IqtMqHI1Z9nGdJvlToUlyM,2092
|
1140
|
-
zrb/shell-scripts/rsync-util.sh,sha256=
|
1140
|
+
zrb/shell-scripts/rsync-util.sh,sha256=QzdhSBvUNMxB4U2B4m0Dxg9czGckRjB7Vk4A1ObG0-k,353
|
1141
1141
|
zrb/shell-scripts/ssh-util.sh,sha256=9lXDzw6oO8HuA4vdbfps_uQMMwKyNYX9fZkZgpK52g8,401
|
1142
1142
|
zrb/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1143
|
-
zrb/task/any_task.py,sha256=
|
1143
|
+
zrb/task/any_task.py,sha256=fViLjv35ZAuQxBjArv52E6LJgv9vvgihCGEPuiEgv_4,6238
|
1144
1144
|
zrb/task/any_task_event_handler.py,sha256=vpO9t0fck8-oFu1KYptfcg2hXKRsk6V5je4Dg-Bl21o,359
|
1145
|
-
zrb/task/base_remote_cmd_task.py,sha256=
|
1146
|
-
zrb/task/base_task.py,sha256=
|
1147
|
-
zrb/task/base_task_composite.py,sha256=
|
1148
|
-
zrb/task/cmd_task.py,sha256=
|
1145
|
+
zrb/task/base_remote_cmd_task.py,sha256=M0915WLSjokKrfdLdPhEtXRPKTG1BfWMRTQLEzj6hL4,8930
|
1146
|
+
zrb/task/base_task.py,sha256=HxMUb1Iqe4lLOkoSwxCNmRCk2ZE5FoYXmtW8IDy9DkY,21068
|
1147
|
+
zrb/task/base_task_composite.py,sha256=mkw6lSYnDqtO5a9y6HGfCWwBcQOfCx-gX8l0-DurC4Q,18756
|
1148
|
+
zrb/task/cmd_task.py,sha256=g96LPvWNoYoqGuo4V7ZrzGk8_witf4J0eIKMInwIjvM,12758
|
1149
1149
|
zrb/task/decorator.py,sha256=6mJuDhmyHnVwx8SzBf8el5KwYJdA06VTeb1BABgLmTc,2399
|
1150
|
-
zrb/task/docker_compose_task.py,sha256=
|
1151
|
-
zrb/task/flow_task.py,sha256=
|
1150
|
+
zrb/task/docker_compose_task.py,sha256=aytg_c2_gDyhCIRxGmJONicz_Gw8QPVKWdFCV8rOngI,13152
|
1151
|
+
zrb/task/flow_task.py,sha256=lagR8S2tM3y7k5GFoo6qhr9rLJHGCjvVciwMMRxhpzg,3929
|
1152
1152
|
zrb/task/http_checker.py,sha256=ajsBDRgpp2OMeLlgyCL15UECYr2SoKAWfU3PGOJY24Q,5519
|
1153
1153
|
zrb/task/path_checker.py,sha256=EhPJHDPYGAJG3XPUaiN_iN9Y-vtf96gEsWwqagy4IIM,3879
|
1154
1154
|
zrb/task/port_checker.py,sha256=bZ7JPSNoZ1zyZsS05tL4y7soKRbjyU0u3LXsPOE5w7I,4398
|
@@ -1156,8 +1156,9 @@ zrb/task/remote_cmd_task.py,sha256=LYWmnZ4mPsU-RIdAUyhui7mlIunx4vY8upwjhctnkEs,3
|
|
1156
1156
|
zrb/task/resource_maker.py,sha256=QwB4S7aFjxX52onCqIu5OOMnm5omoZBl6OqZz9TqSOs,6379
|
1157
1157
|
zrb/task/rsync_task.py,sha256=3vxENH-unD1VLgZI09Ts_lAQRMi2i1UiJpsaI1dltzI,3966
|
1158
1158
|
zrb/task/task.py,sha256=aOwBVPl3U_dXCMcnrtcN0wPR8cDKbYkzgwa86BZMqBE,236
|
1159
|
-
zrb/task_env/
|
1160
|
-
zrb/task_env/
|
1159
|
+
zrb/task_env/constant.py,sha256=JdPhtZCTZlbW-jzG5vyFtpEXgTJ-Yx863LcrX_LiURY,44
|
1160
|
+
zrb/task_env/env.py,sha256=4oS4Y6_qwbzFqO08fzLb0TcSDAe9kxCW5cmbOFO1PSs,1954
|
1161
|
+
zrb/task_env/env_file.py,sha256=wQQmIQeK8-bRyl3KYe1xSFfebgHVFjXoXm8mQoVk7dY,1479
|
1161
1162
|
zrb/task_group/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1162
1163
|
zrb/task_group/group.py,sha256=qPZ79UZzLh5UPqsu2NflE6QAQzV568OPtXHcWloZX1o,1420
|
1163
1164
|
zrb/task_input/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -1165,14 +1166,14 @@ zrb/task_input/any_input.py,sha256=pLHMnH8VteIXS1ZBuBAVz8_WlAcikTUk1WyU_EEXxX4,5
|
|
1165
1166
|
zrb/task_input/base_input.py,sha256=98z4bQDvgKlhf8CFMtakbWjvFwn_Y4XKb4YdSB-OTwE,3144
|
1166
1167
|
zrb/task_input/bool_input.py,sha256=8-Kc4Rdc1dykMHxGUuAnRdnRcyEYfVM8ECtZqT071Fc,1594
|
1167
1168
|
zrb/task_input/choice_input.py,sha256=V7BvsI-cI1CCX1DrQQY9bvwEHBYfNvS1WW5QWreMF_0,1672
|
1168
|
-
zrb/task_input/constant.py,sha256=
|
1169
|
+
zrb/task_input/constant.py,sha256=QgG5alvaRVQYQ5yFNEwj_1DvSmebW0xEDU1JXktSlO4,59
|
1169
1170
|
zrb/task_input/float_input.py,sha256=flaZvFY55us8vtYuBxuAvvr4mTTAVZ-S8uTUt9AGfNg,1595
|
1170
1171
|
zrb/task_input/int_input.py,sha256=mtNrgs65SL0GCzW5qr6c869UjiJ__zJaiXmJZCaqIJs,1592
|
1171
1172
|
zrb/task_input/password_input.py,sha256=5bkUWyPumryigIy-S_z3nBDCo8sQB8_5PeS_gvPI0HQ,1611
|
1172
1173
|
zrb/task_input/str_input.py,sha256=7cubJJKLCWRoGIRIM0_0WUhya18wvURoytrhVZA4xYI,1592
|
1173
1174
|
zrb/task_input/task_input.py,sha256=HotqM1iYSzwE4PIj8grnEUsvJqjx1dS6Ek7i6ZJLq2Y,83
|
1174
|
-
zrb-0.0.
|
1175
|
-
zrb-0.0.
|
1176
|
-
zrb-0.0.
|
1177
|
-
zrb-0.0.
|
1178
|
-
zrb-0.0.
|
1175
|
+
zrb-0.0.110.dist-info/entry_points.txt,sha256=xTgXc1kBKYhJHEujdaSPHUcJT3-hbyP1mLgwkv-5sSk,40
|
1176
|
+
zrb-0.0.110.dist-info/LICENSE,sha256=WfnGCl8G60EYOPAEkuc8C9m9pdXWDe08NsKj3TBbxsM,728
|
1177
|
+
zrb-0.0.110.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
1178
|
+
zrb-0.0.110.dist-info/METADATA,sha256=YIIg3sAs_V0P_U2aFDdowyznVCsNB1CAdt04_erUeBA,9740
|
1179
|
+
zrb-0.0.110.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|