adalab-cli 3.0.0__tar.gz → 3.2.0__tar.gz
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.
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/PKG-INFO +3 -2
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/app.py +17 -1
- adalab_cli-3.2.0/adalab_cli/cli/completion_tree.py +143 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/databases_commands.py +1 -1
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/gallery_commands.py +60 -8
- adalab_cli-3.2.0/adalab_cli/cli/logs_commands.py +337 -0
- adalab_cli-3.2.0/adalab_cli/cli/pictures_commands.py +85 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/schedule_commands.py +91 -2
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/user_commands.py +1 -1
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/pyproject.toml +18 -22
- adalab_cli-3.0.0/adalab_cli/cli/completion_tree.py +0 -67
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/README.md +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/__init__.py +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/__init__.py +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/authentication_flows.py +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/factory.py +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/interactive.py +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/kernel_commands.py +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/logger.py +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/login_commands.py +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/oci_commands.py +0 -0
- {adalab_cli-3.0.0 → adalab_cli-3.2.0}/adalab_cli/cli/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: adalab-cli
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.2.0
|
|
4
4
|
Summary: The CLI app to interact with AdaLab.
|
|
5
5
|
Home-page: https://adamatics.com
|
|
6
6
|
Author: Adamatics ApS
|
|
@@ -16,8 +16,9 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
18
|
Classifier: Typing :: Typed
|
|
19
|
-
Requires-Dist: adalib (>=
|
|
19
|
+
Requires-Dist: adalib (>=7.2.0)
|
|
20
20
|
Requires-Dist: adalib-auth (>=1.2.2)
|
|
21
|
+
Requires-Dist: ascii-magic (>=2.3.0)
|
|
21
22
|
Requires-Dist: loguru (>=0.7.2)
|
|
22
23
|
Requires-Dist: prompt-toolkit (>=3.0.47)
|
|
23
24
|
Requires-Dist: sh (>=2.0.6)
|
|
@@ -28,13 +28,15 @@ from .gallery_commands import gallery_app
|
|
|
28
28
|
from .interactive import interactive_mode
|
|
29
29
|
from .logger import Logger
|
|
30
30
|
from .login_commands import load_config
|
|
31
|
+
from .logs_commands import logs_app
|
|
32
|
+
from .pictures_commands import pictures_app
|
|
31
33
|
from .schedule_commands import schedules_app
|
|
32
34
|
from .user_commands import user_app
|
|
33
35
|
|
|
34
36
|
app = typer.Typer(no_args_is_help=False)
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
@app.callback(
|
|
39
|
+
@app.callback(invoke_without_command=True, no_args_is_help=True)
|
|
38
40
|
def main(
|
|
39
41
|
token: str = typer.Option(None, help="User token for authentication"),
|
|
40
42
|
adalab_url: str = typer.Option(None, help="URL of the AdaLab server"),
|
|
@@ -189,3 +191,17 @@ app.add_typer(
|
|
|
189
191
|
help="Commands for interacting with schedules.",
|
|
190
192
|
no_args_is_help=True,
|
|
191
193
|
)
|
|
194
|
+
|
|
195
|
+
app.add_typer(
|
|
196
|
+
logs_app,
|
|
197
|
+
name="logs",
|
|
198
|
+
help="Commands for fetching AdaLab logs.",
|
|
199
|
+
no_args_is_help=True,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
app.add_typer(
|
|
203
|
+
pictures_app,
|
|
204
|
+
name="pictures",
|
|
205
|
+
help="Commands for handling pictures in AdaLab.",
|
|
206
|
+
no_args_is_help=True,
|
|
207
|
+
)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""Map of the CLI commands and subcommands for the CLI completion tree."""
|
|
2
|
+
|
|
3
|
+
completion_tree = {
|
|
4
|
+
"cards": {
|
|
5
|
+
"toggle-review": {"help": None, "exit": None},
|
|
6
|
+
"expose-card": {"help": None, "exit": None},
|
|
7
|
+
"get-card": {"help": None, "--incl-content": None, "exit": None},
|
|
8
|
+
"hide-card": {"help": None, "exit": None},
|
|
9
|
+
"list-cards": {
|
|
10
|
+
"all": {
|
|
11
|
+
"--search-phrase": None,
|
|
12
|
+
"--group-category": None,
|
|
13
|
+
"--only-hidden": None,
|
|
14
|
+
"--only-exposed": None,
|
|
15
|
+
"help": None,
|
|
16
|
+
"exit": None,
|
|
17
|
+
},
|
|
18
|
+
"notebook": {
|
|
19
|
+
"--search-phrase": None,
|
|
20
|
+
"--group-category": None,
|
|
21
|
+
"--only-hidden": None,
|
|
22
|
+
"--only-exposed": None,
|
|
23
|
+
"help": None,
|
|
24
|
+
"exit": None,
|
|
25
|
+
},
|
|
26
|
+
"voila": {
|
|
27
|
+
"--search-phrase": None,
|
|
28
|
+
"--group-category": None,
|
|
29
|
+
"--only-hidden": None,
|
|
30
|
+
"--only-exposed": None,
|
|
31
|
+
"help": None,
|
|
32
|
+
"exit": None,
|
|
33
|
+
},
|
|
34
|
+
"url": {
|
|
35
|
+
"--search-phrase": None,
|
|
36
|
+
"--group-category": None,
|
|
37
|
+
"--url-subtype": None,
|
|
38
|
+
"--only-hidden": None,
|
|
39
|
+
"--only-exposed": None,
|
|
40
|
+
"help": None,
|
|
41
|
+
"exit": None,
|
|
42
|
+
},
|
|
43
|
+
"group": {
|
|
44
|
+
"--search-phrase": None,
|
|
45
|
+
"--group-category": None,
|
|
46
|
+
"--only-hidden": None,
|
|
47
|
+
"--only-exposed": None,
|
|
48
|
+
"help": None,
|
|
49
|
+
"exit": None,
|
|
50
|
+
},
|
|
51
|
+
"help": None,
|
|
52
|
+
"exit": None,
|
|
53
|
+
},
|
|
54
|
+
"help": None,
|
|
55
|
+
"exit": None,
|
|
56
|
+
},
|
|
57
|
+
"databases": {
|
|
58
|
+
"list-databases": {"--no-pretty": None, "help": None},
|
|
59
|
+
"list-datasets": {"--no-pretty": None, "--return-sql": None, "help": None},
|
|
60
|
+
"list-tables": {"--no-pretty": None, "help": None},
|
|
61
|
+
"view-dataset": {"--head": None, "--no-pretty": None, "help": None},
|
|
62
|
+
"help": None,
|
|
63
|
+
"exit": None,
|
|
64
|
+
},
|
|
65
|
+
"logs": {
|
|
66
|
+
"app": {
|
|
67
|
+
"--container": None,
|
|
68
|
+
"--container-index": None,
|
|
69
|
+
"--from": None,
|
|
70
|
+
"--source": None,
|
|
71
|
+
"--to": None,
|
|
72
|
+
"help": None,
|
|
73
|
+
"exit": None,
|
|
74
|
+
},
|
|
75
|
+
"build": {"--source": None, "help": None},
|
|
76
|
+
"lab": {"--from": None, "--source": None, "--to": None, "help": None},
|
|
77
|
+
"publish": {"--source": None, "help": None},
|
|
78
|
+
"run": {"help": None},
|
|
79
|
+
"help": None,
|
|
80
|
+
"exit": None,
|
|
81
|
+
},
|
|
82
|
+
"schedules": {
|
|
83
|
+
"list-schedules": {
|
|
84
|
+
"--only-active": None,
|
|
85
|
+
"--search-phrase": None,
|
|
86
|
+
"help": None,
|
|
87
|
+
"exit": None,
|
|
88
|
+
},
|
|
89
|
+
"get-schedule": {"--incl-content": None, "help": None},
|
|
90
|
+
"create-schedule": {
|
|
91
|
+
"--schedule": None,
|
|
92
|
+
"--pool": None,
|
|
93
|
+
"--active": None,
|
|
94
|
+
"--concurrent": None,
|
|
95
|
+
"--cleanup": None,
|
|
96
|
+
"--timeout": None,
|
|
97
|
+
"help": None,
|
|
98
|
+
"exit": None,
|
|
99
|
+
},
|
|
100
|
+
"delete-run": {"help": None, "exit": None},
|
|
101
|
+
"delete-schedule": {"help": None, "exit": None},
|
|
102
|
+
"start-run": {
|
|
103
|
+
"--cleanup": None,
|
|
104
|
+
"--pool": None,
|
|
105
|
+
"--timeout": None,
|
|
106
|
+
"help": None,
|
|
107
|
+
"exit": None,
|
|
108
|
+
},
|
|
109
|
+
"stop-run": {"help": None, "exit": None},
|
|
110
|
+
"update-schedule": {
|
|
111
|
+
"--schedule": None,
|
|
112
|
+
"--pool": None,
|
|
113
|
+
"--active": None,
|
|
114
|
+
"--concurrent": None,
|
|
115
|
+
"--cleanup": None,
|
|
116
|
+
"--timeout": None,
|
|
117
|
+
"help": None,
|
|
118
|
+
"exit": None,
|
|
119
|
+
},
|
|
120
|
+
"help": None,
|
|
121
|
+
"exit": None,
|
|
122
|
+
},
|
|
123
|
+
"user": {
|
|
124
|
+
"whoami": {
|
|
125
|
+
"--full-information": None,
|
|
126
|
+
"--with-notifications": None,
|
|
127
|
+
"help": None,
|
|
128
|
+
"exit": None,
|
|
129
|
+
},
|
|
130
|
+
"help": None,
|
|
131
|
+
"exit": None,
|
|
132
|
+
},
|
|
133
|
+
"pictures": {
|
|
134
|
+
"show": {"help": None, "exit": None},
|
|
135
|
+
"download": {"--output-path": None, "help": None, "exit": None},
|
|
136
|
+
"create": {"--path": None, "--url": None, "help": None, "exit": None},
|
|
137
|
+
"help": None,
|
|
138
|
+
"exit": None,
|
|
139
|
+
},
|
|
140
|
+
"version": None,
|
|
141
|
+
"help": None,
|
|
142
|
+
"exit": None,
|
|
143
|
+
}
|
|
@@ -204,7 +204,7 @@ def list_tables(
|
|
|
204
204
|
utils.print_dataframe(dataframe=tables, pretty=pretty, title=f"Tables in database {db_index}")
|
|
205
205
|
|
|
206
206
|
|
|
207
|
-
@db_app.callback(
|
|
207
|
+
@db_app.callback(invoke_without_command=True)
|
|
208
208
|
def main(
|
|
209
209
|
interactive: bool = typer.Option(
|
|
210
210
|
False, "-i", "--interactive", help="Activate interactive mode"
|
|
@@ -38,26 +38,65 @@ def gallery_list_cards(
|
|
|
38
38
|
typer.Argument(
|
|
39
39
|
help="The type of cards to list. " "Choose from [all, notebook, voila, url, group].",
|
|
40
40
|
),
|
|
41
|
-
]
|
|
41
|
+
] = "all",
|
|
42
|
+
head: Annotated[int | None, typer.Option(help="Number of cards to display.")] = None,
|
|
43
|
+
url_subtype: Annotated[
|
|
44
|
+
str,
|
|
45
|
+
typer.Option(
|
|
46
|
+
help="The URL subtype to filter by.",
|
|
47
|
+
),
|
|
48
|
+
] = "all",
|
|
49
|
+
search_phrase: Annotated[str, typer.Option(help="Search phrase to filter cards by.")] = None,
|
|
50
|
+
group_category: Annotated[str, typer.Option(help="Group category to filter by.")] = None,
|
|
51
|
+
only_hidden: Annotated[bool, typer.Option(help="Show only hidden cards.")] = False,
|
|
52
|
+
only_exposed: Annotated[bool, typer.Option(help="Show only exposed cards.")] = False,
|
|
42
53
|
):
|
|
43
54
|
"""
|
|
44
|
-
Prints all cards from the Gallery with the type CARD_TYPE.
|
|
55
|
+
Prints all cards from the Gallery with the type CARD_TYPE. Optionally filter by URL_SUBTYPE
|
|
56
|
+
for URL cards.
|
|
45
57
|
"""
|
|
46
58
|
try:
|
|
47
59
|
with Progress(
|
|
48
60
|
SpinnerColumn(), TextColumn("[progress.description]{task.description}"), transient=True
|
|
49
61
|
) as progress:
|
|
50
62
|
progress.add_task(description="Fetching data...", total=None)
|
|
51
|
-
cards = get_cards(
|
|
63
|
+
cards = get_cards(
|
|
64
|
+
card_type=card_type,
|
|
65
|
+
url_subtype=url_subtype,
|
|
66
|
+
head=head,
|
|
67
|
+
search_phrase=search_phrase,
|
|
68
|
+
group_category=group_category,
|
|
69
|
+
only_hidden=only_hidden,
|
|
70
|
+
only_exposed=only_exposed,
|
|
71
|
+
)
|
|
52
72
|
except Exception as e:
|
|
53
73
|
logger.error(f"Error: {str(e)}")
|
|
54
74
|
sys.exit()
|
|
55
75
|
|
|
56
76
|
rich_print(f"Card type: {card_type} ({len(cards)})")
|
|
57
77
|
|
|
58
|
-
|
|
78
|
+
cols = (
|
|
79
|
+
[("Card id", 0), ("Card type", 1)]
|
|
80
|
+
+ ([("URL type", 2)] if card_type == "url" else [])
|
|
81
|
+
+ [("Reviewed", 3), ("Exposed", 4), ("Card name", 5)]
|
|
82
|
+
+ ([("Cards in Group", 6)] if card_type == "group" else [])
|
|
83
|
+
+ [("Card author", 7)]
|
|
84
|
+
)
|
|
85
|
+
table = Table(
|
|
86
|
+
*[x[0] for x in cols],
|
|
87
|
+
title="Cards",
|
|
88
|
+
)
|
|
59
89
|
for card in cards:
|
|
60
|
-
table.add_row(
|
|
90
|
+
table.add_row(
|
|
91
|
+
*[
|
|
92
|
+
(
|
|
93
|
+
str(card[ind])
|
|
94
|
+
if _cname not in ["Reviewed", "Exposed"]
|
|
95
|
+
else ("✅" if card[ind] else "❌")
|
|
96
|
+
)
|
|
97
|
+
for _cname, ind in cols
|
|
98
|
+
]
|
|
99
|
+
)
|
|
61
100
|
console = Console()
|
|
62
101
|
console.print(table)
|
|
63
102
|
|
|
@@ -70,6 +109,9 @@ def gallery_get_card(
|
|
|
70
109
|
help="The ID of the card you want to retrieve.",
|
|
71
110
|
),
|
|
72
111
|
],
|
|
112
|
+
incl_content: Annotated[
|
|
113
|
+
bool, typer.Option(help="Include card content in the output.")
|
|
114
|
+
] = False,
|
|
73
115
|
):
|
|
74
116
|
"""
|
|
75
117
|
Gets the contents of a card identified by CARD_ID.
|
|
@@ -81,12 +123,22 @@ def gallery_get_card(
|
|
|
81
123
|
transient=True,
|
|
82
124
|
) as progress:
|
|
83
125
|
progress.add_task(description="Fetching data...", total=None)
|
|
84
|
-
card = get_card_contents(card_id=card_id)
|
|
126
|
+
card = get_card_contents(card_id=card_id, incl_content=incl_content)
|
|
85
127
|
except Exception:
|
|
86
128
|
rich_print(f"Card {card_id} [bold red]failed[/bold red] to retrieve.")
|
|
87
129
|
sys.exit(1)
|
|
88
130
|
|
|
89
|
-
|
|
131
|
+
console = Console()
|
|
132
|
+
|
|
133
|
+
table = Table(title="Card Details")
|
|
134
|
+
table.add_column("Property", style="cyan", no_wrap=True)
|
|
135
|
+
table.add_column("Value", style="magenta")
|
|
136
|
+
for key, value in card.items():
|
|
137
|
+
if isinstance(value, bool):
|
|
138
|
+
value = "✅" if value else "❌"
|
|
139
|
+
table.add_row(key, str(value) if value != [] else "[dim]Empty List[/dim]")
|
|
140
|
+
|
|
141
|
+
console.print(table)
|
|
90
142
|
|
|
91
143
|
|
|
92
144
|
@gallery_app.command("expose-card", no_args_is_help=True)
|
|
@@ -149,7 +201,7 @@ def gallery_toggle_card_review(
|
|
|
149
201
|
rich_print(f"Card {card_id} review status [bold green]updated[/bold green] successfully.")
|
|
150
202
|
|
|
151
203
|
|
|
152
|
-
@gallery_app.callback(
|
|
204
|
+
@gallery_app.callback(invoke_without_command=True)
|
|
153
205
|
def main(
|
|
154
206
|
interactive: bool = typer.Option(
|
|
155
207
|
False, "-i", "--interactive", help="Activate interactive mode"
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"""Logs command group for the adalib CLI.
|
|
2
|
+
|
|
3
|
+
This submodule encompasses commands related to AdaLab logs
|
|
4
|
+
in the adalib CLI. It uses Typer for command line interface implementation,
|
|
5
|
+
allowing the user to retrieve different types of logs.
|
|
6
|
+
|
|
7
|
+
Functions:
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
import typer
|
|
14
|
+
from adalib.apps import get_app, get_app_logs
|
|
15
|
+
from adalib.harbor import get_publish_logs
|
|
16
|
+
from adalib.lab import get_build_logs, get_lab_logs
|
|
17
|
+
from adalib.schedules import get_run_logs
|
|
18
|
+
from loguru import logger
|
|
19
|
+
from prompt_toolkit.completion import NestedCompleter
|
|
20
|
+
from rich import print as rich_print
|
|
21
|
+
from rich.console import Console
|
|
22
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
23
|
+
from rich.table import Table
|
|
24
|
+
from typing_extensions import Annotated
|
|
25
|
+
|
|
26
|
+
from .completion_tree import completion_tree
|
|
27
|
+
from .factory import check_authentication
|
|
28
|
+
from .interactive import interactive_mode
|
|
29
|
+
|
|
30
|
+
logs_app = typer.Typer()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@logs_app.command("app", no_args_is_help=True)
|
|
34
|
+
def logs_get_app_logs(
|
|
35
|
+
app_id: Annotated[
|
|
36
|
+
str,
|
|
37
|
+
typer.Argument(
|
|
38
|
+
help="The ID of the app to fetch logs for.",
|
|
39
|
+
),
|
|
40
|
+
],
|
|
41
|
+
container: Annotated[
|
|
42
|
+
str,
|
|
43
|
+
typer.Option(
|
|
44
|
+
"-c",
|
|
45
|
+
"--container",
|
|
46
|
+
help="The name of the container whose logs to fetch.",
|
|
47
|
+
),
|
|
48
|
+
] = "",
|
|
49
|
+
container_idx: Annotated[
|
|
50
|
+
int,
|
|
51
|
+
typer.Option(
|
|
52
|
+
"-i",
|
|
53
|
+
"--container-index",
|
|
54
|
+
help="The index of the container whose logs to fetch.",
|
|
55
|
+
),
|
|
56
|
+
] = 0,
|
|
57
|
+
from_date: Annotated[
|
|
58
|
+
str,
|
|
59
|
+
typer.Option(
|
|
60
|
+
"-f",
|
|
61
|
+
"--from",
|
|
62
|
+
help="The start date for the logs, in ISO format (YYYY-MM-DDTHH:mm:ss+HH:mm).",
|
|
63
|
+
),
|
|
64
|
+
] = "",
|
|
65
|
+
source: Annotated[
|
|
66
|
+
str,
|
|
67
|
+
typer.Option(
|
|
68
|
+
"-s",
|
|
69
|
+
"--source",
|
|
70
|
+
help="The source of the logs. One of 'container' or 'system'.",
|
|
71
|
+
),
|
|
72
|
+
] = "container",
|
|
73
|
+
to_date: Annotated[
|
|
74
|
+
str,
|
|
75
|
+
typer.Option(
|
|
76
|
+
"-t",
|
|
77
|
+
"--to",
|
|
78
|
+
help="The end date for the logs, in ISO format (YYYY-MM-DDTHH:mm:ss+HH:mm).",
|
|
79
|
+
),
|
|
80
|
+
] = "",
|
|
81
|
+
):
|
|
82
|
+
"""
|
|
83
|
+
Fetches logs for the app with the given ID.
|
|
84
|
+
"""
|
|
85
|
+
try:
|
|
86
|
+
with Progress(
|
|
87
|
+
SpinnerColumn(),
|
|
88
|
+
TextColumn("[progress.description]{task.description}"),
|
|
89
|
+
transient=True,
|
|
90
|
+
) as progress:
|
|
91
|
+
progress.add_task(description="Fetching data...", total=None)
|
|
92
|
+
tmp = get_app(app_id)
|
|
93
|
+
app_name = tmp["name"]
|
|
94
|
+
logs = get_app_logs(
|
|
95
|
+
app_id,
|
|
96
|
+
container=container,
|
|
97
|
+
container_idx=container_idx,
|
|
98
|
+
from_date=from_date,
|
|
99
|
+
source=source,
|
|
100
|
+
to_date=to_date,
|
|
101
|
+
)
|
|
102
|
+
except Exception as e:
|
|
103
|
+
logger.error(f"Error: {str(e)}")
|
|
104
|
+
sys.exit()
|
|
105
|
+
|
|
106
|
+
rich_print(f"{source.capitalize()} logs for app: {app_name} ({len(logs)})")
|
|
107
|
+
|
|
108
|
+
table = Table("Timestamp", "Log message", title="Logs")
|
|
109
|
+
for log in logs:
|
|
110
|
+
table.add_row(log["time"], log["message"])
|
|
111
|
+
|
|
112
|
+
console = Console()
|
|
113
|
+
console.print(table)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@logs_app.command("build", no_args_is_help=True)
|
|
117
|
+
def logs_get_build_logs(
|
|
118
|
+
build_id: Annotated[
|
|
119
|
+
int,
|
|
120
|
+
typer.Argument(
|
|
121
|
+
help="The ID of the build process to fetch logs for.",
|
|
122
|
+
),
|
|
123
|
+
],
|
|
124
|
+
source: Annotated[
|
|
125
|
+
str,
|
|
126
|
+
typer.Option(
|
|
127
|
+
"-s",
|
|
128
|
+
"--source",
|
|
129
|
+
help="The source of the logs. One of 'build' or 'system'.",
|
|
130
|
+
),
|
|
131
|
+
] = "build",
|
|
132
|
+
):
|
|
133
|
+
"""
|
|
134
|
+
Fetches logs for the build with the given ID.
|
|
135
|
+
"""
|
|
136
|
+
try:
|
|
137
|
+
with Progress(
|
|
138
|
+
SpinnerColumn(),
|
|
139
|
+
TextColumn("[progress.description]{task.description}"),
|
|
140
|
+
transient=True,
|
|
141
|
+
) as progress:
|
|
142
|
+
progress.add_task(description="Fetching data...", total=None)
|
|
143
|
+
logs = get_build_logs(
|
|
144
|
+
build_id=build_id,
|
|
145
|
+
source=source,
|
|
146
|
+
)
|
|
147
|
+
except Exception as e:
|
|
148
|
+
logger.error(f"Error: {str(e)}")
|
|
149
|
+
sys.exit()
|
|
150
|
+
|
|
151
|
+
rich_print(f"{source.capitalize()} logs for build process: {build_id} ({len(logs)})")
|
|
152
|
+
|
|
153
|
+
if len(logs[0].keys()) == 2:
|
|
154
|
+
table = Table("Timestamp", "Log message", title="Logs")
|
|
155
|
+
for log in logs:
|
|
156
|
+
table.add_row(log["time"], log["message"])
|
|
157
|
+
else:
|
|
158
|
+
table = Table("Timestamp", "Input", "Output", title="Logs")
|
|
159
|
+
for log in logs:
|
|
160
|
+
table.add_row(log["time"], log["input"], log["output"])
|
|
161
|
+
|
|
162
|
+
console = Console()
|
|
163
|
+
console.print(table)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@logs_app.command("lab", no_args_is_help=True)
|
|
167
|
+
def logs_get_lab_logs(
|
|
168
|
+
from_date: Annotated[
|
|
169
|
+
str,
|
|
170
|
+
typer.Option(
|
|
171
|
+
"-f",
|
|
172
|
+
"--from",
|
|
173
|
+
help="The start date for the logs, in ISO format (YYYY-MM-DDTHH:mm:ss+HH:mm).",
|
|
174
|
+
),
|
|
175
|
+
] = "",
|
|
176
|
+
source: Annotated[
|
|
177
|
+
str,
|
|
178
|
+
typer.Option(
|
|
179
|
+
"-s",
|
|
180
|
+
"--source",
|
|
181
|
+
help="The source of the logs. One of 'user' or 'system'.",
|
|
182
|
+
),
|
|
183
|
+
] = "user",
|
|
184
|
+
to_date: Annotated[
|
|
185
|
+
str,
|
|
186
|
+
typer.Option(
|
|
187
|
+
"-t",
|
|
188
|
+
"--to",
|
|
189
|
+
help="The end date for the logs, in ISO format (YYYY-MM-DDTHH:mm:ss+HH:mm).",
|
|
190
|
+
),
|
|
191
|
+
] = "",
|
|
192
|
+
):
|
|
193
|
+
"""
|
|
194
|
+
Fetches logs for the user's Lab instance.
|
|
195
|
+
"""
|
|
196
|
+
try:
|
|
197
|
+
with Progress(
|
|
198
|
+
SpinnerColumn(),
|
|
199
|
+
TextColumn("[progress.description]{task.description}"),
|
|
200
|
+
transient=True,
|
|
201
|
+
) as progress:
|
|
202
|
+
progress.add_task(description="Fetching data...", total=None)
|
|
203
|
+
logs = get_lab_logs(
|
|
204
|
+
from_date=from_date,
|
|
205
|
+
source=source,
|
|
206
|
+
to_date=to_date,
|
|
207
|
+
)
|
|
208
|
+
except Exception as e:
|
|
209
|
+
logger.error(f"Error: {str(e)}")
|
|
210
|
+
sys.exit()
|
|
211
|
+
|
|
212
|
+
rich_print(f"{source.capitalize()} Lab logs ({len(logs)})")
|
|
213
|
+
|
|
214
|
+
table = Table("Timestamp", "Log message", title="Logs")
|
|
215
|
+
for log in logs:
|
|
216
|
+
table.add_row(log["time"], log["message"])
|
|
217
|
+
|
|
218
|
+
console = Console()
|
|
219
|
+
console.print(table)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@logs_app.command("publish", no_args_is_help=True)
|
|
223
|
+
def logs_get_publish_logs(
|
|
224
|
+
metadata_id: Annotated[
|
|
225
|
+
int,
|
|
226
|
+
typer.Argument(
|
|
227
|
+
help="The ID of the publish process to fetch logs for.",
|
|
228
|
+
),
|
|
229
|
+
],
|
|
230
|
+
source: Annotated[
|
|
231
|
+
str,
|
|
232
|
+
typer.Option(
|
|
233
|
+
"-s",
|
|
234
|
+
"--source",
|
|
235
|
+
help="The source of the logs. One of 'publish' or 'system'.",
|
|
236
|
+
),
|
|
237
|
+
] = "publish",
|
|
238
|
+
):
|
|
239
|
+
"""
|
|
240
|
+
Fetches logs for the publish process with the given ID.
|
|
241
|
+
"""
|
|
242
|
+
try:
|
|
243
|
+
with Progress(
|
|
244
|
+
SpinnerColumn(),
|
|
245
|
+
TextColumn("[progress.description]{task.description}"),
|
|
246
|
+
transient=True,
|
|
247
|
+
) as progress:
|
|
248
|
+
progress.add_task(description="Fetching data...", total=None)
|
|
249
|
+
logs = get_publish_logs(
|
|
250
|
+
metadata_id=metadata_id,
|
|
251
|
+
source=source,
|
|
252
|
+
)
|
|
253
|
+
except Exception as e:
|
|
254
|
+
logger.error(f"Error: {str(e)}")
|
|
255
|
+
sys.exit()
|
|
256
|
+
|
|
257
|
+
rich_print(
|
|
258
|
+
f"{source.capitalize()} logs for publish process of metadata {metadata_id} ({len(logs)})"
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
if len(logs[0].keys()) == 2:
|
|
262
|
+
table = Table("Timestamp", "Log message", title="Logs")
|
|
263
|
+
for log in logs:
|
|
264
|
+
table.add_row(log["time"], log["message"])
|
|
265
|
+
else:
|
|
266
|
+
table = Table("Timestamp", "Input", "Output", title="Logs")
|
|
267
|
+
for log in logs:
|
|
268
|
+
table.add_row(log["time"], log["input"], log["output"])
|
|
269
|
+
|
|
270
|
+
console = Console()
|
|
271
|
+
console.print(table)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
@logs_app.command("run", no_args_is_help=True)
|
|
275
|
+
def logs_get_run_logs(
|
|
276
|
+
schedule_id: Annotated[
|
|
277
|
+
int,
|
|
278
|
+
typer.Argument(
|
|
279
|
+
help="The ID of the schedule to fetch logs for.",
|
|
280
|
+
),
|
|
281
|
+
],
|
|
282
|
+
run_id: Annotated[
|
|
283
|
+
int,
|
|
284
|
+
typer.Argument(
|
|
285
|
+
help="The ID of the run instance to fetch logs for.",
|
|
286
|
+
),
|
|
287
|
+
],
|
|
288
|
+
):
|
|
289
|
+
"""
|
|
290
|
+
Fetches logs for the schedule run instance with the given ID.
|
|
291
|
+
"""
|
|
292
|
+
try:
|
|
293
|
+
with Progress(
|
|
294
|
+
SpinnerColumn(),
|
|
295
|
+
TextColumn("[progress.description]{task.description}"),
|
|
296
|
+
transient=True,
|
|
297
|
+
) as progress:
|
|
298
|
+
progress.add_task(description="Fetching data...", total=None)
|
|
299
|
+
logs = get_run_logs(
|
|
300
|
+
schedule_id=schedule_id,
|
|
301
|
+
run_id=run_id,
|
|
302
|
+
)
|
|
303
|
+
except Exception as e:
|
|
304
|
+
logger.error(f"Error: {str(e)}")
|
|
305
|
+
sys.exit()
|
|
306
|
+
|
|
307
|
+
rich_print(f"Logs for run process {run_id} of schedule {schedule_id} ({len(logs)})")
|
|
308
|
+
|
|
309
|
+
table = Table("Timestamp", "Source", "Input", "Output", "Cell number", title="Logs")
|
|
310
|
+
for log in logs:
|
|
311
|
+
table.add_row(
|
|
312
|
+
log["timestamp"],
|
|
313
|
+
log["log_type"],
|
|
314
|
+
log["input"] or "",
|
|
315
|
+
log["output"] or "",
|
|
316
|
+
str(log["cell_number"]) or "",
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
console = Console()
|
|
320
|
+
console.print(table)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
@logs_app.callback(invoke_without_command=True)
|
|
324
|
+
def main(
|
|
325
|
+
interactive: bool = typer.Option(
|
|
326
|
+
False, "-i", "--interactive", help="Activate interactive mode"
|
|
327
|
+
)
|
|
328
|
+
):
|
|
329
|
+
if interactive:
|
|
330
|
+
interactive_mode(
|
|
331
|
+
this_app=logs_app,
|
|
332
|
+
title="logs",
|
|
333
|
+
color="maroon",
|
|
334
|
+
completion=NestedCompleter.from_nested_dict(completion_tree["logs"]),
|
|
335
|
+
)
|
|
336
|
+
else:
|
|
337
|
+
check_authentication()
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Pictures-related commands"""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from io import BytesIO
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from adalib.adaboard import request_adaboard
|
|
9
|
+
from adalib.pictures import get_picture, post_picture, post_picture_url
|
|
10
|
+
from ascii_magic import AsciiArt
|
|
11
|
+
from prompt_toolkit.completion import NestedCompleter
|
|
12
|
+
from rich import print as rich_print
|
|
13
|
+
|
|
14
|
+
from .completion_tree import completion_tree
|
|
15
|
+
from .factory import check_authentication
|
|
16
|
+
from .interactive import interactive_mode
|
|
17
|
+
|
|
18
|
+
pictures_app = typer.Typer()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pictures_app.command("show", no_args_is_help=True)
|
|
22
|
+
def show_picture(picture_id: Annotated[int, typer.Argument(help="The ID of the picture to show")]):
|
|
23
|
+
"""Show the specific picture as an ASCII art"""
|
|
24
|
+
try:
|
|
25
|
+
data = BytesIO(request_adaboard(f"image/{picture_id}").content)
|
|
26
|
+
AsciiArt.from_image(data).to_terminal()
|
|
27
|
+
except Exception:
|
|
28
|
+
rich_print(f"Could not show the picture with ID: {picture_id}")
|
|
29
|
+
sys.exit(1)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pictures_app.command("download", no_args_is_help=True)
|
|
33
|
+
def download_picture(
|
|
34
|
+
picture_id: Annotated[int, typer.Argument(help="The ID of the picture to download")],
|
|
35
|
+
output_path: Annotated[
|
|
36
|
+
str | None, typer.Option(help="The path to save the picture to")
|
|
37
|
+
] = None,
|
|
38
|
+
):
|
|
39
|
+
"""Download the specific picture into a file."""
|
|
40
|
+
if output_path is None:
|
|
41
|
+
output_path = f"picture_{picture_id}"
|
|
42
|
+
try:
|
|
43
|
+
get_picture(picture_id=picture_id, output_file_path=output_path)
|
|
44
|
+
except Exception:
|
|
45
|
+
rich_print(f"Could not download the picture with ID: {picture_id}")
|
|
46
|
+
sys.exit(1)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@pictures_app.command("create", no_args_is_help=True)
|
|
50
|
+
def create_new_picture(
|
|
51
|
+
path: Annotated[str | None, typer.Option(help="The path to the picture file")] = None,
|
|
52
|
+
url: Annotated[str | None, typer.Option(help="The URL of the picture")] = None,
|
|
53
|
+
):
|
|
54
|
+
"""Create a new picture from a file or URL."""
|
|
55
|
+
if (path is not None and url is not None) or (path is None and url is None):
|
|
56
|
+
rich_print("Please provide either a path or a URL to create a picture.")
|
|
57
|
+
sys.exit(1)
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
if path is not None:
|
|
61
|
+
picture_id = post_picture(input_file_path=path)
|
|
62
|
+
else:
|
|
63
|
+
picture_id = post_picture_url(picture_url=url)
|
|
64
|
+
|
|
65
|
+
rich_print(f"Picture created with ID: {picture_id}")
|
|
66
|
+
except Exception:
|
|
67
|
+
rich_print("Could not create the picture.")
|
|
68
|
+
sys.exit(1)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@pictures_app.callback(invoke_without_command=True)
|
|
72
|
+
def main(
|
|
73
|
+
interactive: bool = typer.Option(
|
|
74
|
+
False, "-i", "--interactive", help="Activate interactive mode"
|
|
75
|
+
)
|
|
76
|
+
):
|
|
77
|
+
if interactive:
|
|
78
|
+
interactive_mode(
|
|
79
|
+
this_app=pictures_app,
|
|
80
|
+
title="pictures",
|
|
81
|
+
color="maroon",
|
|
82
|
+
completion=NestedCompleter.from_nested_dict(completion_tree["pictures"]),
|
|
83
|
+
)
|
|
84
|
+
else:
|
|
85
|
+
check_authentication()
|
|
@@ -10,10 +10,11 @@ Functions:
|
|
|
10
10
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
|
+
import base64
|
|
13
14
|
import sys
|
|
14
15
|
|
|
15
16
|
import typer
|
|
16
|
-
from adalib.adaboard import get_user
|
|
17
|
+
from adalib.adaboard import get_all_pages, get_user, request_adaboard
|
|
17
18
|
from adalib.schedules import (
|
|
18
19
|
create_schedule,
|
|
19
20
|
delete_run,
|
|
@@ -24,6 +25,7 @@ from adalib.schedules import (
|
|
|
24
25
|
)
|
|
25
26
|
from prompt_toolkit.completion import NestedCompleter
|
|
26
27
|
from rich import print as rich_print
|
|
28
|
+
from rich.table import Table
|
|
27
29
|
from typing_extensions import Annotated
|
|
28
30
|
|
|
29
31
|
from .completion_tree import completion_tree
|
|
@@ -33,6 +35,93 @@ from .interactive import interactive_mode
|
|
|
33
35
|
schedules_app = typer.Typer()
|
|
34
36
|
|
|
35
37
|
|
|
38
|
+
@schedules_app.command("list-schedules", no_args_is_help=False)
|
|
39
|
+
def list_all_schedules(
|
|
40
|
+
only_active: Annotated[bool, typer.Option(help="Include only active schedules")] = False,
|
|
41
|
+
search_phrase: Annotated[str, typer.Option(help="Search phrase to filter schedules")] = None,
|
|
42
|
+
):
|
|
43
|
+
"""Lists all available schedules."""
|
|
44
|
+
params = dict()
|
|
45
|
+
if only_active:
|
|
46
|
+
params = {"only_active": True}
|
|
47
|
+
|
|
48
|
+
if search_phrase is not None:
|
|
49
|
+
params["search"] = search_phrase
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
res = get_all_pages("schedules/v2", params=params)
|
|
53
|
+
except Exception:
|
|
54
|
+
rich_print("Failed to list schedules.")
|
|
55
|
+
sys.exit(1)
|
|
56
|
+
|
|
57
|
+
cols = ["ID", "Name", "Owner", "Cron", "Pool", "Active", "Last Run", "Next Run"]
|
|
58
|
+
table = Table(
|
|
59
|
+
*[x for x in cols],
|
|
60
|
+
title="Schedules",
|
|
61
|
+
)
|
|
62
|
+
for row in res:
|
|
63
|
+
table.add_row(
|
|
64
|
+
str(row["schedule_id"]),
|
|
65
|
+
row["name"],
|
|
66
|
+
row["owner"]["name"],
|
|
67
|
+
row["cron"],
|
|
68
|
+
row["pool"],
|
|
69
|
+
"✅" if row["active"] else "❌",
|
|
70
|
+
row["last_scheduled_ts"] or "N/A",
|
|
71
|
+
row["next_scheduled_ts"] or "N/A",
|
|
72
|
+
)
|
|
73
|
+
rich_print(table)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@schedules_app.command("get-schedule", no_args_is_help=True)
|
|
77
|
+
def get_single_schedule(
|
|
78
|
+
schedule_id: Annotated[int, typer.Argument(help="ID of the schedule.")],
|
|
79
|
+
incl_content: Annotated[bool, typer.Option(help="Include the schedule content.")] = False,
|
|
80
|
+
):
|
|
81
|
+
"""Retrieves the details of a single schedule."""
|
|
82
|
+
params = {"with_content": incl_content}
|
|
83
|
+
try:
|
|
84
|
+
res = request_adaboard(f"schedules/v2/{schedule_id}", params=params).json()
|
|
85
|
+
except Exception:
|
|
86
|
+
rich_print(f"Failed to get schedule {schedule_id}.")
|
|
87
|
+
sys.exit(1)
|
|
88
|
+
|
|
89
|
+
if res["content"]:
|
|
90
|
+
for _content in res["content"]:
|
|
91
|
+
_content["content"] = base64.b64decode(_content["content"]).decode("utf-8")
|
|
92
|
+
|
|
93
|
+
schedule = {
|
|
94
|
+
"ID": schedule_id,
|
|
95
|
+
"Name": res["name"],
|
|
96
|
+
"Owner": res["owner"]["name"],
|
|
97
|
+
"Runner": res["runner"]["name"],
|
|
98
|
+
"Timeout": res["timeout"],
|
|
99
|
+
"Pool": res["pool"],
|
|
100
|
+
"Active": "✅" if res["active"] else "❌",
|
|
101
|
+
"Timezone": res["timezone"],
|
|
102
|
+
"Cron": res["cron"],
|
|
103
|
+
"Last Run": res["last_scheduled_ts"] or "N/A",
|
|
104
|
+
"Next Run": res["next_scheduled_ts"] or "N/A",
|
|
105
|
+
"Concurrent": "✅" if res["concurrent"] else "❌",
|
|
106
|
+
"Cleanup": "✅" if res["cleanup"] else "❌",
|
|
107
|
+
"Contents": res["content"],
|
|
108
|
+
"Inputs": res["run_config"]["inputs"],
|
|
109
|
+
"Pre-run script": res["run_config"]["scripts"]["pre_run_script"] or "N/A",
|
|
110
|
+
"Post-run script": res["run_config"]["scripts"]["post_run_script"] or "N/A",
|
|
111
|
+
"Kernel ID": res["kernel_metadata_id"],
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
table = Table(title="Schedule Details")
|
|
115
|
+
table.add_column("Property", style="cyan", no_wrap=True)
|
|
116
|
+
table.add_column("Value", style="magenta")
|
|
117
|
+
for key, value in schedule.items():
|
|
118
|
+
if isinstance(value, bool):
|
|
119
|
+
value = "✅" if value else "❌"
|
|
120
|
+
table.add_row(key, str(value) if value != [] else "[dim]Empty List[/dim]")
|
|
121
|
+
|
|
122
|
+
rich_print(table)
|
|
123
|
+
|
|
124
|
+
|
|
36
125
|
@schedules_app.command("start-run", no_args_is_help=True)
|
|
37
126
|
def notebooks_start_run(
|
|
38
127
|
schedule_id: Annotated[int, typer.Argument(help="ID of the schedule to start run.")]
|
|
@@ -172,7 +261,7 @@ def notebooks_delete_schedule(
|
|
|
172
261
|
sys.exit(1)
|
|
173
262
|
|
|
174
263
|
|
|
175
|
-
@schedules_app.callback(
|
|
264
|
+
@schedules_app.callback(invoke_without_command=True)
|
|
176
265
|
def main(
|
|
177
266
|
interactive: bool = typer.Option(
|
|
178
267
|
False, "-i", "--interactive", help="Activate interactive mode"
|
|
@@ -58,7 +58,7 @@ def user_who_am_i_in_adalab(
|
|
|
58
58
|
console.print(table)
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
@user_app.callback(
|
|
61
|
+
@user_app.callback(invoke_without_command=True)
|
|
62
62
|
def main(
|
|
63
63
|
interactive: bool = typer.Option(
|
|
64
64
|
False, "-i", "--interactive", help="Activate interactive mode"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "adalab-cli"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.2.0"
|
|
4
4
|
description = "The CLI app to interact with AdaLab."
|
|
5
|
-
keywords = [
|
|
5
|
+
keywords = ["cli"]
|
|
6
6
|
|
|
7
7
|
[[project.authors]]
|
|
8
8
|
name = "Adamatics ApS"
|
|
@@ -10,35 +10,34 @@ email = "info@adamatics.com"
|
|
|
10
10
|
|
|
11
11
|
[tool.poetry]
|
|
12
12
|
name = "adalab-cli"
|
|
13
|
-
version = "3.
|
|
13
|
+
version = "3.2.0"
|
|
14
14
|
description = "The CLI app to interact with AdaLab."
|
|
15
15
|
authors = ["Adamatics ApS <info@adamatics.com>"]
|
|
16
16
|
readme = "README.md"
|
|
17
17
|
homepage = "https://adamatics.com"
|
|
18
18
|
repository = "https://gitlab.com/adamatics/python/adalab-cli"
|
|
19
19
|
classifiers = [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
]
|
|
29
|
-
packages = [
|
|
30
|
-
{ include = "adalab_cli" }
|
|
20
|
+
"Development Status :: 4 - Beta",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Programming Language :: Python",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
"Typing :: Typed",
|
|
31
28
|
]
|
|
29
|
+
packages = [{ include = "adalab_cli" }]
|
|
32
30
|
|
|
33
31
|
[tool.poetry.dependencies]
|
|
34
32
|
python = "^3.10.0"
|
|
35
33
|
tabulate = ">=0.9.0"
|
|
36
34
|
typer = ">=0.9.0"
|
|
37
35
|
sh = ">=2.0.6"
|
|
38
|
-
adalib = {version = ">=
|
|
39
|
-
adalib-auth = {version = ">=1.2.2", source = "adalib-dev"}
|
|
36
|
+
adalib = { version = ">=7.2.0", source = "adalib-dev" }
|
|
37
|
+
adalib-auth = { version = ">=1.2.2", source = "adalib-dev" }
|
|
40
38
|
loguru = ">=0.7.2"
|
|
41
39
|
prompt-toolkit = ">=3.0.47"
|
|
40
|
+
ascii-magic = ">=2.3.0"
|
|
42
41
|
|
|
43
42
|
[tool.poetry.group.dev.dependencies]
|
|
44
43
|
black = "^23.9.1"
|
|
@@ -87,8 +86,8 @@ line-length = 99
|
|
|
87
86
|
[tool.flake8]
|
|
88
87
|
ignore = ["E203", "E266", "E501", "W503"]
|
|
89
88
|
max-complexity = 18
|
|
90
|
-
select = ["B","C","E","F","W","T4"]
|
|
91
|
-
exclude = [".git",".venv",".tox"]
|
|
89
|
+
select = ["B", "C", "E", "F", "W", "T4"]
|
|
90
|
+
exclude = [".git", ".venv", ".tox"]
|
|
92
91
|
max-line-length = 99
|
|
93
92
|
|
|
94
93
|
[tool.pytest]
|
|
@@ -104,10 +103,7 @@ addopts = """\
|
|
|
104
103
|
|
|
105
104
|
[tool.coverage.report]
|
|
106
105
|
fail_under = 100
|
|
107
|
-
exclude_lines = [
|
|
108
|
-
'if TYPE_CHECKING:',
|
|
109
|
-
'pragma: no cover'
|
|
110
|
-
]
|
|
106
|
+
exclude_lines = ['if TYPE_CHECKING:', 'pragma: no cover']
|
|
111
107
|
|
|
112
108
|
[tool.mypy]
|
|
113
109
|
disallow_any_unimported = true
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"""Map of the CLI commands and subcommands for the CLI completion tree."""
|
|
2
|
-
|
|
3
|
-
completion_tree = {
|
|
4
|
-
"cards": {
|
|
5
|
-
"approve-card": {"--help": None},
|
|
6
|
-
"expose-card": {"--help": None},
|
|
7
|
-
"get-card": {"--help": None},
|
|
8
|
-
"hide-card": {"--help": None},
|
|
9
|
-
"list-cards": {
|
|
10
|
-
"all": None,
|
|
11
|
-
"notebook": None,
|
|
12
|
-
"voila": None,
|
|
13
|
-
"url": None,
|
|
14
|
-
"group": None,
|
|
15
|
-
"--help": None,
|
|
16
|
-
},
|
|
17
|
-
"help": None,
|
|
18
|
-
"exit": None,
|
|
19
|
-
},
|
|
20
|
-
"databases": {
|
|
21
|
-
"list-databases": {"--no-pretty": None, "--help": None},
|
|
22
|
-
"list-datasets": {"--no-pretty": None, "--return-sql": None, "--help": None},
|
|
23
|
-
"list-tables": {"--no-pretty": None, "--help": None},
|
|
24
|
-
"view-dataset": {"--head": None, "--no-pretty": None, "--help": None},
|
|
25
|
-
"help": None,
|
|
26
|
-
"exit": None,
|
|
27
|
-
},
|
|
28
|
-
"schedules": {
|
|
29
|
-
"create-schedule": {
|
|
30
|
-
"--schedule": None,
|
|
31
|
-
"--pool": None,
|
|
32
|
-
"--active": None,
|
|
33
|
-
"--concurrent": None,
|
|
34
|
-
"--cleanup": None,
|
|
35
|
-
"--timeout": None,
|
|
36
|
-
"--help": None,
|
|
37
|
-
},
|
|
38
|
-
"delete-run": {"--help": None},
|
|
39
|
-
"delete-schedule": {"--help": None},
|
|
40
|
-
"start-run": {
|
|
41
|
-
"--cleanup": None,
|
|
42
|
-
"--pool": None,
|
|
43
|
-
"--timeout": None,
|
|
44
|
-
"--help": None,
|
|
45
|
-
},
|
|
46
|
-
"stop-run": {"--help": None},
|
|
47
|
-
"update-schedule": {
|
|
48
|
-
"--schedule": None,
|
|
49
|
-
"--pool": None,
|
|
50
|
-
"--active": None,
|
|
51
|
-
"--concurrent": None,
|
|
52
|
-
"--cleanup": None,
|
|
53
|
-
"--timeout": None,
|
|
54
|
-
"--help": None,
|
|
55
|
-
},
|
|
56
|
-
"help": None,
|
|
57
|
-
"exit": None,
|
|
58
|
-
},
|
|
59
|
-
"user": {
|
|
60
|
-
"whoami": {"--full-information": None, "--with-notifications": None, "--help": None},
|
|
61
|
-
"help": None,
|
|
62
|
-
"exit": None,
|
|
63
|
-
},
|
|
64
|
-
"version": None,
|
|
65
|
-
"help": None,
|
|
66
|
-
"exit": None,
|
|
67
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|