cmem-cmemc 24.3.2__py3-none-any.whl → 25.1.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/__init__.py +1 -160
- cmem_cmemc/cli.py +138 -0
- cmem_cmemc/command.py +36 -0
- cmem_cmemc/commands/admin.py +7 -6
- cmem_cmemc/commands/client.py +4 -3
- cmem_cmemc/commands/config.py +3 -2
- cmem_cmemc/commands/dataset.py +18 -17
- cmem_cmemc/commands/graph.py +20 -22
- cmem_cmemc/commands/manual.py +56 -0
- cmem_cmemc/commands/metrics.py +11 -11
- cmem_cmemc/commands/migration.py +6 -3
- cmem_cmemc/commands/project.py +10 -10
- cmem_cmemc/commands/python.py +29 -2
- cmem_cmemc/commands/query.py +31 -14
- cmem_cmemc/commands/resource.py +4 -3
- cmem_cmemc/commands/scheduler.py +4 -4
- cmem_cmemc/commands/store.py +2 -2
- cmem_cmemc/commands/user.py +10 -9
- cmem_cmemc/commands/validation.py +2 -2
- cmem_cmemc/commands/variable.py +1 -1
- cmem_cmemc/commands/vocabulary.py +11 -10
- cmem_cmemc/commands/workflow.py +18 -18
- cmem_cmemc/completion.py +76 -49
- cmem_cmemc/config_parser.py +44 -0
- cmem_cmemc/context.py +166 -97
- cmem_cmemc/exceptions.py +15 -2
- cmem_cmemc/manual_helper/graph.py +2 -0
- cmem_cmemc/manual_helper/multi_page.py +1 -1
- cmem_cmemc/manual_helper/single_page.py +2 -0
- cmem_cmemc/migrations/abc.py +1 -0
- cmem_cmemc/migrations/remove_noop_triple_251.py +50 -0
- cmem_cmemc/migrations/shapes_widget_integrations_243.py +0 -5
- cmem_cmemc/migrations/sparql_query_texts_242.py +53 -0
- cmem_cmemc/object_list.py +3 -3
- cmem_cmemc/parameter_types/path.py +7 -0
- cmem_cmemc/placeholder.py +69 -0
- cmem_cmemc/utils.py +49 -15
- {cmem_cmemc-24.3.2.dist-info → cmem_cmemc-25.1.0.dist-info}/METADATA +14 -14
- cmem_cmemc-25.1.0.dist-info/RECORD +59 -0
- cmem_cmemc-25.1.0.dist-info/entry_points.txt +3 -0
- cmem_cmemc-24.3.2.dist-info/RECORD +0 -53
- cmem_cmemc-24.3.2.dist-info/entry_points.txt +0 -3
- {cmem_cmemc-24.3.2.dist-info → cmem_cmemc-25.1.0.dist-info}/LICENSE +0 -0
- {cmem_cmemc-24.3.2.dist-info → cmem_cmemc-25.1.0.dist-info}/WHEEL +0 -0
cmem_cmemc/__init__.py
CHANGED
|
@@ -1,160 +1 @@
|
|
|
1
|
-
"""
|
|
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
|
cmem_cmemc/commands/admin.py
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)
|
cmem_cmemc/commands/client.py
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
cmem_cmemc/commands/config.py
CHANGED
|
@@ -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.
|
|
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
|
|
63
|
+
raise ClickException(f"Configuration key {key} is not used in this configuration.")
|
|
63
64
|
app.echo_info(str(value))
|
|
64
65
|
|
|
65
66
|
|
cmem_cmemc/commands/dataset.py
CHANGED
|
@@ -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
|
-
|
|
71
|
+
UsageError
|
|
71
72
|
|
|
72
73
|
"""
|
|
73
74
|
if filter_name not in DATASET_FILTER_TYPES:
|
|
74
|
-
raise
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
900
|
+
raise ClickException(f"Dataset '{_}' not found.")
|
|
900
901
|
|
|
901
902
|
|
|
902
903
|
@click.group(cls=CmemcGroup)
|