cmem-cmemc 25.5.0rc1__py3-none-any.whl → 26.1.0rc1__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.
Files changed (42) hide show
  1. cmem_cmemc/cli.py +11 -6
  2. cmem_cmemc/command.py +1 -1
  3. cmem_cmemc/command_group.py +59 -31
  4. cmem_cmemc/commands/acl.py +403 -26
  5. cmem_cmemc/commands/admin.py +10 -10
  6. cmem_cmemc/commands/client.py +12 -5
  7. cmem_cmemc/commands/config.py +106 -12
  8. cmem_cmemc/commands/dataset.py +163 -172
  9. cmem_cmemc/commands/file.py +509 -0
  10. cmem_cmemc/commands/graph.py +200 -72
  11. cmem_cmemc/commands/graph_imports.py +12 -5
  12. cmem_cmemc/commands/graph_insights.py +157 -53
  13. cmem_cmemc/commands/metrics.py +15 -9
  14. cmem_cmemc/commands/migration.py +12 -4
  15. cmem_cmemc/commands/package.py +548 -0
  16. cmem_cmemc/commands/project.py +157 -22
  17. cmem_cmemc/commands/python.py +9 -5
  18. cmem_cmemc/commands/query.py +119 -25
  19. cmem_cmemc/commands/scheduler.py +6 -4
  20. cmem_cmemc/commands/store.py +2 -1
  21. cmem_cmemc/commands/user.py +124 -24
  22. cmem_cmemc/commands/validation.py +15 -10
  23. cmem_cmemc/commands/variable.py +264 -61
  24. cmem_cmemc/commands/vocabulary.py +31 -17
  25. cmem_cmemc/commands/workflow.py +21 -11
  26. cmem_cmemc/completion.py +126 -109
  27. cmem_cmemc/context.py +40 -10
  28. cmem_cmemc/exceptions.py +8 -2
  29. cmem_cmemc/manual_helper/graph.py +2 -2
  30. cmem_cmemc/manual_helper/multi_page.py +5 -7
  31. cmem_cmemc/object_list.py +234 -7
  32. cmem_cmemc/placeholder.py +2 -2
  33. cmem_cmemc/string_processor.py +153 -4
  34. cmem_cmemc/title_helper.py +50 -0
  35. cmem_cmemc/utils.py +9 -8
  36. {cmem_cmemc-25.5.0rc1.dist-info → cmem_cmemc-26.1.0rc1.dist-info}/METADATA +7 -6
  37. cmem_cmemc-26.1.0rc1.dist-info/RECORD +62 -0
  38. {cmem_cmemc-25.5.0rc1.dist-info → cmem_cmemc-26.1.0rc1.dist-info}/WHEEL +1 -1
  39. cmem_cmemc/commands/resource.py +0 -220
  40. cmem_cmemc-25.5.0rc1.dist-info/RECORD +0 -61
  41. {cmem_cmemc-25.5.0rc1.dist-info → cmem_cmemc-26.1.0rc1.dist-info}/entry_points.txt +0 -0
  42. {cmem_cmemc-25.5.0rc1.dist-info → cmem_cmemc-26.1.0rc1.dist-info}/licenses/LICENSE +0 -0
cmem_cmemc/completion.py CHANGED
@@ -4,11 +4,13 @@
4
4
  import os
5
5
  import pathlib
6
6
  from collections import OrderedDict
7
+ from collections.abc import Callable
7
8
  from contextlib import suppress
9
+ from functools import wraps
8
10
  from typing import Any
9
11
 
10
12
  import requests.exceptions
11
- from click import Argument, ClickException, Context
13
+ from click import Argument, Context
12
14
  from click.shell_completion import CompletionItem, split_arg_string
13
15
  from cmem.cmempy.dp.authorization.conditions import (
14
16
  fetch_all_acls,
@@ -31,7 +33,7 @@ from cmem.cmempy.workspace import (
31
33
  )
32
34
  from cmem.cmempy.workspace.projects.datasets.dataset import get_dataset
33
35
  from cmem.cmempy.workspace.projects.project import get_projects
34
- from cmem.cmempy.workspace.projects.resources import get_all_resources
36
+ from cmem.cmempy.workspace.projects.resources import get_all_resources, get_resources
35
37
  from cmem.cmempy.workspace.projects.variables import get_all_variables
36
38
  from cmem.cmempy.workspace.python import list_packages
37
39
  from cmem.cmempy.workspace.search import list_items
@@ -39,6 +41,7 @@ from natsort import natsorted, ns
39
41
 
40
42
  from cmem_cmemc.constants import NS_ACL, NS_ACTION, NS_GROUP, NS_USER
41
43
  from cmem_cmemc.context import ApplicationContext
44
+ from cmem_cmemc.exceptions import CmemcError
42
45
  from cmem_cmemc.placeholder import QueryPlaceholder, get_placeholders_for_query
43
46
  from cmem_cmemc.smart_path import SmartPath as Path
44
47
  from cmem_cmemc.utils import (
@@ -53,6 +56,43 @@ SORT_BY_KEY = 0
53
56
  SORT_BY_DESC = 1
54
57
 
55
58
 
59
+ def suppress_completion_errors(
60
+ func: Callable[..., list[CompletionItem]],
61
+ ) -> Callable[..., list[CompletionItem]]:
62
+ """Safely handle errors in shell completion functions.
63
+
64
+ When shell completion encounters connection errors (server down, network issues, etc.),
65
+ this decorator catches specific exceptions and returns an empty list instead of
66
+ propagating the error to the terminal.
67
+
68
+ Currently catches:
69
+ - requests.exceptions.ConnectionError: Server connection failures
70
+
71
+ Usage:
72
+ ------
73
+ @suppress_completion_errors
74
+ def my_completion_func(ctx, param, incomplete):
75
+ # code that might fail (e.g., server calls)
76
+ return completion_items
77
+
78
+ Returns
79
+ -------
80
+ Wrapped function that returns [] on caught exceptions
81
+
82
+ """
83
+
84
+ @wraps(func)
85
+ def wrapper(*args, **kwargs) -> list[CompletionItem]: # noqa: ANN002, ANN003
86
+ try:
87
+ return func(*args, **kwargs)
88
+ except requests.exceptions.ConnectionError:
89
+ # Silently fail during shell completion - return empty list
90
+ # This prevents error messages from appearing during tab completion
91
+ return []
92
+
93
+ return wrapper
94
+
95
+
56
96
  def finalize_completion(
57
97
  candidates: list,
58
98
  incomplete: str = "",
@@ -82,7 +122,7 @@ def finalize_completion(
82
122
 
83
123
  """
84
124
  if sort_by not in (SORT_BY_KEY, SORT_BY_DESC, NOT_SORTED):
85
- raise ClickException("sort_by should be -1, 0 or 1.")
125
+ raise CmemcError("sort_by should be -1, 0 or 1.")
86
126
  incomplete = incomplete.lower()
87
127
  if len(candidates) == 0:
88
128
  return candidates
@@ -127,7 +167,7 @@ def finalize_completion(
127
167
  )
128
168
  return [CompletionItem(value=element[0], help=element[1]) for element in sorted_list]
129
169
 
130
- raise ClickException(
170
+ raise CmemcError(
131
171
  "Candidates should be a list of strings or a list of tuples." f" Got {candidates}"
132
172
  )
133
173
 
@@ -160,6 +200,7 @@ def add_metadata_parameter(list_: list | None = None) -> list:
160
200
  return list_
161
201
 
162
202
 
203
+ @suppress_completion_errors
163
204
  def acl_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
164
205
  """Prepare a list of access condition identifier"""
165
206
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -174,6 +215,7 @@ def acl_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionIt
174
215
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
175
216
 
176
217
 
218
+ @suppress_completion_errors
177
219
  def acl_actions(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
178
220
  """Prepare a list of access condition actions"""
179
221
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -198,6 +240,7 @@ def acl_actions(ctx: Context, param: Argument, incomplete: str) -> list[Completi
198
240
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
199
241
 
200
242
 
243
+ @suppress_completion_errors
201
244
  def acl_users(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
202
245
  """Prepare a list of access condition users"""
203
246
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -219,6 +262,7 @@ def acl_users(ctx: Context, param: Argument, incomplete: str) -> list[Completion
219
262
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
220
263
 
221
264
 
265
+ @suppress_completion_errors
222
266
  def acl_groups(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
223
267
  """Prepare a list of access condition groups"""
224
268
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -267,6 +311,7 @@ def add_read_only_and_uri_property_parameters(list_: list | None = None) -> list
267
311
  return list_
268
312
 
269
313
 
314
+ @suppress_completion_errors
270
315
  def dataset_parameter(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
271
316
  """Prepare a list of dataset parameters for a dataset type."""
272
317
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -317,6 +362,7 @@ def dataset_parameter(ctx: Context, param: Argument, incomplete: str) -> list[Co
317
362
  return [CompletionItem(value=option[0], help=option[1]) for option in options]
318
363
 
319
364
 
365
+ @suppress_completion_errors
320
366
  def dataset_types(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
321
367
  """Prepare a list of dataset types."""
322
368
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -336,6 +382,7 @@ def dataset_types(ctx: Context, param: Argument, incomplete: str) -> list[Comple
336
382
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
337
383
 
338
384
 
385
+ @suppress_completion_errors
339
386
  def dataset_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
340
387
  """Prepare a list of projectid:datasetid dataset identifier."""
341
388
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -345,43 +392,19 @@ def dataset_ids(ctx: Context, param: Argument, incomplete: str) -> list[Completi
345
392
  return finalize_completion(candidates=options, incomplete=incomplete)
346
393
 
347
394
 
348
- def dataset_list_filter(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
349
- """Prepare a list of filter names and values for dataset list filter."""
350
- filter_names = [
351
- ("project", "Filter by project ID."),
352
- ("regex", "Filter by regular expression on the dataset label."),
353
- ("tag", "Filter by tag label."),
354
- ("type", "Filter by dataset type."),
355
- ]
356
- filter_regex = [
357
- ("^Final:", "Example: Dataset label starts with 'Final:'."),
358
- (
359
- r"[12][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]",
360
- "Example: Dataset label contains a date-like string.",
361
- ),
362
- ]
363
- options = []
364
- args = get_completion_args(incomplete)
365
- if args[len(args) - 1] == "--filter":
366
- options = finalize_completion(candidates=filter_names, incomplete=incomplete)
367
- if args[len(args) - 1] == "type":
368
- options = dataset_types(ctx, param, incomplete)
369
- if args[len(args) - 1] == "project":
370
- options = project_ids(ctx, param, incomplete)
371
- if args[len(args) - 1] == "tag":
372
- options = tag_labels(ctx, param, incomplete, "dataset")
373
- if args[len(args) - 1] == "regex":
374
- options = finalize_completion(candidates=filter_regex, incomplete=incomplete)
375
- return options
376
-
377
-
395
+ @suppress_completion_errors
378
396
  def resource_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
379
397
  """Prepare a list of projectid:resourceid resource identifier."""
380
398
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
381
- options = [_["id"] for _ in get_all_resources()]
399
+ options = []
400
+ for _ in get_all_resources():
401
+ if check_option_in_params(_["id"], ctx.params.get(str(param.name))):
402
+ continue
403
+ options.append(_["id"])
382
404
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
383
405
 
384
406
 
407
+ @suppress_completion_errors
385
408
  def scheduler_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
386
409
  """Prepare a list of projectid:schedulerid scheduler identifier."""
387
410
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -417,11 +440,13 @@ def vocabularies(
417
440
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
418
441
 
419
442
 
443
+ @suppress_completion_errors
420
444
  def installed_vocabularies(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
421
445
  """Prepare a list of installed vocabulary graphs."""
422
446
  return vocabularies(ctx, param, incomplete, filter_="installed")
423
447
 
424
448
 
449
+ @suppress_completion_errors
425
450
  def installable_vocabularies(
426
451
  ctx: Context, param: Argument, incomplete: str
427
452
  ) -> list[CompletionItem]:
@@ -444,6 +469,7 @@ def file_list(
444
469
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_KEY)
445
470
 
446
471
 
472
+ @suppress_completion_errors
447
473
  def workflow_io_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
448
474
  """Prepare a list of io workflows."""
449
475
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -455,11 +481,13 @@ def workflow_io_ids(ctx: Context, param: Argument, incomplete: str) -> list[Comp
455
481
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
456
482
 
457
483
 
484
+ @suppress_completion_errors
458
485
  def replay_files(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
459
486
  """Prepare a list of JSON replay files."""
460
487
  return file_list(incomplete=incomplete, suffix=".json", description="JSON query replay file")
461
488
 
462
489
 
490
+ @suppress_completion_errors
463
491
  def installed_package_names(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
464
492
  """Prepare a list of installed packages."""
465
493
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -467,6 +495,7 @@ def installed_package_names(ctx: Context, param: Argument, incomplete: str) -> l
467
495
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_KEY)
468
496
 
469
497
 
498
+ @suppress_completion_errors
470
499
  def published_package_names(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
471
500
  """List of plugin packages scraped from pypi.org."""
472
501
  options = [(_.name, f"{_.version}: {_.description}") for _ in get_published_packages()]
@@ -483,6 +512,7 @@ def python_package_files(ctx: Context, param: Argument, incomplete: str) -> list
483
512
  )
484
513
 
485
514
 
515
+ @suppress_completion_errors
486
516
  def installable_packages(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
487
517
  """Installable packages from files and pypi.org."""
488
518
  return python_package_files(ctx, param, incomplete) + published_package_names(
@@ -490,6 +520,7 @@ def installable_packages(ctx: Context, param: Argument, incomplete: str) -> list
490
520
  )
491
521
 
492
522
 
523
+ @suppress_completion_errors
493
524
  def workflow_io_output_files(
494
525
  ctx: Context, param: Argument, incomplete: str
495
526
  ) -> list[CompletionItem]:
@@ -504,6 +535,7 @@ def workflow_io_output_files(
504
535
  )
505
536
 
506
537
 
538
+ @suppress_completion_errors
507
539
  def workflow_io_input_files(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
508
540
  """Prepare a list of acceptable workflow io input files."""
509
541
  files = []
@@ -548,6 +580,7 @@ def get_dataset_file_mapping() -> dict[str, dict[str, str]]:
548
580
  }
549
581
 
550
582
 
583
+ @suppress_completion_errors
551
584
  def dataset_files(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
552
585
  """Prepare a list of dataset files."""
553
586
  files = []
@@ -570,6 +603,7 @@ def dataset_files(ctx: Context, param: Argument, incomplete: str) -> list[Comple
570
603
  return files + filtered_multicsv
571
604
 
572
605
 
606
+ @suppress_completion_errors
573
607
  def project_files(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
574
608
  """Prepare a list of workspace files."""
575
609
  return file_list(
@@ -579,11 +613,23 @@ def project_files(ctx: Context, param: Argument, incomplete: str) -> list[Comple
579
613
  )
580
614
 
581
615
 
616
+ @suppress_completion_errors
582
617
  def ini_files(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
583
618
  """Prepare a list of workspace files."""
584
619
  return file_list(incomplete=incomplete, suffix=".ini", description="INI file")
585
620
 
586
621
 
622
+ @suppress_completion_errors
623
+ def acl_files(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
624
+ """Prepare a list of ACL files."""
625
+ return file_list(
626
+ incomplete=incomplete,
627
+ suffix=".acls.json",
628
+ description="eccenca Corporate Memory ACL backup file",
629
+ )
630
+
631
+
632
+ @suppress_completion_errors
587
633
  def workspace_files(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
588
634
  """Prepare a list of workspace files."""
589
635
  return file_list(
@@ -600,6 +646,7 @@ def sparql_files(ctx: Context, param: Argument, incomplete: str) -> list[Complet
600
646
  ) + file_list(incomplete=incomplete, suffix=".rq", description="SPARQL query file")
601
647
 
602
648
 
649
+ @suppress_completion_errors
603
650
  def triple_files(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
604
651
  """Prepare a list of triple files."""
605
652
  return (
@@ -620,6 +667,7 @@ def triple_files(ctx: Context, param: Argument, incomplete: str) -> list[Complet
620
667
  )
621
668
 
622
669
 
670
+ @suppress_completion_errors
623
671
  def sparql_accept_types(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
624
672
  """Prepare a list of commonly used SPARQL accept content types."""
625
673
  examples = [
@@ -634,6 +682,7 @@ def sparql_accept_types(ctx: Context, param: Argument, incomplete: str) -> list[
634
682
  return finalize_completion(candidates=examples, incomplete=incomplete)
635
683
 
636
684
 
685
+ @suppress_completion_errors
637
686
  def placeholder(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
638
687
  """Prepare a list of placeholder from the to-be executed queries."""
639
688
  args = get_completion_args(incomplete)
@@ -683,6 +732,7 @@ def remote_queries(ctx: Context, param: Argument, incomplete: str) -> list[Compl
683
732
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
684
733
 
685
734
 
735
+ @suppress_completion_errors
686
736
  def remote_queries_and_sparql_files(
687
737
  ctx: Context, param: Argument, incomplete: str
688
738
  ) -> list[CompletionItem]:
@@ -692,6 +742,7 @@ def remote_queries_and_sparql_files(
692
742
  return remote + files
693
743
 
694
744
 
745
+ @suppress_completion_errors
695
746
  def workflow_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
696
747
  """Prepare a list of projectid:taskid workflow identifier."""
697
748
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -706,6 +757,7 @@ def workflow_ids(ctx: Context, param: Argument, incomplete: str) -> list[Complet
706
757
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
707
758
 
708
759
 
760
+ @suppress_completion_errors
709
761
  def marshalling_plugins(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
710
762
  """Prepare a list of supported workspace/project import/export plugins."""
711
763
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -721,6 +773,7 @@ def marshalling_plugins(ctx: Context, param: Argument, incomplete: str) -> list[
721
773
  )
722
774
 
723
775
 
776
+ @suppress_completion_errors
724
777
  def project_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
725
778
  """Prepare a list of project IDs for auto-completion."""
726
779
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -728,7 +781,7 @@ def project_ids(ctx: Context, param: Argument, incomplete: str) -> list[Completi
728
781
  options = []
729
782
  for _ in projects:
730
783
  project_id = _["name"]
731
- label = _["metaData"]["label"]
784
+ label = _["metaData"].get("label", "")
732
785
  # do not add project if already in the command line
733
786
  if check_option_in_params(project_id, ctx.params.get(str(param.name))):
734
787
  continue
@@ -757,6 +810,7 @@ def _prepare_graph_options(
757
810
  return options
758
811
 
759
812
 
813
+ @suppress_completion_errors
760
814
  def graph_uris_skip_check(
761
815
  ctx: Context, param: Argument, incomplete: str, writeable: bool = True, readonly: bool = True
762
816
  ) -> list[CompletionItem]:
@@ -767,6 +821,7 @@ def graph_uris_skip_check(
767
821
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
768
822
 
769
823
 
824
+ @suppress_completion_errors
770
825
  def graph_uris(
771
826
  ctx: Context, param: Argument, incomplete: str, writeable: bool = True, readonly: bool = True
772
827
  ) -> list[CompletionItem]:
@@ -775,6 +830,7 @@ def graph_uris(
775
830
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
776
831
 
777
832
 
833
+ @suppress_completion_errors
778
834
  def ignore_graph_uris(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
779
835
  """Prepare a list of import graphs for auto-completion."""
780
836
  data_graph = ctx.args[0]
@@ -785,11 +841,13 @@ def ignore_graph_uris(ctx: Context, param: Argument, incomplete: str) -> list[Co
785
841
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
786
842
 
787
843
 
844
+ @suppress_completion_errors
788
845
  def writable_graph_uris(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
789
846
  """Prepare a list of writable graphs for auto-completion."""
790
847
  return graph_uris(ctx, param, incomplete, writeable=True, readonly=False)
791
848
 
792
849
 
850
+ @suppress_completion_errors
793
851
  def graph_uris_with_all_graph_uri(
794
852
  ctx: Context, param: Argument, incomplete: str
795
853
  ) -> list[CompletionItem]:
@@ -806,6 +864,7 @@ def graph_uris_with_all_graph_uri(
806
864
  return options
807
865
 
808
866
 
867
+ @suppress_completion_errors
809
868
  def connections(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
810
869
  """Prepare a list of config connections for auto-completion."""
811
870
  # since ctx does not have an obj here, we re-create the object
@@ -814,6 +873,7 @@ def connections(ctx: Context, param: Argument, incomplete: str) -> list[Completi
814
873
  return finalize_completion(candidates=options, incomplete=incomplete)
815
874
 
816
875
 
876
+ @suppress_completion_errors
817
877
  def graph_export_templates(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
818
878
  """Prepare a list of example templates for the graph export command."""
819
879
  examples = [
@@ -828,6 +888,7 @@ def graph_export_templates(ctx: Context, param: Argument, incomplete: str) -> li
828
888
  return finalize_completion(candidates=examples, incomplete=incomplete)
829
889
 
830
890
 
891
+ @suppress_completion_errors
831
892
  def project_export_templates(
832
893
  ctx: Context, param: Argument, incomplete: str
833
894
  ) -> list[CompletionItem]:
@@ -840,6 +901,7 @@ def project_export_templates(
840
901
  return finalize_completion(candidates=examples, incomplete=incomplete)
841
902
 
842
903
 
904
+ @suppress_completion_errors
843
905
  def workspace_export_templates(
844
906
  ctx: Context, param: Argument, incomplete: str
845
907
  ) -> list[CompletionItem]:
@@ -852,30 +914,7 @@ def workspace_export_templates(
852
914
  return finalize_completion(candidates=examples, incomplete=incomplete)
853
915
 
854
916
 
855
- def graph_list_filter(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
856
- """Prepare a list of filter names and values for graph list filter."""
857
- filter_names = [
858
- (
859
- "access",
860
- "List only graphs which have a certain access condition " "(readonly or writeable).",
861
- ),
862
- ("imported-by", "List only graphs which are in the import tree of a " "specified graph."),
863
- ]
864
- filter_values_access = [
865
- ("readonly", "List only graphs which are NOT writable for the current user."),
866
- ("writeable", "List only graphs which ARE writeable for the current user."),
867
- ]
868
- args = get_completion_args(incomplete)
869
- options = []
870
- if args[len(args) - 1] == "--filter":
871
- options = finalize_completion(candidates=filter_names, incomplete=incomplete)
872
- if args[len(args) - 1] == "access":
873
- options = finalize_completion(candidates=filter_values_access, incomplete=incomplete)
874
- if args[len(args) - 1] == "imported-by":
875
- options = graph_uris(ctx, param, incomplete)
876
- return options
877
-
878
-
917
+ @suppress_completion_errors
879
918
  def variable_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
880
919
  """Prepare a list of variables IDs for auto-completion."""
881
920
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -893,55 +932,7 @@ def variable_ids(ctx: Context, param: Argument, incomplete: str) -> list[Complet
893
932
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_KEY)
894
933
 
895
934
 
896
- def variable_list_filter(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
897
- """Prepare a list of filter names and values for variable list filter."""
898
- filter_names = [
899
- ("project", "Filter for variables from a specific project."),
900
- (
901
- "regex",
902
- "Filter for variables with a regular expression search over "
903
- "id, value and description.",
904
- ),
905
- ]
906
- filter_values_regex = [
907
- ("ending$", "Variables name ends with 'ending'."),
908
- ("^starting", "Variables name starts with 'starting'."),
909
- ]
910
- args = get_completion_args(incomplete)
911
- if args[len(args) - 1] == "--filter":
912
- return [CompletionItem(value=f[0], help=f[1]) for f in filter_names]
913
- if args[len(args) - 1] == "regex":
914
- return finalize_completion(candidates=filter_values_regex, incomplete=incomplete)
915
- if args[len(args) - 1] == "project":
916
- return project_ids(ctx, param, incomplete)
917
- return []
918
-
919
-
920
- def resource_list_filter(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
921
- """Prepare a list of filter names and values for resource list filter."""
922
- filter_names = [
923
- ("project", "Filter for file resources from a specific project."),
924
- (
925
- "regex",
926
- "Filter for file resources with a regular expression search on " "the name field.",
927
- ),
928
- ]
929
- filter_values_regex = [
930
- ("csv$", "File resources which name ends with .csv"),
931
- ("2021-10-[0-9][0-9]", "File resources which name has a date from 2021-10 in it"),
932
- ]
933
- args = get_completion_args(incomplete)
934
- if args[len(args) - 1] == "--filter":
935
- return [CompletionItem(value=f[0], help=f[1]) for f in filter_names]
936
- if args[len(args) - 1] == "project":
937
- return finalize_completion(
938
- candidates=project_ids(ctx, param, incomplete), incomplete=incomplete
939
- )
940
- if args[len(args) - 1] == "regex":
941
- return finalize_completion(candidates=filter_values_regex, incomplete=incomplete)
942
- return []
943
-
944
-
935
+ @suppress_completion_errors
945
936
  def workflow_list_filter(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
946
937
  """Prepare a list of filter names and values for workflow list filter."""
947
938
  filter_names = [
@@ -979,6 +970,7 @@ def workflow_list_filter(ctx: Context, param: Argument, incomplete: str) -> list
979
970
  return finalize_completion(candidates=options, incomplete=incomplete)
980
971
 
981
972
 
973
+ @suppress_completion_errors
982
974
  def tag_labels(
983
975
  ctx: Context, param: Argument, incomplete: str, item_type: str
984
976
  ) -> list[CompletionItem]:
@@ -999,6 +991,7 @@ def tag_labels(
999
991
  )
1000
992
 
1001
993
 
994
+ @suppress_completion_errors
1002
995
  def status_keys(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
1003
996
  """Prepare a list of status keys for the admin status command."""
1004
997
  os.environ["CMEMPY_IS_CHATTY"] = "false"
@@ -1008,6 +1001,7 @@ def status_keys(ctx: Context, param: Argument, incomplete: str) -> list[Completi
1008
1001
  return finalize_completion(candidates=options, incomplete=incomplete)
1009
1002
 
1010
1003
 
1004
+ @suppress_completion_errors
1011
1005
  def user_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
1012
1006
  """Prepare a list of username for admin update/delete/password command."""
1013
1007
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -1015,6 +1009,7 @@ def user_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionI
1015
1009
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
1016
1010
 
1017
1011
 
1012
+ @suppress_completion_errors
1018
1013
  def user_group_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
1019
1014
  """Prepare a list of group name for admin user update --(un)assign-group parameter"""
1020
1015
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -1041,6 +1036,7 @@ def user_group_ids(ctx: Context, param: Argument, incomplete: str) -> list[Compl
1041
1036
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
1042
1037
 
1043
1038
 
1039
+ @suppress_completion_errors
1044
1040
  def client_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
1045
1041
  """Prepare a list of client ids for admin secret and update command."""
1046
1042
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -1048,6 +1044,7 @@ def client_ids(ctx: Context, param: Argument, incomplete: str) -> list[Completio
1048
1044
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
1049
1045
 
1050
1046
 
1047
+ @suppress_completion_errors
1051
1048
  def transformation_task_ids(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
1052
1049
  """Prepare a list of projectId:transformation task identifier."""
1053
1050
  ApplicationContext.set_connection_from_params(ctx.find_root().params)
@@ -1055,3 +1052,23 @@ def transformation_task_ids(ctx: Context, param: Argument, incomplete: str) -> l
1055
1052
  datasets = results["results"]
1056
1053
  options = [(f"{_['projectId']}:{_['id']}", _["label"]) for _ in datasets]
1057
1054
  return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)
1055
+
1056
+
1057
+ @suppress_completion_errors
1058
+ def resource_paths(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
1059
+ """Prepare a list of file resource paths within a project.
1060
+
1061
+ Returns the full path of file resources (not including the project ID prefix).
1062
+ If a project_id is available in context, lists resources from that project.
1063
+ If only one project exists, automatically uses that project.
1064
+ """
1065
+ ApplicationContext.set_connection_from_params(ctx.find_root().params)
1066
+ project_id = ctx.params.get("project_id")
1067
+ if not project_id:
1068
+ projects = get_projects()
1069
+ if len(projects) == 1:
1070
+ project_id = projects[0]["name"]
1071
+ if project_id is None:
1072
+ return []
1073
+ options = [_["fullPath"] for _ in list(get_resources(project_id))]
1074
+ return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_DESC)