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.
@@ -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
- autocompletion=completion.installed_vocabularies
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
- autocompletion=completion.installable_vocabularies
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
- autocompletion=completion.installed_vocabularies
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
- autocompletion=completion.triple_files,
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
- autocompletion=completion.installed_vocabularies
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 _workflow_wait_until_finished(project_id, task_id, polling_interval):
280
- """Poll workflow status until workflow is finished and return status.
281
-
282
- :type project_id: string
283
- :type task_id: string
284
- :type polling_interval: int
285
- """
286
- while True:
287
- status = get_activity_status(project_id, task_id)
288
- # wait until isRunning is false
289
- if not status['isRunning']:
290
- break
291
- time.sleep(polling_interval)
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 all executed workflows are completed."
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
- autocompletion=completion.workflow_ids
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 ValueError(
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
- _workflow_echo_status(app, status)
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
- autocompletion=completion.workflow_io_input_files,
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
- autocompletion=completion.workflow_io_output_files,
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
- autocompletion=completion.workflow_io_ids
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
- autocompletion=completion.workflow_list_filter,
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
- autocompletion=completion.project_ids,
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
- autocompletion=completion.workflow_ids
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
- autocompletion=completion.workflow_ids
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
- autocompletion=completion.marshalling_plugins,
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
- autocompletion=completion.workspace_export_templates,
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
- autocompletion=completion.workspace_files,
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
- autocompletion=completion.marshalling_plugins,
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
- autocompletion=completion.workspace_files,
103
+ shell_complete=completion.workspace_files,
104
104
  type=click.Path(
105
105
  readable=True,
106
106
  allow_dash=False,