cmem-cmemc 25.5.0rc1__py3-none-any.whl → 25.6.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.
@@ -1,220 +0,0 @@
1
- """Build dataset resource commands for cmemc."""
2
-
3
- import re
4
-
5
- import click
6
- from click import ClickException, UsageError
7
- from cmem.cmempy.workspace.projects.resources import get_all_resources
8
- from cmem.cmempy.workspace.projects.resources.resource import (
9
- delete_resource,
10
- get_resource_metadata,
11
- get_resource_usage_data,
12
- )
13
-
14
- from cmem_cmemc import completion
15
- from cmem_cmemc.command import CmemcCommand
16
- from cmem_cmemc.command_group import CmemcGroup
17
- from cmem_cmemc.context import ApplicationContext
18
- from cmem_cmemc.utils import split_task_id, struct_to_table
19
-
20
- RESOURCE_FILTER_TYPES = ["project", "regex"]
21
- RESOURCE_FILTER_TYPES_HIDDEN = ["ids"]
22
- RESOURCE_FILTER_TEXT = (
23
- "Filter file resources based on metadata. "
24
- f"First parameter CHOICE can be one of {RESOURCE_FILTER_TYPES!s}"
25
- ". The second parameter is based on CHOICE, e.g. a project "
26
- "ID or a regular expression string."
27
- )
28
-
29
-
30
- def _get_resources_filtered(
31
- resources: list[dict], filter_name: str, filter_value: str | tuple[str, ...]
32
- ) -> list[dict]:
33
- """Get file resources but filtered according to name and value."""
34
- # check for correct filter names (filter ids is used internally only)
35
- if filter_name not in RESOURCE_FILTER_TYPES + RESOURCE_FILTER_TYPES_HIDDEN:
36
- raise UsageError(
37
- f"{filter_name} is an unknown filter name. " f"Use one of {RESOURCE_FILTER_TYPES}."
38
- )
39
- # filter by ID list
40
- if filter_name == "ids":
41
- return [_ for _ in resources if _["id"] in filter_value]
42
- # filter by project
43
- if filter_name == "project":
44
- return [_ for _ in resources if _["project"] == str(filter_value)]
45
- # filter by regex
46
- if filter_name == "regex":
47
- return [_ for _ in resources if re.search(str(filter_value), _["name"])]
48
- # return unfiltered list
49
- return resources
50
-
51
-
52
- @click.command(cls=CmemcCommand, name="list")
53
- @click.option("--raw", is_flag=True, help="Outputs raw JSON.")
54
- @click.option(
55
- "--id-only",
56
- is_flag=True,
57
- help="Lists only resource names and no other metadata. "
58
- "This is useful for piping the IDs into other commands.",
59
- )
60
- @click.option(
61
- "--filter",
62
- "filters_",
63
- multiple=True,
64
- type=(str, str),
65
- shell_complete=completion.resource_list_filter,
66
- help=RESOURCE_FILTER_TEXT,
67
- )
68
- @click.pass_obj
69
- def list_command(
70
- app: ApplicationContext, raw: bool, id_only: bool, filters_: tuple[tuple[str, str], ...]
71
- ) -> None:
72
- """List available file resources.
73
-
74
- Outputs a table or a list of dataset resources (files).
75
- """
76
- resources = get_all_resources()
77
- for _ in filters_:
78
- filter_name, filter_value = _
79
- resources = _get_resources_filtered(resources, filter_name, filter_value)
80
- if raw:
81
- app.echo_info_json(resources)
82
- return
83
- if id_only:
84
- for _ in sorted(_["id"] for _ in resources):
85
- app.echo_result(_)
86
- return
87
- # output a user table
88
- table = []
89
- headers = ["ID", "Modified", "Size"]
90
- for _ in resources:
91
- row = [
92
- _["id"],
93
- _["modified"],
94
- _["size"],
95
- ]
96
- table.append(row)
97
- app.echo_info_table(
98
- table,
99
- headers=headers,
100
- sort_column=0,
101
- empty_table_message="No dataset resources found. "
102
- "Use the `dataset create` command to create a new file based dataset.",
103
- )
104
-
105
-
106
- @click.command(cls=CmemcCommand, name="delete")
107
- @click.argument("resource_ids", nargs=-1, type=click.STRING, shell_complete=completion.resource_ids)
108
- @click.option("--force", is_flag=True, help="Delete resource even if in use by a task.")
109
- @click.option(
110
- "-a",
111
- "--all",
112
- "all_",
113
- is_flag=True,
114
- help="Delete all resources. " "This is a dangerous option, so use it with care.",
115
- )
116
- @click.option(
117
- "--filter",
118
- "filters_",
119
- multiple=True,
120
- type=(str, str),
121
- shell_complete=completion.resource_list_filter,
122
- help=RESOURCE_FILTER_TEXT,
123
- )
124
- @click.pass_obj
125
- def delete_command(
126
- app: ApplicationContext,
127
- resource_ids: tuple[str, ...],
128
- force: bool,
129
- all_: bool,
130
- filters_: tuple[tuple[str, str], ...],
131
- ) -> None:
132
- """Delete file resources.
133
-
134
- There are three selection mechanisms: with specific IDs, only those
135
- specified resources will be deleted; by using --filter, resources based
136
- on the filter type and value will be deleted; using --all will delete
137
- all resources.
138
- """
139
- if resource_ids == () and not all_ and filters_ == ():
140
- raise UsageError(
141
- "Either specify at least one resource ID or use the --all or "
142
- "--filter options to specify resources for deletion."
143
- )
144
-
145
- resources = get_all_resources()
146
- if len(resource_ids) > 0:
147
- for resource_id in resource_ids:
148
- if resource_id not in [_["id"] for _ in resources]:
149
- raise ClickException(f"Resource {resource_id} not available.")
150
- # "filter" by id
151
- resources = _get_resources_filtered(resources, "ids", resource_ids)
152
- for _ in filters_:
153
- resources = _get_resources_filtered(resources, _[0], _[1])
154
-
155
- # avoid double removal as well as sort IDs
156
- processed_ids = sorted({_["id"] for _ in resources}, key=lambda v: v.lower())
157
- count = len(processed_ids)
158
- for current, resource_id in enumerate(processed_ids, start=1):
159
- current_string = str(current).zfill(len(str(count)))
160
- app.echo_info(f"Delete resource {current_string}/{count}: {resource_id} ... ", nl=False)
161
- project_id, resource_local_id = split_task_id(resource_id)
162
- usage = get_resource_usage_data(project_id, resource_local_id)
163
- if len(usage) > 0:
164
- app.echo_error(f"in use by {len(usage)} task(s)", nl=False)
165
- if force:
166
- app.echo_info(" ... ", nl=False)
167
- else:
168
- app.echo_info("")
169
- continue
170
- delete_resource(project_name=project_id, resource_name=resource_local_id)
171
- app.echo_success("deleted")
172
-
173
-
174
- @click.command(cls=CmemcCommand, name="inspect")
175
- @click.argument("resource_id", type=click.STRING, shell_complete=completion.resource_ids)
176
- @click.option("--raw", is_flag=True, help="Outputs raw JSON.")
177
- @click.pass_obj
178
- def inspect_command(app: ApplicationContext, resource_id: str, raw: bool) -> None:
179
- """Display all metadata of a file resource."""
180
- project_id, resource_id = split_task_id(resource_id)
181
- resource_data = get_resource_metadata(project_id, resource_id)
182
- if raw:
183
- app.echo_info_json(resource_data)
184
- else:
185
- table = struct_to_table(resource_data)
186
- app.echo_info_table(table, headers=["Key", "Value"], sort_column=0)
187
-
188
-
189
- @click.command(cls=CmemcCommand, name="usage")
190
- @click.argument("resource_id", type=click.STRING, shell_complete=completion.resource_ids)
191
- @click.option("--raw", is_flag=True, help="Outputs raw JSON.")
192
- @click.pass_obj
193
- def usage_command(app: ApplicationContext, resource_id: str, raw: bool) -> None:
194
- """Display all usage data of a file resource."""
195
- project_id, resource_id = split_task_id(resource_id)
196
- usage = get_resource_usage_data(project_id, resource_id)
197
- if raw:
198
- app.echo_info_json(usage)
199
- return
200
- # output a user table
201
- table = []
202
- headers = ["Task ID", "Type", "Label"]
203
- for _ in usage:
204
- row = [project_id + ":" + _["id"], _["taskType"], _["label"]]
205
- table.append(row)
206
- app.echo_info_table(table, headers=headers, sort_column=2)
207
-
208
-
209
- @click.group(cls=CmemcGroup)
210
- def resource() -> CmemcGroup: # type: ignore[empty-body]
211
- """List, inspect or delete dataset file resources.
212
-
213
- File resources are identified by their paths and project IDs.
214
- """
215
-
216
-
217
- resource.add_command(list_command)
218
- resource.add_command(delete_command)
219
- resource.add_command(inspect_command)
220
- resource.add_command(usage_command)