cmem-cmemc 24.3.3__py3-none-any.whl → 25.1.1__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/__init__.py +1 -160
  2. cmem_cmemc/cli.py +138 -0
  3. cmem_cmemc/command.py +36 -0
  4. cmem_cmemc/commands/admin.py +7 -6
  5. cmem_cmemc/commands/client.py +4 -3
  6. cmem_cmemc/commands/config.py +3 -2
  7. cmem_cmemc/commands/dataset.py +18 -17
  8. cmem_cmemc/commands/graph.py +20 -22
  9. cmem_cmemc/commands/manual.py +56 -0
  10. cmem_cmemc/commands/metrics.py +11 -11
  11. cmem_cmemc/commands/migration.py +4 -3
  12. cmem_cmemc/commands/project.py +10 -10
  13. cmem_cmemc/commands/python.py +29 -2
  14. cmem_cmemc/commands/query.py +31 -14
  15. cmem_cmemc/commands/resource.py +4 -3
  16. cmem_cmemc/commands/scheduler.py +4 -4
  17. cmem_cmemc/commands/store.py +2 -2
  18. cmem_cmemc/commands/user.py +10 -9
  19. cmem_cmemc/commands/validation.py +2 -2
  20. cmem_cmemc/commands/variable.py +1 -1
  21. cmem_cmemc/commands/vocabulary.py +11 -10
  22. cmem_cmemc/commands/workflow.py +18 -18
  23. cmem_cmemc/completion.py +76 -49
  24. cmem_cmemc/config_parser.py +44 -0
  25. cmem_cmemc/context.py +168 -99
  26. cmem_cmemc/exceptions.py +15 -2
  27. cmem_cmemc/manual_helper/graph.py +2 -0
  28. cmem_cmemc/manual_helper/multi_page.py +1 -1
  29. cmem_cmemc/manual_helper/single_page.py +2 -0
  30. cmem_cmemc/migrations/remove_noop_triple_251.py +50 -0
  31. cmem_cmemc/migrations/shapes_widget_integrations_243.py +0 -5
  32. cmem_cmemc/object_list.py +3 -3
  33. cmem_cmemc/parameter_types/path.py +7 -0
  34. cmem_cmemc/placeholder.py +69 -0
  35. cmem_cmemc/utils.py +49 -15
  36. {cmem_cmemc-24.3.3.dist-info → cmem_cmemc-25.1.1.dist-info}/METADATA +14 -14
  37. cmem_cmemc-25.1.1.dist-info/RECORD +59 -0
  38. cmem_cmemc-25.1.1.dist-info/entry_points.txt +3 -0
  39. cmem_cmemc-24.3.3.dist-info/RECORD +0 -54
  40. cmem_cmemc-24.3.3.dist-info/entry_points.txt +0 -3
  41. {cmem_cmemc-24.3.3.dist-info → cmem_cmemc-25.1.1.dist-info}/LICENSE +0 -0
  42. {cmem_cmemc-24.3.3.dist-info → cmem_cmemc-25.1.1.dist-info}/WHEEL +0 -0
cmem_cmemc/__init__.py CHANGED
@@ -1,160 +1 @@
1
- """The main command line interface."""
2
-
3
- import contextlib
4
- import os
5
- import sys
6
- import traceback
7
- from importlib.resources import open_text
8
- from subprocess import CalledProcessError # nosec
9
-
10
- import click
11
- import requests.exceptions
12
-
13
- from cmem_cmemc import completion
14
- from cmem_cmemc.command_group import CmemcGroup
15
- from cmem_cmemc.commands import (
16
- admin,
17
- config,
18
- dataset,
19
- graph,
20
- project,
21
- query,
22
- vocabulary,
23
- workflow,
24
- )
25
- from cmem_cmemc.context import CONTEXT
26
- from cmem_cmemc.exceptions import InvalidConfigurationError
27
- from cmem_cmemc.manual_helper.graph import print_manual_graph
28
- from cmem_cmemc.manual_helper.multi_page import create_multi_page_documentation
29
- from cmem_cmemc.manual_helper.single_page import print_manual
30
- from cmem_cmemc.utils import check_python_version, extract_error_message, get_version
31
-
32
- CMEMC_VERSION = get_version()
33
-
34
- # this will output a custom zsh completion function
35
- if os.environ.get("_CMEMC_COMPLETE", "") == "zsh_source":
36
- with open_text("cmem_cmemc", "_cmemc.zsh") as zsh_output:
37
- CONTEXT.echo_info(zsh_output.read())
38
- sys.exit(0)
39
-
40
- version = sys.version_info
41
- PYTHON_VERSION = f"{version.major}.{version.minor}.{version.micro}"
42
- check_python_version(ctx=CONTEXT)
43
-
44
- # set the user-agent environment for the http request headers
45
- os.environ["CMEM_USER_AGENT"] = f"cmemc/{CMEMC_VERSION} (Python {PYTHON_VERSION})"
46
-
47
- # https://github.com/pallets/click/blob/master/examples/complex/complex/cli.py
48
- CONTEXT_SETTINGS = {"auto_envvar_prefix": "CMEMC", "help_option_names": ["-h", "--help"]}
49
-
50
-
51
- @click.group(name="cmemc", cls=CmemcGroup, context_settings=CONTEXT_SETTINGS)
52
- @click.option(
53
- "-c",
54
- "--connection",
55
- type=click.STRING,
56
- shell_complete=completion.connections,
57
- help="Use a specific connection from the config file.",
58
- )
59
- @click.option(
60
- "--config-file",
61
- shell_complete=completion.ini_files,
62
- type=click.Path(readable=True, allow_dash=False, dir_okay=False),
63
- default=CONTEXT.config_file_default,
64
- show_default=True,
65
- help="Use this config file instead of the default one.",
66
- )
67
- @click.option("-q", "--quiet", is_flag=True, help="Suppress any non-error info messages.")
68
- @click.option(
69
- "-d", "--debug", is_flag=True, help="Output debug messages and stack traces after errors."
70
- )
71
- @click.version_option(
72
- version=CMEMC_VERSION,
73
- message="%(prog)s, version %(version)s, " f"running under python {PYTHON_VERSION}",
74
- )
75
- @click.pass_context
76
- def cli(
77
- ctx: click.core.Context, debug: bool, quiet: bool, config_file: str, connection: str
78
- ) -> None:
79
- """Eccenca Corporate Memory Control (cmemc).
80
-
81
- cmemc is the eccenca Corporate Memory Command Line Interface (CLI).
82
-
83
- Available commands are grouped by affecting resource type (such as graph,
84
- project and query).
85
- Each command and group has a separate --help screen for detailed
86
- documentation.
87
- In order to see possible commands in a group, simply
88
- execute the group command without further parameter (e.g. cmemc project).
89
-
90
- If your terminal supports colors, these coloring rules are applied:
91
- Groups are colored in white; Commands which change data are colored in
92
- red; all other commands as well as options are colored in green.
93
-
94
- Please also have a look at the cmemc online documentation:
95
-
96
- https://eccenca.com/go/cmemc
97
-
98
- cmemc is © 2025 eccenca GmbH, licensed under the Apache License 2.0.
99
- """
100
- ctx.obj = CONTEXT
101
- # hidden feature: 'CMEMC_MANUAL=true cmemc -q config list' will output
102
- # the whole markdown manual
103
- if os.getenv("CMEMC_MANUAL_DIR"):
104
- create_multi_page_documentation(ctx, str(os.getenv("CMEMC_MANUAL_DIR")))
105
- ctx.exit()
106
- # hidden feature: 'CMEMC_MANUAL=true cmemc -q config list' will output
107
- # the whole markdown manual
108
- if os.getenv("CMEMC_MANUAL"):
109
- print_manual(ctx)
110
- ctx.exit()
111
- # hidden feature: 'CMEMC_MANUAL_GRAPH=true cmemc -q config list' will
112
- # output the documentation graph
113
- if os.getenv("CMEMC_MANUAL_GRAPH"):
114
- print_manual_graph(ctx, get_version())
115
- ctx.exit()
116
- ctx.obj.set_quiet(quiet)
117
- ctx.obj.set_debug(debug)
118
- ctx.obj.set_config_file(config_file)
119
- try:
120
- ctx.obj.set_connection(connection)
121
- except InvalidConfigurationError:
122
- # if config is broken still allow for "config edit"
123
- # means: do not forward this exception if "config edit"
124
- if " ".join(sys.argv).find("config edit") == -1:
125
- raise
126
-
127
-
128
- cli.add_command(admin.admin)
129
- cli.add_command(config.config)
130
- cli.add_command(dataset.dataset)
131
- cli.add_command(graph.graph)
132
- cli.add_command(project.project)
133
- cli.add_command(query.query)
134
- cli.add_command(vocabulary.vocabulary)
135
- cli.add_command(workflow.workflow)
136
-
137
-
138
- def main() -> None:
139
- """Start the command line interface."""
140
- try:
141
- cli() # pylint: disable=no-value-for-parameter
142
- except (
143
- OSError,
144
- CalledProcessError,
145
- requests.exceptions.HTTPError,
146
- requests.exceptions.ConnectionError,
147
- ValueError,
148
- NotImplementedError,
149
- KeyError,
150
- ) as error:
151
- if CONTEXT.is_completing():
152
- # if currently autocompleting -> silently die with exit 1
153
- sys.exit(1)
154
- CONTEXT.echo_debug(traceback.format_exc())
155
- CONTEXT.echo_error(extract_error_message(error))
156
- with contextlib.suppress(
157
- requests.exceptions.ConnectionError, requests.exceptions.HTTPError
158
- ):
159
- CONTEXT.check_versions()
160
- sys.exit(1)
1
+ """cmem_cmemc module"""
cmem_cmemc/cli.py ADDED
@@ -0,0 +1,138 @@
1
+ """The main command line interface."""
2
+
3
+ import os
4
+ import sys
5
+ import traceback
6
+ from importlib.resources import open_text
7
+ from os import environ as env
8
+
9
+ import click
10
+
11
+ from cmem_cmemc import completion
12
+ from cmem_cmemc.command_group import CmemcGroup
13
+ from cmem_cmemc.commands import (
14
+ admin,
15
+ config,
16
+ dataset,
17
+ graph,
18
+ manual,
19
+ project,
20
+ query,
21
+ vocabulary,
22
+ workflow,
23
+ )
24
+ from cmem_cmemc.context import ApplicationContext
25
+ from cmem_cmemc.exceptions import CmemcError
26
+ from cmem_cmemc.utils import check_python_version, extract_error_message, get_version
27
+
28
+ CMEMC_VERSION = get_version()
29
+
30
+ # this will output a custom zsh completion function
31
+ if os.environ.get("_CMEMC_COMPLETE", "") == "zsh_source":
32
+ with open_text("cmem_cmemc", "_cmemc.zsh") as zsh_output:
33
+ click.secho(zsh_output.read())
34
+ sys.exit(0)
35
+
36
+ version = sys.version_info
37
+ PYTHON_VERSION = f"{version.major}.{version.minor}.{version.micro}"
38
+ check_python_version(ctx=ApplicationContext)
39
+
40
+ # set the user-agent environment for the http request headers
41
+ os.environ["CMEM_USER_AGENT"] = f"cmemc/{CMEMC_VERSION} (Python {PYTHON_VERSION})"
42
+
43
+ # https://github.com/pallets/click/blob/master/examples/complex/complex/cli.py
44
+ CONTEXT_SETTINGS = {"auto_envvar_prefix": "CMEMC", "help_option_names": ["-h", "--help"]}
45
+
46
+
47
+ @click.group(name="cmemc", cls=CmemcGroup, context_settings=CONTEXT_SETTINGS)
48
+ @click.option(
49
+ "-c",
50
+ "--connection",
51
+ type=click.STRING,
52
+ shell_complete=completion.connections,
53
+ help="Use a specific connection from the config file.",
54
+ )
55
+ @click.option(
56
+ "--config-file",
57
+ shell_complete=completion.ini_files,
58
+ type=click.Path(readable=True, allow_dash=False, dir_okay=False),
59
+ default=ApplicationContext.DEFAULT_CONFIG_FILE,
60
+ show_default=f"Using {env['CMEMC_CONFIG_FILE']} "
61
+ f"instead of {ApplicationContext.DEFAULT_CONFIG_FILE}"
62
+ if "CMEMC_CONFIG_FILE" in env
63
+ else ApplicationContext.DEFAULT_CONFIG_FILE,
64
+ help="Use this config file instead of the default one.",
65
+ )
66
+ @click.option("-q", "--quiet", is_flag=True, help="Suppress any non-error info messages.")
67
+ @click.option(
68
+ "-d", "--debug", is_flag=True, help="Output debug messages and stack traces after errors."
69
+ )
70
+ @click.option(
71
+ "--external-http-timeout",
72
+ default=ApplicationContext.DEFAULT_EXTERNAL_HTTP_TIMEOUT,
73
+ type=int,
74
+ show_default=True,
75
+ help="Timeout in seconds for external HTTP requests.",
76
+ )
77
+ @click.version_option(
78
+ version=CMEMC_VERSION,
79
+ message="%(prog)s, version %(version)s, " f"running under python {PYTHON_VERSION}",
80
+ )
81
+ @click.pass_context
82
+ def cli( # noqa: PLR0913
83
+ ctx: click.core.Context,
84
+ debug: bool,
85
+ quiet: bool,
86
+ config_file: str,
87
+ connection: str,
88
+ external_http_timeout: int,
89
+ ) -> None:
90
+ """Eccenca Corporate Memory Control (cmemc).
91
+
92
+ cmemc is the eccenca Corporate Memory Command Line Interface (CLI).
93
+
94
+ Available commands are grouped by affecting resource type (such as graph,
95
+ project and query).
96
+ Each command and group has a separate --help screen for detailed
97
+ documentation.
98
+ In order to see possible commands in a group, simply
99
+ execute the group command without further parameter (e.g. cmemc project).
100
+
101
+ If your terminal supports colors, these coloring rules are applied:
102
+ Groups are colored in white; Commands which change data are colored in
103
+ red; all other commands as well as options are colored in green.
104
+
105
+ Please also have a look at the cmemc online documentation:
106
+
107
+ https://eccenca.com/go/cmemc
108
+
109
+ cmemc is © 2025 eccenca GmbH, licensed under the Apache License 2.0.
110
+ """
111
+ _ = connection, debug, quiet, config_file, external_http_timeout
112
+ if " ".join(sys.argv).find("config edit") != -1:
113
+ app = ApplicationContext(config_file=config_file, debug=debug, quiet=quiet)
114
+ else:
115
+ app = ApplicationContext.from_params(params=ctx.params)
116
+ ctx.obj = app
117
+
118
+
119
+ cli.add_command(admin.admin)
120
+ cli.add_command(config.config)
121
+ cli.add_command(dataset.dataset)
122
+ cli.add_command(graph.graph)
123
+ cli.add_command(project.project)
124
+ cli.add_command(query.query)
125
+ cli.add_command(vocabulary.vocabulary)
126
+ cli.add_command(workflow.workflow)
127
+ cli.add_command(manual.manual_command)
128
+
129
+
130
+ def main() -> None:
131
+ """Start the command line interface."""
132
+ try:
133
+ cli() # pylint: disable=no-value-for-parameter
134
+ except CmemcError as error:
135
+ app: ApplicationContext = error.app
136
+ app.echo_debug(traceback.format_exc())
137
+ app.echo_error(extract_error_message(error))
138
+ sys.exit(1)
cmem_cmemc/command.py CHANGED
@@ -1,7 +1,15 @@
1
1
  """cmemc Click Command"""
2
2
 
3
+ from subprocess import CalledProcessError
4
+ from typing import Any
5
+
6
+ import click
7
+ import requests
3
8
  from click_help_colors import HelpColorsCommand
4
9
 
10
+ from cmem_cmemc.exceptions import CmemcError
11
+ from cmem_cmemc.utils import extract_error_message
12
+
5
13
 
6
14
  class CmemcCommand(HelpColorsCommand):
7
15
  """Wrapper click.Command class to have a single extension point.
@@ -18,3 +26,31 @@ class CmemcCommand(HelpColorsCommand):
18
26
  kwargs.setdefault("help_headers_color", self.color_for_headers)
19
27
  kwargs.setdefault("help_options_color", self.color_for_options)
20
28
  super().__init__(*args, **kwargs)
29
+
30
+ def invoke(self, ctx: click.core.Context) -> Any: # noqa: ANN401
31
+ """Execute the command and handles known exceptions by wrapping them in a CmemcError.
32
+
33
+ This method overrides the default Click command invocation to catch a predefined
34
+ set of exceptions (such as OSError, HTTPError, ValueError, etc.) and re-raises them
35
+ as a unified CmemcError. This allows consistent error handling and messaging across
36
+ all CLI commands.
37
+
38
+ Args:
39
+ ctx (click.core.Context): The Click context for the command.
40
+
41
+ Raises:
42
+ CmemcError: Wraps any of the caught exceptions and attaches context-specific data.
43
+
44
+ """
45
+ try:
46
+ return super().invoke(ctx)
47
+ except (
48
+ OSError,
49
+ CalledProcessError,
50
+ requests.exceptions.HTTPError,
51
+ requests.exceptions.ConnectionError,
52
+ ValueError,
53
+ NotImplementedError,
54
+ KeyError,
55
+ ) as e:
56
+ raise CmemcError(ctx.obj, extract_error_message(e, True)) from e
@@ -4,6 +4,7 @@ from datetime import datetime, timezone
4
4
 
5
5
  import click
6
6
  import jwt
7
+ from click import ClickException
7
8
  from cmem.cmempy.api import get_access_token, get_token
8
9
  from cmem.cmempy.config import get_cmem_base_uri
9
10
  from cmem.cmempy.health import get_complete_status_info
@@ -43,7 +44,7 @@ def _check_cmem_license(app: ApplicationContext, data: dict, exit_1: str) -> Non
43
44
  cmem_license_end = license_["validDate"]
44
45
  output = f"Your Corporate Memory license expired on {cmem_license_end}."
45
46
  if exit_1 in ("error", "always"):
46
- raise ValueError(output)
47
+ raise ClickException(output)
47
48
  app.echo_error(output)
48
49
 
49
50
 
@@ -59,7 +60,7 @@ def _check_graphdb_license(app: ApplicationContext, data: dict, months: int, exi
59
60
  graphdb_license_end = data["explore"]["info"]["store"]["licenseExpiration"]
60
61
  output = f"Your GraphDB license expires on {graphdb_license_end}."
61
62
  if exit_1 == "always":
62
- raise ValueError(output)
63
+ raise ClickException(output)
63
64
  app.echo_warning(output)
64
65
 
65
66
 
@@ -123,7 +124,7 @@ def status_command( # noqa: C901, PLR0912
123
124
  app.echo_debug(_["explore"]["error"])
124
125
 
125
126
  if exit_1 in ("always", "error") and (_["overall"]["healthy"] != "UP"):
126
- raise ValueError(
127
+ raise ClickException(
127
128
  f"One or more major status flags are DOWN or UNKNOWN: {_!r}",
128
129
  )
129
130
  if raw:
@@ -135,19 +136,19 @@ def status_command( # noqa: C901, PLR0912
135
136
  app.echo_info(table[0][1])
136
137
  return
137
138
  if len(table) == 0:
138
- raise ValueError(f"No values for key(s): {key}")
139
+ raise ClickException(f"No values for key(s): {key}")
139
140
  app.echo_info_table(table, headers=["Key", "Value"], sort_column=0)
140
141
  return
141
142
  app.check_versions()
142
143
  _workspace_config = _["explore"]["info"].get("workspaceConfiguration", {})
143
144
  if _workspace_config.get("workspacesToMigrate"):
144
145
  if exit_1 == "always":
145
- raise ValueError(WARNING_MIGRATION)
146
+ raise ClickException(WARNING_MIGRATION)
146
147
  app.echo_warning(WARNING_MIGRATION)
147
148
 
148
149
  if _["shapes"]["version"] not in (_["explore"]["version"], "UNKNOWN"):
149
150
  if exit_1 == "always":
150
- raise ValueError(WARNING_SHAPES)
151
+ raise ClickException(WARNING_SHAPES)
151
152
  app.echo_warning(WARNING_SHAPES)
152
153
 
153
154
  _check_cmem_license(app=app, data=_, exit_1=exit_1)
@@ -1,6 +1,7 @@
1
1
  """Keycloak client management commands"""
2
2
 
3
3
  import click
4
+ from click import ClickException, UsageError
4
5
  from cmem.cmempy.config import get_keycloak_base_uri, get_keycloak_realm_id
5
6
  from cmem.cmempy.keycloak.client import (
6
7
  generate_client_secret,
@@ -61,11 +62,11 @@ def secret_command(app: ApplicationContext, client_id: str, generate: bool, outp
61
62
  """
62
63
  if not output and not generate:
63
64
  app.echo_info(click.get_current_context().get_help())
64
- raise ValueError("You need to use '--output' or '--generate' as an option.")
65
+ raise UsageError("You need to use '--output' or '--generate' as an option.")
65
66
 
66
67
  clients = get_client_by_client_id(client_id)
67
68
  if not clients:
68
- raise ValueError(NO_CLIENT_ERROR.format(client_id))
69
+ raise ClickException(NO_CLIENT_ERROR.format(client_id))
69
70
 
70
71
  if generate:
71
72
  if not output:
@@ -105,7 +106,7 @@ def open_command(app: ApplicationContext, client_ids: tuple[str]) -> None:
105
106
  client_id_map = {c["clientId"]: c["id"] for c in clients}
106
107
  for _ in client_ids:
107
108
  if _ not in client_id_map:
108
- raise ValueError(NO_CLIENT_ERROR.format(_))
109
+ raise ClickException(NO_CLIENT_ERROR.format(_))
109
110
  client_id = client_id_map[_]
110
111
  open_user_uri = f"{open_client_base_uri}/{client_id}/settings"
111
112
 
@@ -1,6 +1,7 @@
1
1
  """configuration commands for cmem command line interface."""
2
2
 
3
3
  import click
4
+ from click import ClickException
4
5
 
5
6
  from cmem_cmemc.command import CmemcCommand
6
7
  from cmem_cmemc.command_group import CmemcGroup
@@ -25,7 +26,7 @@ def list_command(app: ApplicationContext) -> None:
25
26
 
26
27
  Example: cmemc config list | parallel --jobs 5 cmemc -c {} admin status
27
28
  """
28
- for section_string in sorted(app.config, key=str.casefold):
29
+ for section_string in sorted(app.get_config(), key=str.casefold):
29
30
  if section_string != "DEFAULT":
30
31
  app.echo_result(section_string)
31
32
 
@@ -59,7 +60,7 @@ def get_command(app: ApplicationContext, key: str) -> None:
59
60
  value = KNOWN_CONFIG_KEYS[key]()
60
61
  app.echo_debug(f"Type of {key} value is {type(value)}")
61
62
  if value is None:
62
- raise ValueError(f"Configuration key {key} is not used in this configuration.")
63
+ raise ClickException(f"Configuration key {key} is not used in this configuration.")
63
64
  app.echo_info(str(value))
64
65
 
65
66
 
@@ -5,7 +5,7 @@ import re
5
5
 
6
6
  import click
7
7
  import requests.exceptions
8
- from click import UsageError
8
+ from click import ClickException, UsageError
9
9
  from cmem.cmempy.config import get_cmem_base_uri
10
10
  from cmem.cmempy.workspace import get_task_plugin_description, get_task_plugins
11
11
  from cmem.cmempy.workspace.projects.datasets.dataset import (
@@ -28,6 +28,7 @@ from cmem_cmemc.command_group import CmemcGroup
28
28
  from cmem_cmemc.commands.resource import resource
29
29
  from cmem_cmemc.completion import get_dataset_file_mapping
30
30
  from cmem_cmemc.context import ApplicationContext
31
+ from cmem_cmemc.exceptions import CmemcError
31
32
  from cmem_cmemc.parameter_types.path import ClickSmartPath
32
33
  from cmem_cmemc.smart_path import SmartPath as Path
33
34
  from cmem_cmemc.utils import check_or_select_project, struct_to_table
@@ -67,11 +68,11 @@ def _get_datasets_filtered(
67
68
 
68
69
  Raises:
69
70
  ------
70
- ValueError
71
+ UsageError
71
72
 
72
73
  """
73
74
  if filter_name not in DATASET_FILTER_TYPES:
74
- raise ValueError(
75
+ raise UsageError(
75
76
  f"{filter_name} is an unknown filter name. " f"Use one of {DATASET_FILTER_TYPES}."
76
77
  )
77
78
  # filter by project ID
@@ -99,14 +100,14 @@ def _validate_and_split_dataset_id(dataset_id: str) -> tuple[str, str]:
99
100
 
100
101
  Raises:
101
102
  ------
102
- ValueError: in case the dataset ID is not splittable
103
+ ClickException: in case the dataset ID is not splittable
103
104
 
104
105
  """
105
106
  try:
106
107
  project_part = dataset_id.split(":")[0]
107
108
  dataset_part = dataset_id.split(":")[1]
108
109
  except IndexError as error:
109
- raise ValueError(
110
+ raise ClickException(
110
111
  f"{dataset_id} is not a valid dataset ID. Use the "
111
112
  "'dataset list' command to get a list of existing datasets."
112
113
  ) from error
@@ -170,7 +171,7 @@ def _upload_file_resource(
170
171
  """
171
172
  exist = resource_exist(project_name=project_id, resource_name=remote_file_name)
172
173
  if exist and not replace:
173
- raise ValueError(
174
+ raise ClickException(
174
175
  f"A file resource with the name '{remote_file_name}' already "
175
176
  "exists in this project. \n"
176
177
  "Please rename the file or use the '--replace' "
@@ -234,7 +235,7 @@ def _get_read_only_out_of_parameter(parameter_dict: dict) -> bool:
234
235
  return True
235
236
  if read_only in ("false", False, "False"):
236
237
  return False
237
- raise ValueError(f"readOnly parameter should be 'true' or 'false' - was {read_only!r}")
238
+ raise ClickException(f"readOnly parameter should be 'true' or 'false' - was {read_only!r}")
238
239
 
239
240
 
240
241
  def _extend_parameter_with_metadata(
@@ -298,7 +299,7 @@ def _check_or_set_dataset_type(
298
299
  dataset_type = type_
299
300
  break
300
301
  if not dataset_type:
301
- raise ValueError("Missing parameter. Please specify a dataset " "type with '--type'.")
302
+ raise UsageError("Missing parameter. Please specify a dataset " "type with '--type'.")
302
303
  app.echo_warning(
303
304
  "Missing dataset type (--type) - based on the used file name, "
304
305
  f"this type is assumed: {dataset_type}"
@@ -374,7 +375,7 @@ def _check_or_select_dataset_type(app: ApplicationContext, dataset_type: str) ->
374
375
 
375
376
  Raises:
376
377
  ------
377
- ValueError: If type is not known
378
+ CmemcError: If type is not known
378
379
 
379
380
  Returns:
380
381
  -------
@@ -385,7 +386,7 @@ def _check_or_select_dataset_type(app: ApplicationContext, dataset_type: str) ->
385
386
  app.echo_debug(f"check type {dataset_type}")
386
387
  plugin = get_task_plugin_description(dataset_type)
387
388
  except requests.exceptions.HTTPError as error:
388
- raise ValueError(f"Unknown dataset type: {dataset_type}.") from error
389
+ raise CmemcError(app, f"Unknown dataset type: {dataset_type}.") from error
389
390
  else:
390
391
  return dataset_type, plugin
391
392
 
@@ -494,14 +495,14 @@ def delete_command(
494
495
  "Please use '--filter project XXX' instead."
495
496
  )
496
497
  if dataset_ids == () and not all_ and not filter_:
497
- raise ValueError(
498
+ raise UsageError(
498
499
  "Either specify at least one dataset ID"
499
500
  " or use a --filter option,"
500
501
  " or use the --all option to delete all datasets."
501
502
  )
502
503
 
503
504
  if dataset_ids and (all_ or filter_):
504
- raise ValueError("Either specify a dataset ID OR" " use a --filter or the --all option.")
505
+ raise UsageError("Either specify a dataset ID OR" " use a --filter or the --all option.")
505
506
 
506
507
  if all_ or filter_:
507
508
  # in case --all or --filter is given, a list of datasets is fetched
@@ -562,11 +563,11 @@ def download_command(
562
563
  try:
563
564
  file = project["data"]["parameters"]["file"]
564
565
  except KeyError as no_file_resource:
565
- raise ValueError(
566
- f"The dataset {dataset_id} has no associated file resource."
566
+ raise CmemcError(
567
+ app, f"The dataset {dataset_id} has no associated file resource."
567
568
  ) from no_file_resource
568
569
  if Path(output_path).exists() and replace is not True:
569
- raise ValueError(
570
+ raise UsageError(
570
571
  f"Target file {click.format_filename(output_path)} already "
571
572
  "exists. Use --replace in case you want to replace it."
572
573
  )
@@ -752,7 +753,7 @@ def create_command( # noqa: PLR0913
752
753
 
753
754
  # file required but not given
754
755
  if "file" in plugin["required"] and not dataset_file and "file" not in parameter_dict:
755
- raise ValueError(
756
+ raise UsageError(
756
757
  f"The dataset type {dataset_type} is file based, so you need "
757
758
  "to specify a file with the create command."
758
759
  )
@@ -896,7 +897,7 @@ def open_command(app: ApplicationContext, dataset_ids: tuple[str]) -> None:
896
897
  app.echo_debug(f"Open {_}: {full_url}")
897
898
  click.launch(full_url)
898
899
  else:
899
- raise ValueError(f"Dataset '{_}' not found.")
900
+ raise ClickException(f"Dataset '{_}' not found.")
900
901
 
901
902
 
902
903
  @click.group(cls=CmemcGroup)