cmem-cmemc 23.2__py3-none-any.whl → 23.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cmem/cmemc/cli/__init__.py +9 -3
- cmem/cmemc/cli/_cmemc.zsh +44 -0
- cmem/cmemc/cli/commands/__init__.py +1 -0
- cmem/cmemc/cli/commands/admin.py +1 -1
- cmem/cmemc/cli/commands/client.py +2 -2
- cmem/cmemc/cli/commands/config.py +1 -1
- cmem/cmemc/cli/commands/dataset.py +104 -59
- cmem/cmemc/cli/commands/graph.py +10 -10
- cmem/cmemc/cli/commands/metrics.py +3 -3
- cmem/cmemc/cli/commands/project.py +50 -14
- cmem/cmemc/cli/commands/python.py +110 -29
- cmem/cmemc/cli/commands/query.py +6 -6
- cmem/cmemc/cli/commands/resource.py +5 -5
- cmem/cmemc/cli/commands/scheduler.py +4 -4
- cmem/cmemc/cli/commands/store.py +34 -31
- cmem/cmemc/cli/commands/user.py +6 -6
- cmem/cmemc/cli/commands/variable.py +364 -0
- cmem/cmemc/cli/commands/vocabulary.py +5 -5
- cmem/cmemc/cli/commands/workflow.py +73 -29
- cmem/cmemc/cli/commands/workspace.py +5 -5
- cmem/cmemc/cli/completion.py +269 -159
- cmem/cmemc/cli/context.py +20 -3
- cmem/cmemc/cli/manual_helper/multi_page.py +9 -6
- cmem/cmemc/cli/utils.py +80 -0
- {cmem_cmemc-23.2.dist-info → cmem_cmemc-23.3.0.dist-info}/METADATA +4 -4
- cmem_cmemc-23.3.0.dist-info/RECORD +35 -0
- {cmem_cmemc-23.2.dist-info → cmem_cmemc-23.3.0.dist-info}/WHEEL +1 -1
- cmem_cmemc-23.2.dist-info/RECORD +0 -33
- {cmem_cmemc-23.2.dist-info → cmem_cmemc-23.3.0.dist-info}/LICENSE +0 -0
- {cmem_cmemc-23.2.dist-info → cmem_cmemc-23.3.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
"""DataIntegration variable commands for cmemc."""
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
from click import UsageError
|
|
6
|
+
|
|
7
|
+
from cmem.cmemc.cli import completion
|
|
8
|
+
from cmem.cmemc.cli.commands import CmemcCommand, CmemcGroup
|
|
9
|
+
from cmem.cmemc.cli.utils import split_task_id, check_or_select_project
|
|
10
|
+
from cmem.cmempy.workspace.projects.variables import (
|
|
11
|
+
create_or_update_variable,
|
|
12
|
+
delete_variable,
|
|
13
|
+
get_all_variables,
|
|
14
|
+
get_variable
|
|
15
|
+
)
|
|
16
|
+
from cmem.cmemc.cli.context import ApplicationContext
|
|
17
|
+
|
|
18
|
+
VARIABLES_FILTER_TYPES = ["project", 'regex']
|
|
19
|
+
VARIABLES_FILTER_TYPES_HIDDEN = ["ids"]
|
|
20
|
+
VARIABLES_FILTER_TEXT = (
|
|
21
|
+
"Filter variables based on metadata. "
|
|
22
|
+
f"First parameter CHOICE can be one of {str(VARIABLES_FILTER_TYPES)}"
|
|
23
|
+
". The second parameter is based on CHOICE, e.g. a project "
|
|
24
|
+
"ID or a regular expression string."
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _get_variables_filtered(variables, filter_name, filter_value):
|
|
29
|
+
"""Get variables but filtered according to name and value."""
|
|
30
|
+
filter_types = VARIABLES_FILTER_TYPES + VARIABLES_FILTER_TYPES_HIDDEN
|
|
31
|
+
# check for correct filter names (filter ids is used internally only)
|
|
32
|
+
if filter_name not in filter_types:
|
|
33
|
+
raise ValueError(
|
|
34
|
+
f"{filter_name} is an unknown filter name. "
|
|
35
|
+
f"Use one of {VARIABLES_FILTER_TYPES}."
|
|
36
|
+
)
|
|
37
|
+
# filter by ID list
|
|
38
|
+
if filter_name == "ids":
|
|
39
|
+
return [_ for _ in variables if _["id"] in filter_value]
|
|
40
|
+
# filter by project
|
|
41
|
+
if filter_name == "project":
|
|
42
|
+
return [_ for _ in variables if _["project"] == filter_value]
|
|
43
|
+
# filter by regex
|
|
44
|
+
if filter_name == "regex":
|
|
45
|
+
return [
|
|
46
|
+
_ for _ in variables
|
|
47
|
+
if re.search(filter_value, _["id"])
|
|
48
|
+
or re.search(filter_value, _["value"])
|
|
49
|
+
or re.search(filter_value, _.get("description", ""))
|
|
50
|
+
or re.search(filter_value, _.get("template", ""))
|
|
51
|
+
]
|
|
52
|
+
# return unfiltered list
|
|
53
|
+
return variables
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@click.command(cls=CmemcCommand, name="list")
|
|
57
|
+
@click.option(
|
|
58
|
+
"--raw",
|
|
59
|
+
is_flag=True,
|
|
60
|
+
help="Outputs raw JSON."
|
|
61
|
+
)
|
|
62
|
+
@click.option(
|
|
63
|
+
"--id-only",
|
|
64
|
+
is_flag=True,
|
|
65
|
+
help="Lists only variables names and no other metadata. "
|
|
66
|
+
"This is useful for piping the IDs into other commands."
|
|
67
|
+
)
|
|
68
|
+
@click.option(
|
|
69
|
+
"--filter", "filters_",
|
|
70
|
+
multiple=True,
|
|
71
|
+
type=(str, str),
|
|
72
|
+
shell_complete=completion.variable_list_filter,
|
|
73
|
+
help=VARIABLES_FILTER_TEXT
|
|
74
|
+
)
|
|
75
|
+
@click.pass_obj
|
|
76
|
+
def list_command(app: ApplicationContext, raw, id_only, filters_):
|
|
77
|
+
"""List available project variables.
|
|
78
|
+
|
|
79
|
+
Outputs a table or a list of project variables.
|
|
80
|
+
"""
|
|
81
|
+
variables = get_all_variables()
|
|
82
|
+
|
|
83
|
+
for _ in filters_:
|
|
84
|
+
filter_name, filter_value = _
|
|
85
|
+
variables = _get_variables_filtered(
|
|
86
|
+
variables, filter_name, filter_value
|
|
87
|
+
)
|
|
88
|
+
if raw:
|
|
89
|
+
app.echo_info_json(variables)
|
|
90
|
+
return
|
|
91
|
+
if id_only:
|
|
92
|
+
for _ in sorted(_["id"] for _ in variables):
|
|
93
|
+
app.echo_result(_)
|
|
94
|
+
return
|
|
95
|
+
# output a user table
|
|
96
|
+
table = []
|
|
97
|
+
headers = ["ID", "Value", "Template", "Description"]
|
|
98
|
+
for _ in variables:
|
|
99
|
+
row = [
|
|
100
|
+
_["id"],
|
|
101
|
+
_["value"],
|
|
102
|
+
_.get("template", ""),
|
|
103
|
+
_.get("description", ""),
|
|
104
|
+
]
|
|
105
|
+
table.append(row)
|
|
106
|
+
app.echo_info_table(table, headers=headers, sort_column=0)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@click.command(cls=CmemcCommand, name="get")
|
|
110
|
+
@click.argument(
|
|
111
|
+
"variable_id",
|
|
112
|
+
required=True,
|
|
113
|
+
type=click.STRING,
|
|
114
|
+
shell_complete=completion.variable_ids
|
|
115
|
+
)
|
|
116
|
+
@click.option(
|
|
117
|
+
"--key",
|
|
118
|
+
type=click.Choice(
|
|
119
|
+
["value", "template", "description"],
|
|
120
|
+
case_sensitive=False
|
|
121
|
+
),
|
|
122
|
+
default="value",
|
|
123
|
+
show_default=True,
|
|
124
|
+
help="Specify the name of the value you want to get."
|
|
125
|
+
)
|
|
126
|
+
@click.option(
|
|
127
|
+
"--raw",
|
|
128
|
+
is_flag=True,
|
|
129
|
+
help="Outputs raw json."
|
|
130
|
+
)
|
|
131
|
+
@click.pass_obj
|
|
132
|
+
def get_command(app: ApplicationContext, variable_id, key, raw):
|
|
133
|
+
"""Get the value or other data of a project variable.
|
|
134
|
+
|
|
135
|
+
Use the `--key` option to specify which information you want to get.
|
|
136
|
+
|
|
137
|
+
Note: Only the `value` key is always available on a project variable.
|
|
138
|
+
Static value variables have no `template` key, and the `description` key
|
|
139
|
+
is optional for both types of variables.
|
|
140
|
+
"""
|
|
141
|
+
project_name, variable_name = split_task_id(variable_id)
|
|
142
|
+
_ = get_variable(variable_name=variable_name, project_name=project_name)
|
|
143
|
+
if raw:
|
|
144
|
+
app.echo_info_json(_)
|
|
145
|
+
return
|
|
146
|
+
try:
|
|
147
|
+
app.echo_info(_[key], nl=False)
|
|
148
|
+
except KeyError as error:
|
|
149
|
+
raise UsageError(
|
|
150
|
+
f"Variable {variable_name} has no value of '{key}'."
|
|
151
|
+
) from error
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@click.command(cls=CmemcCommand, name="delete")
|
|
155
|
+
@click.argument(
|
|
156
|
+
"variable_id",
|
|
157
|
+
required=True,
|
|
158
|
+
type=click.STRING,
|
|
159
|
+
shell_complete=completion.variable_ids
|
|
160
|
+
)
|
|
161
|
+
@click.pass_obj
|
|
162
|
+
def delete_command(app: ApplicationContext, variable_id):
|
|
163
|
+
"""Delete a project variable.
|
|
164
|
+
|
|
165
|
+
Note: You can not delete a variable which is used by another
|
|
166
|
+
(template based) variable. In order to do so, delete the template based
|
|
167
|
+
variable first.
|
|
168
|
+
"""
|
|
169
|
+
project_name, variable_name = split_task_id(variable_id)
|
|
170
|
+
app.echo_info(
|
|
171
|
+
f"Delete variable {variable_name} from project {project_name} ... ",
|
|
172
|
+
nl=False
|
|
173
|
+
)
|
|
174
|
+
delete_variable(variable_name=variable_name, project_name=project_name)
|
|
175
|
+
app.echo_success("done")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# pylint: disable=too-many-arguments
|
|
179
|
+
@click.command(cls=CmemcCommand, name="create")
|
|
180
|
+
@click.argument(
|
|
181
|
+
"variable_name",
|
|
182
|
+
required=True,
|
|
183
|
+
type=click.STRING,
|
|
184
|
+
)
|
|
185
|
+
@click.option(
|
|
186
|
+
"--value",
|
|
187
|
+
type=click.STRING,
|
|
188
|
+
help="The value of the new project variable."
|
|
189
|
+
)
|
|
190
|
+
@click.option(
|
|
191
|
+
"--template",
|
|
192
|
+
type=click.STRING,
|
|
193
|
+
help="The template of the new project variable. You can use Jinja template "
|
|
194
|
+
"syntax, e.g. use '{{global.myVar}}' for accessing global variables, or "
|
|
195
|
+
"'{{project.myVar}}' for accessing variables from the same project."
|
|
196
|
+
)
|
|
197
|
+
@click.option(
|
|
198
|
+
"--description",
|
|
199
|
+
type=click.STRING,
|
|
200
|
+
help="The optional description of the new project variable."
|
|
201
|
+
)
|
|
202
|
+
@click.option(
|
|
203
|
+
"--project", "project_id",
|
|
204
|
+
type=click.STRING,
|
|
205
|
+
shell_complete=completion.project_ids,
|
|
206
|
+
help="The project, where you want to create the variable in. If there is "
|
|
207
|
+
"only one project in the workspace, this option can be omitted."
|
|
208
|
+
)
|
|
209
|
+
@click.pass_obj
|
|
210
|
+
def create_command(
|
|
211
|
+
app: ApplicationContext,
|
|
212
|
+
variable_name, value, template, description,
|
|
213
|
+
project_id
|
|
214
|
+
):
|
|
215
|
+
"""Create a new project variable.
|
|
216
|
+
|
|
217
|
+
Variables need to be created with a value or a template (not both).
|
|
218
|
+
In addition to that, a project ID and a name are mandatory.
|
|
219
|
+
|
|
220
|
+
Example: cmemc project variable create my_var --project my_project --value abc
|
|
221
|
+
|
|
222
|
+
Note: cmemc is currently not able to manage the order of the variables in a
|
|
223
|
+
project. This means you have to create plain value variables in advance,
|
|
224
|
+
before you can create template based variables, which access these values.
|
|
225
|
+
"""
|
|
226
|
+
if value and template:
|
|
227
|
+
raise UsageError(
|
|
228
|
+
"Either use '--value' or '--template' but not both."
|
|
229
|
+
)
|
|
230
|
+
if not value and not template:
|
|
231
|
+
raise UsageError(
|
|
232
|
+
"Use '--value' or '--template' to create a new variable."
|
|
233
|
+
)
|
|
234
|
+
project_id = check_or_select_project(app, project_id)
|
|
235
|
+
data = get_variable(project_name=project_id, variable_name=variable_name)
|
|
236
|
+
if data:
|
|
237
|
+
raise UsageError(
|
|
238
|
+
f"Variable '{variable_name}' already exist in project '{project_id}'."
|
|
239
|
+
)
|
|
240
|
+
data = {
|
|
241
|
+
"name": variable_name,
|
|
242
|
+
"isSensitive": False,
|
|
243
|
+
"scope": "project"
|
|
244
|
+
}
|
|
245
|
+
if value:
|
|
246
|
+
data["value"] = value
|
|
247
|
+
if template:
|
|
248
|
+
data["template"] = template
|
|
249
|
+
if description:
|
|
250
|
+
data["description"] = description
|
|
251
|
+
app.echo_info(
|
|
252
|
+
f"Create variable {variable_name} in project {project_id} ... ",
|
|
253
|
+
nl=False
|
|
254
|
+
)
|
|
255
|
+
create_or_update_variable(
|
|
256
|
+
project_name=project_id,
|
|
257
|
+
variable_name=variable_name,
|
|
258
|
+
data=data
|
|
259
|
+
)
|
|
260
|
+
app.echo_success("done")
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@click.command(cls=CmemcCommand, name="update")
|
|
264
|
+
@click.argument(
|
|
265
|
+
"variable_id",
|
|
266
|
+
required=True,
|
|
267
|
+
type=click.STRING,
|
|
268
|
+
shell_complete=completion.variable_ids
|
|
269
|
+
)
|
|
270
|
+
@click.option(
|
|
271
|
+
"--value",
|
|
272
|
+
type=click.STRING,
|
|
273
|
+
help="The new value of the project variable."
|
|
274
|
+
)
|
|
275
|
+
@click.option(
|
|
276
|
+
"--template",
|
|
277
|
+
type=click.STRING,
|
|
278
|
+
help="The new template of the project variable. You can use Jinja template "
|
|
279
|
+
"syntax, e.g. use '{{global.myVar}}' for accessing global variables, or "
|
|
280
|
+
"'{{project.myVar}}' for accessing variables from the same project."
|
|
281
|
+
)
|
|
282
|
+
@click.option(
|
|
283
|
+
"--description",
|
|
284
|
+
type=click.STRING,
|
|
285
|
+
help="The new description of the project variable."
|
|
286
|
+
)
|
|
287
|
+
@click.pass_obj
|
|
288
|
+
def update_command(
|
|
289
|
+
app: ApplicationContext,
|
|
290
|
+
variable_id, value, template, description,
|
|
291
|
+
):
|
|
292
|
+
"""Update data of an existing project variable.
|
|
293
|
+
|
|
294
|
+
With this command you can update the value or the template, as well as the
|
|
295
|
+
description of a project variable.
|
|
296
|
+
|
|
297
|
+
Note: If you update the template of a static variable, it will be transformed
|
|
298
|
+
to a template based variable. If you want to change the value of a template
|
|
299
|
+
based variable, an error will be shown.
|
|
300
|
+
"""
|
|
301
|
+
project_id, variable_name = split_task_id(variable_id)
|
|
302
|
+
data = get_variable(project_name=project_id, variable_name=variable_name)
|
|
303
|
+
if not data:
|
|
304
|
+
raise UsageError(
|
|
305
|
+
f"Variable '{variable_name}' does not exist in project '{project_id}'."
|
|
306
|
+
)
|
|
307
|
+
if value and template:
|
|
308
|
+
raise UsageError(
|
|
309
|
+
"Project variables are based on a static value or on a template, but not "
|
|
310
|
+
"both."
|
|
311
|
+
)
|
|
312
|
+
if not value and not template and not description:
|
|
313
|
+
raise UsageError(
|
|
314
|
+
"Please specify what you want to update. "
|
|
315
|
+
"Use at least one of the following options: "
|
|
316
|
+
"'--value', '--template', '--description'."
|
|
317
|
+
)
|
|
318
|
+
if value:
|
|
319
|
+
if data.get("template", None):
|
|
320
|
+
raise UsageError(
|
|
321
|
+
"You can not change the value of a template based variable."
|
|
322
|
+
)
|
|
323
|
+
data["value"] = value
|
|
324
|
+
if template:
|
|
325
|
+
if not data.get("template", None):
|
|
326
|
+
app.echo_warning(f"Variable '{variable_id}' will be converted from a "
|
|
327
|
+
f"simple to a template based variable.")
|
|
328
|
+
data["template"] = template
|
|
329
|
+
if description:
|
|
330
|
+
data["description"] = description
|
|
331
|
+
app.echo_info(
|
|
332
|
+
f"Update variable {variable_name} in project {project_id} ... ",
|
|
333
|
+
nl=False
|
|
334
|
+
)
|
|
335
|
+
create_or_update_variable(
|
|
336
|
+
project_name=project_id,
|
|
337
|
+
variable_name=variable_name,
|
|
338
|
+
data=data
|
|
339
|
+
)
|
|
340
|
+
app.echo_success("done")
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
@click.group(cls=CmemcGroup)
|
|
344
|
+
def variable():
|
|
345
|
+
"""List, create, delete or get data from project variables.
|
|
346
|
+
|
|
347
|
+
Project variables can be used in dataset and task parameters, and in the template
|
|
348
|
+
transform operator.
|
|
349
|
+
Variables are either based on a static value or based on a template.
|
|
350
|
+
They may use templates that access globally configured
|
|
351
|
+
variables or other preceding variables from the same project.
|
|
352
|
+
|
|
353
|
+
Variables are identified by a VARIABLE_ID. To get a list of existing
|
|
354
|
+
variables, execute the list command or use tab-completion.
|
|
355
|
+
The VARIABLE_ID is a concatenation of a PROJECT_ID and a VARIABLE_NAME,
|
|
356
|
+
such as `my-project:my-variable`.
|
|
357
|
+
"""
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
variable.add_command(list_command)
|
|
361
|
+
variable.add_command(get_command)
|
|
362
|
+
variable.add_command(delete_command)
|
|
363
|
+
variable.add_command(create_command)
|
|
364
|
+
variable.add_command(update_command)
|
|
@@ -202,7 +202,7 @@ def _transform_cache_to_table(cache_category, table):
|
|
|
202
202
|
@click.argument(
|
|
203
203
|
"iri",
|
|
204
204
|
type=click.STRING,
|
|
205
|
-
|
|
205
|
+
shell_complete=completion.installed_vocabularies
|
|
206
206
|
)
|
|
207
207
|
@click.pass_obj
|
|
208
208
|
def open_command(app, iri):
|
|
@@ -276,7 +276,7 @@ def list_command(app, id_only, filter_, raw):
|
|
|
276
276
|
"iris",
|
|
277
277
|
nargs=-1,
|
|
278
278
|
type=click.STRING,
|
|
279
|
-
|
|
279
|
+
shell_complete=completion.installable_vocabularies
|
|
280
280
|
)
|
|
281
281
|
@click.option(
|
|
282
282
|
"-a", "--all", "all_",
|
|
@@ -316,7 +316,7 @@ def install_command(app: ApplicationContext, iris: tuple[str, ...], all_):
|
|
|
316
316
|
"iris",
|
|
317
317
|
nargs=-1,
|
|
318
318
|
type=click.STRING,
|
|
319
|
-
|
|
319
|
+
shell_complete=completion.installed_vocabularies
|
|
320
320
|
)
|
|
321
321
|
@click.option(
|
|
322
322
|
"-a", "--all", "all_",
|
|
@@ -355,7 +355,7 @@ def uninstall_command(app: ApplicationContext, iris: tuple[str, ...], all_):
|
|
|
355
355
|
@click.argument(
|
|
356
356
|
"FILE",
|
|
357
357
|
required=True,
|
|
358
|
-
|
|
358
|
+
shell_complete=completion.triple_files,
|
|
359
359
|
type=click.Path(
|
|
360
360
|
allow_dash=False,
|
|
361
361
|
readable=True
|
|
@@ -437,7 +437,7 @@ def import_command(app: ApplicationContext, file, namespace, replace):
|
|
|
437
437
|
"iris",
|
|
438
438
|
nargs=-1,
|
|
439
439
|
type=click.STRING,
|
|
440
|
-
|
|
440
|
+
shell_complete=completion.installed_vocabularies
|
|
441
441
|
)
|
|
442
442
|
@click.option(
|
|
443
443
|
"-a", "--all", "all_",
|
|
@@ -8,6 +8,7 @@ import time
|
|
|
8
8
|
import click
|
|
9
9
|
|
|
10
10
|
import timeago
|
|
11
|
+
from click import UsageError
|
|
11
12
|
|
|
12
13
|
from cmem.cmemc.cli import completion
|
|
13
14
|
from cmem.cmemc.cli.commands import CmemcCommand, CmemcGroup
|
|
@@ -31,6 +32,7 @@ from cmem.cmempy.workspace.activities.taskactivity import (
|
|
|
31
32
|
)
|
|
32
33
|
from cmem.cmempy.workspace.projects.project import get_projects
|
|
33
34
|
from cmem.cmempy.workspace.search import list_items
|
|
35
|
+
from cmem.cmemc.cli.context import ApplicationContext
|
|
34
36
|
|
|
35
37
|
WORKFLOW_FILTER_TYPES = sorted(['project', 'regex', 'tag', 'io'])
|
|
36
38
|
WORKFLOW_LIST_FILTER_HELP_TEXT = (
|
|
@@ -276,19 +278,54 @@ def _workflows_get_ids():
|
|
|
276
278
|
return ids
|
|
277
279
|
|
|
278
280
|
|
|
279
|
-
def
|
|
280
|
-
"""
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
"""
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
281
|
+
def _get_progress_bar_info(status):
|
|
282
|
+
"""get the workflow message from status response with colors."""
|
|
283
|
+
if status is None:
|
|
284
|
+
return ""
|
|
285
|
+
if status["isRunning"]:
|
|
286
|
+
return click.style(status["message"], fg="yellow")
|
|
287
|
+
if status["concreteStatus"] == "Failed":
|
|
288
|
+
return click.style(status["message"], fg="red")
|
|
289
|
+
return click.style(status["message"], fg="green")
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def _workflow_wait_until_finished(
|
|
293
|
+
app: ApplicationContext,
|
|
294
|
+
project_id: str,
|
|
295
|
+
task_id: str,
|
|
296
|
+
polling_interval: int,
|
|
297
|
+
log_progress: bool
|
|
298
|
+
):
|
|
299
|
+
"""Poll workflow status until workflow is finished and return status."""
|
|
300
|
+
progress = 0
|
|
301
|
+
if log_progress:
|
|
302
|
+
app.echo_success(message="", nl=True)
|
|
303
|
+
with click.progressbar(
|
|
304
|
+
show_eta=False,
|
|
305
|
+
length=100,
|
|
306
|
+
item_show_func=_get_progress_bar_info,
|
|
307
|
+
) as progress_bar:
|
|
308
|
+
while True:
|
|
309
|
+
status = get_activity_status(project_id, task_id)
|
|
310
|
+
if progress is not status['progress']:
|
|
311
|
+
progress_bar.update(
|
|
312
|
+
n_steps=status['progress'] - progress,
|
|
313
|
+
current_item=status
|
|
314
|
+
)
|
|
315
|
+
progress = status['progress']
|
|
316
|
+
app.echo_debug(f"{status['statusName']}({status['message']})")
|
|
317
|
+
# wait until isRunning is false
|
|
318
|
+
if not status['isRunning']:
|
|
319
|
+
break
|
|
320
|
+
time.sleep(polling_interval)
|
|
321
|
+
else:
|
|
322
|
+
while True:
|
|
323
|
+
status = get_activity_status(project_id, task_id)
|
|
324
|
+
app.echo_debug(f"{status['statusName']}({status['message']})")
|
|
325
|
+
# wait until isRunning is false
|
|
326
|
+
if not status['isRunning']:
|
|
327
|
+
break
|
|
328
|
+
time.sleep(polling_interval)
|
|
292
329
|
return status
|
|
293
330
|
|
|
294
331
|
|
|
@@ -336,6 +373,7 @@ def _workflow_echo_status(app, status):
|
|
|
336
373
|
app.echo_success(message)
|
|
337
374
|
|
|
338
375
|
|
|
376
|
+
# pylint: disable=too-many-arguments
|
|
339
377
|
@click.command(cls=CmemcCommand, name="execute")
|
|
340
378
|
@click.option(
|
|
341
379
|
"-a", "--all", "all_",
|
|
@@ -345,7 +383,12 @@ def _workflow_echo_status(app, status):
|
|
|
345
383
|
@click.option(
|
|
346
384
|
"--wait",
|
|
347
385
|
is_flag=True,
|
|
348
|
-
help="Wait until
|
|
386
|
+
help="Wait until workflows are completed."
|
|
387
|
+
)
|
|
388
|
+
@click.option(
|
|
389
|
+
"--progress",
|
|
390
|
+
is_flag=True,
|
|
391
|
+
help="Wait until workflows are completed and show a progress bar."
|
|
349
392
|
)
|
|
350
393
|
@click.option(
|
|
351
394
|
"--polling-interval",
|
|
@@ -359,10 +402,10 @@ def _workflow_echo_status(app, status):
|
|
|
359
402
|
"workflow_ids",
|
|
360
403
|
nargs=-1,
|
|
361
404
|
type=click.STRING,
|
|
362
|
-
|
|
405
|
+
shell_complete=completion.workflow_ids
|
|
363
406
|
)
|
|
364
407
|
@click.pass_obj
|
|
365
|
-
def execute_command(app, all_, wait, polling_interval, workflow_ids):
|
|
408
|
+
def execute_command(app, all_, wait, polling_interval, workflow_ids, progress):
|
|
366
409
|
"""Execute workflow(s).
|
|
367
410
|
|
|
368
411
|
With this command, you can start one or more workflows at the same time or
|
|
@@ -377,16 +420,16 @@ def execute_command(app, all_, wait, polling_interval, workflow_ids):
|
|
|
377
420
|
polls the status of a workflow until it is finished. In case of an error of
|
|
378
421
|
a workflow, the next workflow is not started.
|
|
379
422
|
"""
|
|
380
|
-
all_workflow_ids = _workflows_get_ids()
|
|
381
423
|
if workflow_ids == () and not all_:
|
|
382
424
|
raise ValueError("Either specify at least one workflow or use the"
|
|
383
425
|
+ " --all option to execute all workflows.")
|
|
426
|
+
all_workflow_ids = _workflows_get_ids()
|
|
384
427
|
if all_:
|
|
385
428
|
workflow_ids = all_workflow_ids
|
|
386
429
|
|
|
387
430
|
for workflow_id in workflow_ids:
|
|
388
431
|
if workflow_id not in all_workflow_ids:
|
|
389
|
-
raise
|
|
432
|
+
raise UsageError(
|
|
390
433
|
f"Workflow '{workflow_id}' is not available."
|
|
391
434
|
)
|
|
392
435
|
project_id, task_id = workflow_id.split(":")
|
|
@@ -394,7 +437,7 @@ def execute_command(app, all_, wait, polling_interval, workflow_ids):
|
|
|
394
437
|
|
|
395
438
|
# before we start, we fetch the status
|
|
396
439
|
status = get_activity_status(project_id, task_id)
|
|
397
|
-
if not wait:
|
|
440
|
+
if not wait and not progress:
|
|
398
441
|
if status['isRunning']:
|
|
399
442
|
# in case of a running workflow, we only output status
|
|
400
443
|
app.echo_info('Already Running')
|
|
@@ -403,7 +446,7 @@ def execute_command(app, all_, wait, polling_interval, workflow_ids):
|
|
|
403
446
|
start_task_activity(project_id, task_id)
|
|
404
447
|
app.echo_info('Started')
|
|
405
448
|
else:
|
|
406
|
-
# in case of --wait, we poll the status until finished
|
|
449
|
+
# in case of --wait or --progress, we poll the status until finished
|
|
407
450
|
if status['isRunning']:
|
|
408
451
|
# in case of a running workflow, we only output status
|
|
409
452
|
app.echo_info('Already Running ... ', nl=False)
|
|
@@ -412,10 +455,11 @@ def execute_command(app, all_, wait, polling_interval, workflow_ids):
|
|
|
412
455
|
app.echo_info('Started ... ', nl=False)
|
|
413
456
|
|
|
414
457
|
status = _workflow_wait_until_finished(
|
|
415
|
-
project_id, task_id, polling_interval
|
|
458
|
+
app, project_id, task_id, polling_interval, progress
|
|
416
459
|
)
|
|
417
460
|
# when we have a Finished status, we output it
|
|
418
|
-
|
|
461
|
+
if not progress:
|
|
462
|
+
_workflow_echo_status(app, status)
|
|
419
463
|
# in case of failure, the following workflows are not executed
|
|
420
464
|
if status['failed']:
|
|
421
465
|
sys.exit(1)
|
|
@@ -430,7 +474,7 @@ def execute_command(app, all_, wait, polling_interval, workflow_ids):
|
|
|
430
474
|
dir_okay=False,
|
|
431
475
|
readable=True
|
|
432
476
|
),
|
|
433
|
-
|
|
477
|
+
shell_complete=completion.workflow_io_input_files,
|
|
434
478
|
help="From which file the input is taken. If the workflow "
|
|
435
479
|
"has no defined variable input dataset, this option is not allowed."
|
|
436
480
|
)
|
|
@@ -441,7 +485,7 @@ def execute_command(app, all_, wait, polling_interval, workflow_ids):
|
|
|
441
485
|
dir_okay=False,
|
|
442
486
|
writable=True,
|
|
443
487
|
),
|
|
444
|
-
|
|
488
|
+
shell_complete=completion.workflow_io_output_files,
|
|
445
489
|
help="To which file the result is written to. Use '-' in order to output "
|
|
446
490
|
"the result to stdout. If the workflow has no defined variable "
|
|
447
491
|
"output dataset, this option is not allowed. Please note that the io "
|
|
@@ -475,7 +519,7 @@ def execute_command(app, all_, wait, polling_interval, workflow_ids):
|
|
|
475
519
|
@click.argument(
|
|
476
520
|
"workflow_id",
|
|
477
521
|
type=click.STRING,
|
|
478
|
-
|
|
522
|
+
shell_complete=completion.workflow_io_ids
|
|
479
523
|
)
|
|
480
524
|
@click.pass_obj
|
|
481
525
|
def io_command(
|
|
@@ -548,7 +592,7 @@ def io_command(
|
|
|
548
592
|
"--filter", "filter_",
|
|
549
593
|
type=(str, str),
|
|
550
594
|
multiple=True,
|
|
551
|
-
|
|
595
|
+
shell_complete=completion.workflow_list_filter,
|
|
552
596
|
help=WORKFLOW_LIST_FILTER_HELP_TEXT,
|
|
553
597
|
)
|
|
554
598
|
@click.option(
|
|
@@ -601,7 +645,7 @@ def list_command(app, filter_, raw, id_only):
|
|
|
601
645
|
@click.option(
|
|
602
646
|
"--project", "project_id",
|
|
603
647
|
type=click.STRING,
|
|
604
|
-
|
|
648
|
+
shell_complete=completion.project_ids,
|
|
605
649
|
help="The project, from which you want to list the workflows. "
|
|
606
650
|
"Project IDs can be listed with the 'project list' command."
|
|
607
651
|
)
|
|
@@ -619,7 +663,7 @@ def list_command(app, filter_, raw, id_only):
|
|
|
619
663
|
"workflow_ids",
|
|
620
664
|
nargs=-1,
|
|
621
665
|
type=click.STRING,
|
|
622
|
-
|
|
666
|
+
shell_complete=completion.workflow_ids
|
|
623
667
|
)
|
|
624
668
|
@click.pass_obj
|
|
625
669
|
def status_command(app, project_id, raw, _filter, workflow_ids):
|
|
@@ -644,7 +688,7 @@ def status_command(app, project_id, raw, _filter, workflow_ids):
|
|
|
644
688
|
@click.argument(
|
|
645
689
|
"workflow_id",
|
|
646
690
|
type=click.STRING,
|
|
647
|
-
|
|
691
|
+
shell_complete=completion.workflow_ids
|
|
648
692
|
)
|
|
649
693
|
@click.pass_obj
|
|
650
694
|
def open_command(app, workflow_id):
|
|
@@ -26,7 +26,7 @@ from cmem.cmempy.workspace.import_ import import_workspace
|
|
|
26
26
|
default="xmlZip",
|
|
27
27
|
show_default=True,
|
|
28
28
|
type=click.STRING,
|
|
29
|
-
|
|
29
|
+
shell_complete=completion.marshalling_plugins,
|
|
30
30
|
help="Type of the exported workspace file."
|
|
31
31
|
)
|
|
32
32
|
@click.option(
|
|
@@ -34,7 +34,7 @@ from cmem.cmempy.workspace.import_ import import_workspace
|
|
|
34
34
|
default="{{date}}-{{connection}}.workspace",
|
|
35
35
|
show_default=True,
|
|
36
36
|
type=click.STRING,
|
|
37
|
-
|
|
37
|
+
shell_complete=completion.workspace_export_templates,
|
|
38
38
|
help="Template for the export file name. "
|
|
39
39
|
"Possible placeholders are (Jinja2): "
|
|
40
40
|
"{{connection}} (from the --connection option) and "
|
|
@@ -44,7 +44,7 @@ from cmem.cmempy.workspace.import_ import import_workspace
|
|
|
44
44
|
)
|
|
45
45
|
@click.argument(
|
|
46
46
|
"file",
|
|
47
|
-
|
|
47
|
+
shell_complete=completion.workspace_files,
|
|
48
48
|
required=False,
|
|
49
49
|
type=click.Path(
|
|
50
50
|
writable=True,
|
|
@@ -95,12 +95,12 @@ def export_command(app, overwrite, marshalling_plugin, template, file):
|
|
|
95
95
|
default="xmlZip",
|
|
96
96
|
show_default=True,
|
|
97
97
|
type=click.STRING,
|
|
98
|
-
|
|
98
|
+
shell_complete=completion.marshalling_plugins,
|
|
99
99
|
help="Type of the exported workspace file."
|
|
100
100
|
)
|
|
101
101
|
@click.argument(
|
|
102
102
|
"file",
|
|
103
|
-
|
|
103
|
+
shell_complete=completion.workspace_files,
|
|
104
104
|
type=click.Path(
|
|
105
105
|
readable=True,
|
|
106
106
|
allow_dash=False,
|