tabsdata-cli 2.0.0__cp312-abi3-win_amd64.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.
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/__init__.py +5 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/_registry.py +78 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/assets/manifest/BANNER +5 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/assets/manifest/LICENSE +3 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/assets/manifest/README-PyPi.md +8 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/assets/manifest/RELEASE-NOTES +1 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/assets/manifest/THIRD-PARTY +3 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/assets/manifest/VERSION +1 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/cli_utils.py +993 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/shell.py +390 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/__init__.py +3 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/auth_group.py +197 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/cli.py +508 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/collection_group.py +458 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/config_utils.py +93 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/connection_group.py +159 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/examples_group.py +206 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/execution_utils.py +429 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/fn_group.py +1109 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/fnrun_group.py +285 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/group_group.py +184 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/metrics_group.py +323 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/permission_group.py +259 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/plan_group.py +324 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/project_group.py +170 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/role_group.py +630 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/settings_group.py +344 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/table_group.py +600 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/trigger_group.py +338 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/trx_group.py +329 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/user_group.py +200 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/td/worker_group.py +185 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/cli/template.py +781 -0
- tabsdata_cli-2.0.0.data/purelib/tabsdatak/py.typed +0 -0
- tabsdata_cli-2.0.0.dist-info/METADATA +39 -0
- tabsdata_cli-2.0.0.dist-info/RECORD +39 -0
- tabsdata_cli-2.0.0.dist-info/WHEEL +5 -0
- tabsdata_cli-2.0.0.dist-info/licenses/src/main/python/tabsdatak/cli/assets/manifest/LICENSE +3 -0
- tabsdata_cli-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2026 Tabsdata Inc.
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
import rich_click as click
|
|
7
|
+
|
|
8
|
+
from tabsdatak.cli._registry import cli_command
|
|
9
|
+
from tabsdatak.cli.cli_utils import (
|
|
10
|
+
DISABLED,
|
|
11
|
+
ENABLED,
|
|
12
|
+
OPTION_HINTS,
|
|
13
|
+
OPTION_PROMPT,
|
|
14
|
+
OPTION_SERVER,
|
|
15
|
+
PIN_COLLECTION,
|
|
16
|
+
PIN_PROJECT,
|
|
17
|
+
SERVER_URL_DEFAULTS_HELP,
|
|
18
|
+
clear_current_cli_option,
|
|
19
|
+
cli_option_enabled,
|
|
20
|
+
configured_server,
|
|
21
|
+
format_option,
|
|
22
|
+
get_current_cli_option,
|
|
23
|
+
get_pin,
|
|
24
|
+
hint_common_solutions,
|
|
25
|
+
render,
|
|
26
|
+
set_cli_option_enabled,
|
|
27
|
+
set_current_cli_option,
|
|
28
|
+
set_pin,
|
|
29
|
+
store_cli_options,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
_NOTHING_TO_SET = (
|
|
33
|
+
"Nothing to set. Specify at least one setting: --hints true|false, "
|
|
34
|
+
"--prompt true|false, --server SERVER, --proj PROJECT and/or "
|
|
35
|
+
"--coll COLLECTION."
|
|
36
|
+
)
|
|
37
|
+
_NOTHING_TO_UNSET = (
|
|
38
|
+
"Nothing to unset. Specify at least one setting: --hints, --prompt, "
|
|
39
|
+
"--server, --proj and/or --coll -- or --all for every one of them."
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
_TRUE = "true"
|
|
43
|
+
_FALSE = "false"
|
|
44
|
+
# The on/off settings take the value explicitly, so a command reads as what it
|
|
45
|
+
# leaves behind; both default to true, which is what `tdk unset` restores. The
|
|
46
|
+
# same two words render them in `tdk settings`.
|
|
47
|
+
_BOOL = click.Choice((_TRUE, _FALSE))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@cli_command
|
|
51
|
+
@click.command("set")
|
|
52
|
+
@click.option(
|
|
53
|
+
"--hints",
|
|
54
|
+
type=_BOOL,
|
|
55
|
+
help="Show the hints the CLI adds to errors. Default: true.",
|
|
56
|
+
)
|
|
57
|
+
@click.option(
|
|
58
|
+
"--prompt",
|
|
59
|
+
type=_BOOL,
|
|
60
|
+
help=(
|
|
61
|
+
"Prompt for a value a command needs but was not given. Default: true; "
|
|
62
|
+
"'tdk set --prompt false' is the standing form of the root "
|
|
63
|
+
"'--no-prompt' flag."
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
@click.option(
|
|
67
|
+
"--server",
|
|
68
|
+
"url",
|
|
69
|
+
metavar="SERVER",
|
|
70
|
+
help=(
|
|
71
|
+
"URL of the Tabsdata Server 'tdk login' uses without '--server'. "
|
|
72
|
+
+ SERVER_URL_DEFAULTS_HELP
|
|
73
|
+
),
|
|
74
|
+
)
|
|
75
|
+
@click.option(
|
|
76
|
+
"--proj",
|
|
77
|
+
"-P",
|
|
78
|
+
"project",
|
|
79
|
+
help="Project to pin as the default of project-scoped commands.",
|
|
80
|
+
)
|
|
81
|
+
@click.option(
|
|
82
|
+
"--coll",
|
|
83
|
+
"-c",
|
|
84
|
+
"collection",
|
|
85
|
+
help="Collection to pin (requires a pinned project).",
|
|
86
|
+
)
|
|
87
|
+
@click.pass_context
|
|
88
|
+
def set_setting(
|
|
89
|
+
ctx: click.Context,
|
|
90
|
+
hints: str,
|
|
91
|
+
prompt: str,
|
|
92
|
+
url: str,
|
|
93
|
+
project: str,
|
|
94
|
+
collection: str,
|
|
95
|
+
):
|
|
96
|
+
"""Give a setting a value.
|
|
97
|
+
|
|
98
|
+
Settings are persisted in 'options.json' under the Tabsdata directory
|
|
99
|
+
('~/.tabsdata') and apply to every later invocation; 'tdk unset' drops them
|
|
100
|
+
back to their default and 'tdk settings' shows them. More than one can be
|
|
101
|
+
set at once.
|
|
102
|
+
|
|
103
|
+
Examples:
|
|
104
|
+
tdk set --hints false
|
|
105
|
+
tdk set --prompt false
|
|
106
|
+
tdk set --server http://127.0.0.1:2457
|
|
107
|
+
tdk set --server 127.0.0.1 # http://127.0.0.1:2457
|
|
108
|
+
tdk set --proj sales
|
|
109
|
+
tdk set --proj sales --coll orders
|
|
110
|
+
"""
|
|
111
|
+
if hints is None and prompt is None and not (url or project or collection):
|
|
112
|
+
raise click.UsageError(_NOTHING_TO_SET)
|
|
113
|
+
if hints is not None:
|
|
114
|
+
_set_enabled(ctx, OPTION_HINTS, hints == _TRUE)
|
|
115
|
+
if prompt is not None:
|
|
116
|
+
_set_enabled(ctx, OPTION_PROMPT, prompt == _TRUE)
|
|
117
|
+
if url:
|
|
118
|
+
_set_server(ctx, url)
|
|
119
|
+
if project or collection:
|
|
120
|
+
_pin(ctx, project, collection)
|
|
121
|
+
store_cli_options(ctx)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@cli_command
|
|
125
|
+
@click.command("unset")
|
|
126
|
+
@click.option("--hints", is_flag=True, help="Restore the hints default (true).")
|
|
127
|
+
@click.option(
|
|
128
|
+
"--prompt",
|
|
129
|
+
is_flag=True,
|
|
130
|
+
help="Restore the prompting default (true).",
|
|
131
|
+
)
|
|
132
|
+
@click.option("--server", "url", is_flag=True, help="Clear the configured server.")
|
|
133
|
+
@click.option(
|
|
134
|
+
"--proj",
|
|
135
|
+
"-P",
|
|
136
|
+
"project",
|
|
137
|
+
is_flag=True,
|
|
138
|
+
help=(
|
|
139
|
+
"Unpin the project. Unpins the collection too, since a collection pin "
|
|
140
|
+
"only resolves under a project."
|
|
141
|
+
),
|
|
142
|
+
)
|
|
143
|
+
@click.option("--coll", "-c", "collection", is_flag=True, help="Unpin the collection.")
|
|
144
|
+
@click.option(
|
|
145
|
+
"--all",
|
|
146
|
+
"all_settings",
|
|
147
|
+
is_flag=True,
|
|
148
|
+
help=(
|
|
149
|
+
"Unset every setting: shorthand for all the flags above, leaving every "
|
|
150
|
+
"one of them at its default."
|
|
151
|
+
),
|
|
152
|
+
)
|
|
153
|
+
@click.pass_context
|
|
154
|
+
def unset_setting(
|
|
155
|
+
ctx: click.Context,
|
|
156
|
+
hints: bool,
|
|
157
|
+
prompt: bool,
|
|
158
|
+
url: bool,
|
|
159
|
+
project: bool,
|
|
160
|
+
collection: bool,
|
|
161
|
+
all_settings: bool,
|
|
162
|
+
):
|
|
163
|
+
"""Drop a setting back to its default.
|
|
164
|
+
|
|
165
|
+
The counterpart of 'tdk set': it removes what was stored for every setting
|
|
166
|
+
it is given, so the shipped default applies again. More than one can be
|
|
167
|
+
unset at once.
|
|
168
|
+
|
|
169
|
+
Examples:
|
|
170
|
+
tdk unset --hints
|
|
171
|
+
tdk unset --prompt
|
|
172
|
+
tdk unset --server
|
|
173
|
+
tdk unset --coll # unpin the collection only
|
|
174
|
+
tdk unset --proj # unpins the collection too
|
|
175
|
+
tdk unset --all # every setting
|
|
176
|
+
"""
|
|
177
|
+
if all_settings:
|
|
178
|
+
hints = prompt = url = project = collection = True
|
|
179
|
+
if not (hints or prompt or url or project or collection):
|
|
180
|
+
raise click.UsageError(_NOTHING_TO_UNSET)
|
|
181
|
+
if hints:
|
|
182
|
+
_clear_enabled(ctx, OPTION_HINTS)
|
|
183
|
+
if prompt:
|
|
184
|
+
_clear_enabled(ctx, OPTION_PROMPT)
|
|
185
|
+
if url:
|
|
186
|
+
_unset_server(ctx)
|
|
187
|
+
if project or collection:
|
|
188
|
+
_unpin(ctx, project)
|
|
189
|
+
store_cli_options(ctx)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@cli_command
|
|
193
|
+
@click.command("settings")
|
|
194
|
+
@format_option
|
|
195
|
+
@click.pass_context
|
|
196
|
+
def settings(ctx: click.Context):
|
|
197
|
+
"""Show the current settings.
|
|
198
|
+
|
|
199
|
+
The machine formats mirror what is stored in 'options.json'.
|
|
200
|
+
"""
|
|
201
|
+
hints_enabled = cli_option_enabled(ctx, OPTION_HINTS)
|
|
202
|
+
prompt_enabled = cli_option_enabled(ctx, OPTION_PROMPT)
|
|
203
|
+
current_server = configured_server(ctx)
|
|
204
|
+
project = get_pin(ctx, PIN_PROJECT)
|
|
205
|
+
collection = get_pin(ctx, PIN_COLLECTION)
|
|
206
|
+
|
|
207
|
+
def _table():
|
|
208
|
+
click.echo(f"Hints: {_true_false(hints_enabled)}")
|
|
209
|
+
click.echo(f"Prompt: {_true_false(prompt_enabled)}")
|
|
210
|
+
click.echo(
|
|
211
|
+
f"Server: {current_server if current_server else '(none)'}"
|
|
212
|
+
)
|
|
213
|
+
click.echo(f"Pinned project: {project if project else '(none)'}")
|
|
214
|
+
click.echo(f"Pinned collection: {collection if collection else '(none)'}")
|
|
215
|
+
|
|
216
|
+
render(
|
|
217
|
+
ctx,
|
|
218
|
+
data={
|
|
219
|
+
OPTION_HINTS: _stored(hints_enabled),
|
|
220
|
+
OPTION_PROMPT: _stored(prompt_enabled),
|
|
221
|
+
OPTION_SERVER: current_server,
|
|
222
|
+
"pins": {PIN_PROJECT: project, PIN_COLLECTION: collection},
|
|
223
|
+
},
|
|
224
|
+
table=_table,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
_TOGGLE_MESSAGES = {
|
|
229
|
+
OPTION_HINTS: (
|
|
230
|
+
"Hints enabled. You will now see hints in the CLI.",
|
|
231
|
+
"Hints disabled. You will no longer see hints in the CLI.",
|
|
232
|
+
),
|
|
233
|
+
OPTION_PROMPT: (
|
|
234
|
+
"Prompting enabled. Commands will prompt for missing values.",
|
|
235
|
+
"Prompting disabled. Commands will fail instead of prompting for "
|
|
236
|
+
"missing values.",
|
|
237
|
+
),
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
# Both on/off settings default to true, so unsetting one always lands on true.
|
|
241
|
+
_CLEARED_LABELS = {OPTION_HINTS: "Hints", OPTION_PROMPT: "Prompting"}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _set_enabled(ctx: click.Context, option: str, enabled: bool):
|
|
245
|
+
set_cli_option_enabled(ctx, option, enabled)
|
|
246
|
+
click.echo(_TOGGLE_MESSAGES[option][0 if enabled else 1])
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def _clear_enabled(ctx: click.Context, option: str):
|
|
250
|
+
label = _CLEARED_LABELS[option]
|
|
251
|
+
if get_current_cli_option(ctx, option) is None:
|
|
252
|
+
click.echo(f"{label} was already at its default (true).")
|
|
253
|
+
else:
|
|
254
|
+
clear_current_cli_option(ctx, option)
|
|
255
|
+
click.echo(f"{label} unset, back to its default (true).")
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _set_server(ctx: click.Context, url: str):
|
|
259
|
+
set_current_cli_option(ctx, OPTION_SERVER, url)
|
|
260
|
+
click.echo(f"Server set to {url}. 'tdk login' will use it without '--server'.")
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _unset_server(ctx: click.Context):
|
|
264
|
+
previous = configured_server(ctx)
|
|
265
|
+
clear_current_cli_option(ctx, OPTION_SERVER)
|
|
266
|
+
if previous:
|
|
267
|
+
click.echo(f"Server unset (was {previous}).")
|
|
268
|
+
else:
|
|
269
|
+
click.echo("No server was configured.")
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _pin(ctx: click.Context, project: str, collection: str):
|
|
273
|
+
# A collection only resolves relative to a pinned project -- one being set
|
|
274
|
+
# in this same command, or a pre-existing pin. Fail fast otherwise.
|
|
275
|
+
if collection and not (project or get_pin(ctx, PIN_PROJECT)):
|
|
276
|
+
raise click.ClickException(
|
|
277
|
+
"No project pinned. Pin a project first with 'tdk set --proj <name>' "
|
|
278
|
+
"before pinning a collection."
|
|
279
|
+
)
|
|
280
|
+
try:
|
|
281
|
+
if project:
|
|
282
|
+
previously_pinned = get_pin(ctx, PIN_PROJECT)
|
|
283
|
+
if previously_pinned and previously_pinned != project:
|
|
284
|
+
click.echo(f"Unpinning previously pinned project: {previously_pinned}")
|
|
285
|
+
set_pin(ctx, PIN_PROJECT, project)
|
|
286
|
+
click.echo(f"Pinning project: {project}")
|
|
287
|
+
# Switching to a different project orphans a collection pinned under
|
|
288
|
+
# the old one -- clear it, unless this command also sets a new
|
|
289
|
+
# collection (handled below). Re-pinning the same project keeps it.
|
|
290
|
+
if (
|
|
291
|
+
previously_pinned
|
|
292
|
+
and previously_pinned != project
|
|
293
|
+
and not collection
|
|
294
|
+
and get_pin(ctx, PIN_COLLECTION)
|
|
295
|
+
):
|
|
296
|
+
orphan = get_pin(ctx, PIN_COLLECTION)
|
|
297
|
+
set_pin(ctx, PIN_COLLECTION, None)
|
|
298
|
+
click.echo(
|
|
299
|
+
"Also unpinning collection (it belonged to the previously "
|
|
300
|
+
f"pinned project): {orphan}"
|
|
301
|
+
)
|
|
302
|
+
if collection:
|
|
303
|
+
previously_pinned = get_pin(ctx, PIN_COLLECTION)
|
|
304
|
+
if previously_pinned and previously_pinned != collection:
|
|
305
|
+
click.echo(
|
|
306
|
+
f"Unpinning previously pinned collection: {previously_pinned}"
|
|
307
|
+
)
|
|
308
|
+
set_pin(ctx, PIN_COLLECTION, collection)
|
|
309
|
+
click.echo(f"Pinning collection: {collection}")
|
|
310
|
+
click.echo("Pins updated successfully")
|
|
311
|
+
except Exception as e:
|
|
312
|
+
hint_common_solutions(ctx, e)
|
|
313
|
+
raise click.ClickException(f"Failed to set pins: {e}")
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def _unpin(ctx: click.Context, project: bool):
|
|
317
|
+
try:
|
|
318
|
+
# Clearing the project always cascades to the collection, since a
|
|
319
|
+
# collection only resolves under a project.
|
|
320
|
+
cleared = []
|
|
321
|
+
if project and get_pin(ctx, PIN_PROJECT):
|
|
322
|
+
cleared.append(f"project ({get_pin(ctx, PIN_PROJECT)})")
|
|
323
|
+
if get_pin(ctx, PIN_COLLECTION):
|
|
324
|
+
cleared.append(f"collection ({get_pin(ctx, PIN_COLLECTION)})")
|
|
325
|
+
|
|
326
|
+
if project:
|
|
327
|
+
set_pin(ctx, PIN_PROJECT, None)
|
|
328
|
+
set_pin(ctx, PIN_COLLECTION, None)
|
|
329
|
+
|
|
330
|
+
if cleared:
|
|
331
|
+
click.echo("Unpinned: " + ", ".join(cleared))
|
|
332
|
+
else:
|
|
333
|
+
click.echo("Nothing was pinned.")
|
|
334
|
+
except Exception as e:
|
|
335
|
+
hint_common_solutions(ctx, e)
|
|
336
|
+
raise click.ClickException(f"Failed to unset pins: {e}")
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def _true_false(enabled: bool) -> str:
|
|
340
|
+
return _TRUE if enabled else _FALSE
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def _stored(enabled: bool) -> str:
|
|
344
|
+
return ENABLED if enabled else DISABLED
|