lamin_cli 0.17.4__py2.py3-none-any.whl → 0.17.6__py2.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.
- lamin_cli/__init__.py +1 -1
- lamin_cli/__main__.py +300 -303
- lamin_cli/_get.py +82 -82
- lamin_cli/_migration.py +48 -48
- lamin_cli/_save.py +119 -111
- {lamin_cli-0.17.4.dist-info → lamin_cli-0.17.6.dist-info}/LICENSE +201 -201
- {lamin_cli-0.17.4.dist-info → lamin_cli-0.17.6.dist-info}/METADATA +1 -1
- lamin_cli-0.17.6.dist-info/RECORD +11 -0
- {lamin_cli-0.17.4.dist-info → lamin_cli-0.17.6.dist-info}/WHEEL +1 -1
- lamin_cli-0.17.4.dist-info/RECORD +0 -11
- {lamin_cli-0.17.4.dist-info → lamin_cli-0.17.6.dist-info}/entry_points.txt +0 -0
lamin_cli/__init__.py
CHANGED
lamin_cli/__main__.py
CHANGED
|
@@ -1,303 +1,300 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
import os
|
|
3
|
-
import sys
|
|
4
|
-
from collections import OrderedDict
|
|
5
|
-
import inspect
|
|
6
|
-
from importlib.metadata import PackageNotFoundError, version
|
|
7
|
-
from typing import Optional, Mapping
|
|
8
|
-
from functools import wraps
|
|
9
|
-
|
|
10
|
-
# https://github.com/ewels/rich-click/issues/19
|
|
11
|
-
# Otherwise rich-click takes over the formatting.
|
|
12
|
-
if os.environ.get("NO_RICH"):
|
|
13
|
-
import click as click
|
|
14
|
-
|
|
15
|
-
class OrderedGroup(click.Group):
|
|
16
|
-
"""Overwrites list_commands to return commands in order of definition."""
|
|
17
|
-
|
|
18
|
-
def __init__(
|
|
19
|
-
self,
|
|
20
|
-
name: Optional[str] = None,
|
|
21
|
-
commands: Optional[Mapping[str, click.Command]] = None,
|
|
22
|
-
**kwargs,
|
|
23
|
-
):
|
|
24
|
-
super(OrderedGroup, self).__init__(name, commands, **kwargs)
|
|
25
|
-
self.commands = commands or OrderedDict()
|
|
26
|
-
|
|
27
|
-
def list_commands(self, ctx: click.Context) -> Mapping[str, click.Command]:
|
|
28
|
-
return self.commands
|
|
29
|
-
|
|
30
|
-
lamin_group_decorator = click.group(cls=OrderedGroup)
|
|
31
|
-
|
|
32
|
-
else:
|
|
33
|
-
import rich_click as click
|
|
34
|
-
|
|
35
|
-
COMMAND_GROUPS = {
|
|
36
|
-
"lamin": [
|
|
37
|
-
{
|
|
38
|
-
"name": "Main commands",
|
|
39
|
-
"commands": [
|
|
40
|
-
"login",
|
|
41
|
-
"init",
|
|
42
|
-
"load",
|
|
43
|
-
"info",
|
|
44
|
-
"delete",
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"name": "Data commands",
|
|
49
|
-
"commands": ["get", "save"],
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
"name": "Configuration commands",
|
|
53
|
-
"commands": ["cache", "set"],
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"name": "Schema migration",
|
|
57
|
-
"commands": ["migrate"],
|
|
58
|
-
},
|
|
59
|
-
]
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
def lamin_group_decorator(f):
|
|
63
|
-
@click.rich_config(
|
|
64
|
-
help_config=click.RichHelpConfiguration(
|
|
65
|
-
command_groups=COMMAND_GROUPS,
|
|
66
|
-
style_commands_table_column_width_ratio=(1, 13),
|
|
67
|
-
)
|
|
68
|
-
)
|
|
69
|
-
@click.group()
|
|
70
|
-
@wraps(f)
|
|
71
|
-
def wrapper(*args, **kwargs):
|
|
72
|
-
return f(*args, **kwargs)
|
|
73
|
-
|
|
74
|
-
return wrapper
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
from click import Command, Context
|
|
78
|
-
from lamindb_setup._silence_loggers import silence_loggers
|
|
79
|
-
|
|
80
|
-
from lamin_cli._cache import cache
|
|
81
|
-
from lamin_cli._migration import migrate
|
|
82
|
-
|
|
83
|
-
try:
|
|
84
|
-
lamindb_version = version("lamindb")
|
|
85
|
-
except PackageNotFoundError:
|
|
86
|
-
lamindb_version = "lamindb installation not found"
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@lamin_group_decorator
|
|
90
|
-
@click.version_option(version=lamindb_version, prog_name="lamindb")
|
|
91
|
-
def main():
|
|
92
|
-
"""Configure LaminDB and perform simple actions."""
|
|
93
|
-
silence_loggers()
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
@main.command()
|
|
97
|
-
@click.argument("user", type=str, default=None, required=False)
|
|
98
|
-
@click.option("--key", type=str, default=None, help="The API key.")
|
|
99
|
-
@click.option("--logout", is_flag=True, help="Logout instead of logging in.")
|
|
100
|
-
def login(user: str, key: Optional[str], logout: bool = False):
|
|
101
|
-
"""Log into LaminHub.
|
|
102
|
-
|
|
103
|
-
Upon logging in the first time, you need to pass your API key via:
|
|
104
|
-
|
|
105
|
-
```
|
|
106
|
-
lamin login myemail@acme.com --key YOUR_API_KEY
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
You'll find your API key on LaminHub in the top right corner under "Settings".
|
|
110
|
-
|
|
111
|
-
After this, you can either use `lamin login myhandle` or `lamin login myemail@acme.com`
|
|
112
|
-
|
|
113
|
-
You can also call this without arguments:
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
lamin login
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
You will be prompted for your Beta API key unless you set an environment variable `LAMIN_API_KEY`.
|
|
120
|
-
"""
|
|
121
|
-
if logout:
|
|
122
|
-
from lamindb_setup._setup_user import logout as logout_func
|
|
123
|
-
|
|
124
|
-
return logout_func()
|
|
125
|
-
else:
|
|
126
|
-
from lamindb_setup._setup_user import login
|
|
127
|
-
|
|
128
|
-
if user is None:
|
|
129
|
-
if "LAMIN_API_KEY" in os.environ:
|
|
130
|
-
api_key = os.environ["LAMIN_API_KEY"]
|
|
131
|
-
else:
|
|
132
|
-
api_key = input("Your API key: ")
|
|
133
|
-
else:
|
|
134
|
-
api_key = None
|
|
135
|
-
|
|
136
|
-
return login(user, key=key, api_key=api_key)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
# fmt: off
|
|
140
|
-
@main.command()
|
|
141
|
-
@click.option("--storage", type=str, help="Local directory, s3://bucket_name, gs://bucket_name.") # noqa: E501
|
|
142
|
-
@click.option("--db", type=str, default=None, help="Postgres database connection URL, do not pass for SQLite.") # noqa: E501
|
|
143
|
-
@click.option("--schema", type=str, default=None, help="Comma-separated string of schema modules.") # noqa: E501
|
|
144
|
-
@click.option("--name", type=str, default=None, help="The instance name.")
|
|
145
|
-
# fmt: on
|
|
146
|
-
def init(storage: str, db: Optional[str], schema: Optional[str], name: Optional[str]):
|
|
147
|
-
"""Init a LaminDB instance."""
|
|
148
|
-
from lamindb_setup._init_instance import init as init_
|
|
149
|
-
|
|
150
|
-
return init_(storage=storage, db=db, schema=schema, name=name)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
# fmt: off
|
|
154
|
-
@main.command()
|
|
155
|
-
@click.argument("instance", type=str, default=None, required=False)
|
|
156
|
-
@click.option("--
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
)
|
|
163
|
-
"""
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
# fmt:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
@
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
lamin get
|
|
222
|
-
lamin get
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
@
|
|
235
|
-
@click.
|
|
236
|
-
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
main.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
""
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
def
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
cmd
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if __name__ == "__main__":
|
|
303
|
-
main()
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from collections import OrderedDict
|
|
5
|
+
import inspect
|
|
6
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
7
|
+
from typing import Optional, Mapping
|
|
8
|
+
from functools import wraps
|
|
9
|
+
|
|
10
|
+
# https://github.com/ewels/rich-click/issues/19
|
|
11
|
+
# Otherwise rich-click takes over the formatting.
|
|
12
|
+
if os.environ.get("NO_RICH"):
|
|
13
|
+
import click as click
|
|
14
|
+
|
|
15
|
+
class OrderedGroup(click.Group):
|
|
16
|
+
"""Overwrites list_commands to return commands in order of definition."""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
name: Optional[str] = None,
|
|
21
|
+
commands: Optional[Mapping[str, click.Command]] = None,
|
|
22
|
+
**kwargs,
|
|
23
|
+
):
|
|
24
|
+
super(OrderedGroup, self).__init__(name, commands, **kwargs)
|
|
25
|
+
self.commands = commands or OrderedDict()
|
|
26
|
+
|
|
27
|
+
def list_commands(self, ctx: click.Context) -> Mapping[str, click.Command]:
|
|
28
|
+
return self.commands
|
|
29
|
+
|
|
30
|
+
lamin_group_decorator = click.group(cls=OrderedGroup)
|
|
31
|
+
|
|
32
|
+
else:
|
|
33
|
+
import rich_click as click
|
|
34
|
+
|
|
35
|
+
COMMAND_GROUPS = {
|
|
36
|
+
"lamin": [
|
|
37
|
+
{
|
|
38
|
+
"name": "Main commands",
|
|
39
|
+
"commands": [
|
|
40
|
+
"login",
|
|
41
|
+
"init",
|
|
42
|
+
"load",
|
|
43
|
+
"info",
|
|
44
|
+
"delete",
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "Data commands",
|
|
49
|
+
"commands": ["get", "save"],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "Configuration commands",
|
|
53
|
+
"commands": ["cache", "set"],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "Schema migration",
|
|
57
|
+
"commands": ["migrate"],
|
|
58
|
+
},
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
def lamin_group_decorator(f):
|
|
63
|
+
@click.rich_config(
|
|
64
|
+
help_config=click.RichHelpConfiguration(
|
|
65
|
+
command_groups=COMMAND_GROUPS,
|
|
66
|
+
style_commands_table_column_width_ratio=(1, 13),
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
@click.group()
|
|
70
|
+
@wraps(f)
|
|
71
|
+
def wrapper(*args, **kwargs):
|
|
72
|
+
return f(*args, **kwargs)
|
|
73
|
+
|
|
74
|
+
return wrapper
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
from click import Command, Context
|
|
78
|
+
from lamindb_setup._silence_loggers import silence_loggers
|
|
79
|
+
|
|
80
|
+
from lamin_cli._cache import cache
|
|
81
|
+
from lamin_cli._migration import migrate
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
lamindb_version = version("lamindb")
|
|
85
|
+
except PackageNotFoundError:
|
|
86
|
+
lamindb_version = "lamindb installation not found"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@lamin_group_decorator
|
|
90
|
+
@click.version_option(version=lamindb_version, prog_name="lamindb")
|
|
91
|
+
def main():
|
|
92
|
+
"""Configure LaminDB and perform simple actions."""
|
|
93
|
+
silence_loggers()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@main.command()
|
|
97
|
+
@click.argument("user", type=str, default=None, required=False)
|
|
98
|
+
@click.option("--key", type=str, default=None, help="The API key.")
|
|
99
|
+
@click.option("--logout", is_flag=True, help="Logout instead of logging in.")
|
|
100
|
+
def login(user: str, key: Optional[str], logout: bool = False):
|
|
101
|
+
"""Log into LaminHub.
|
|
102
|
+
|
|
103
|
+
Upon logging in the first time, you need to pass your API key via:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
lamin login myemail@acme.com --key YOUR_API_KEY
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
You'll find your API key on LaminHub in the top right corner under "Settings".
|
|
110
|
+
|
|
111
|
+
After this, you can either use `lamin login myhandle` or `lamin login myemail@acme.com`
|
|
112
|
+
|
|
113
|
+
You can also call this without arguments:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
lamin login
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
You will be prompted for your Beta API key unless you set an environment variable `LAMIN_API_KEY`.
|
|
120
|
+
"""
|
|
121
|
+
if logout:
|
|
122
|
+
from lamindb_setup._setup_user import logout as logout_func
|
|
123
|
+
|
|
124
|
+
return logout_func()
|
|
125
|
+
else:
|
|
126
|
+
from lamindb_setup._setup_user import login
|
|
127
|
+
|
|
128
|
+
if user is None:
|
|
129
|
+
if "LAMIN_API_KEY" in os.environ:
|
|
130
|
+
api_key = os.environ["LAMIN_API_KEY"]
|
|
131
|
+
else:
|
|
132
|
+
api_key = input("Your API key: ")
|
|
133
|
+
else:
|
|
134
|
+
api_key = None
|
|
135
|
+
|
|
136
|
+
return login(user, key=key, api_key=api_key)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# fmt: off
|
|
140
|
+
@main.command()
|
|
141
|
+
@click.option("--storage", type=str, help="Local directory, s3://bucket_name, gs://bucket_name.") # noqa: E501
|
|
142
|
+
@click.option("--db", type=str, default=None, help="Postgres database connection URL, do not pass for SQLite.") # noqa: E501
|
|
143
|
+
@click.option("--schema", type=str, default=None, help="Comma-separated string of schema modules.") # noqa: E501
|
|
144
|
+
@click.option("--name", type=str, default=None, help="The instance name.")
|
|
145
|
+
# fmt: on
|
|
146
|
+
def init(storage: str, db: Optional[str], schema: Optional[str], name: Optional[str]):
|
|
147
|
+
"""Init a LaminDB instance."""
|
|
148
|
+
from lamindb_setup._init_instance import init as init_
|
|
149
|
+
|
|
150
|
+
return init_(storage=storage, db=db, schema=schema, name=name)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
# fmt: off
|
|
154
|
+
@main.command()
|
|
155
|
+
@click.argument("instance", type=str, default=None, required=False)
|
|
156
|
+
@click.option("--unload", is_flag=True, help="Unload the current instance.")
|
|
157
|
+
# fmt: on
|
|
158
|
+
def load(instance: Optional[str], unload: bool):
|
|
159
|
+
"""Load an instance for auto-connection.
|
|
160
|
+
|
|
161
|
+
Pass a slug (`account/name`) or URL
|
|
162
|
+
(`https://lamin.ai/account/name`).
|
|
163
|
+
"""
|
|
164
|
+
if unload:
|
|
165
|
+
from lamindb_setup._close import close as close_
|
|
166
|
+
|
|
167
|
+
return close_()
|
|
168
|
+
else:
|
|
169
|
+
if instance is None:
|
|
170
|
+
raise click.UsageError("INSTANCE is required when loading an instance.")
|
|
171
|
+
from lamindb_setup import settings, connect
|
|
172
|
+
|
|
173
|
+
settings.auto_connect = True
|
|
174
|
+
return connect(slug=instance)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@main.command()
|
|
178
|
+
@click.option("--schema", is_flag=True, help="View schema.")
|
|
179
|
+
def info(schema: bool):
|
|
180
|
+
"""Show info about current instance."""
|
|
181
|
+
if schema:
|
|
182
|
+
from lamindb_setup._schema import view
|
|
183
|
+
|
|
184
|
+
print("Open in browser: http://127.0.0.1:8000/schema/")
|
|
185
|
+
return view()
|
|
186
|
+
else:
|
|
187
|
+
import lamindb_setup
|
|
188
|
+
|
|
189
|
+
print(lamindb_setup.settings)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# fmt: off
|
|
193
|
+
@main.command()
|
|
194
|
+
@click.argument("instance", type=str, default=None)
|
|
195
|
+
@click.option("--force", is_flag=True, default=False, help="Do not ask for confirmation.") # noqa: E501
|
|
196
|
+
# fmt: on
|
|
197
|
+
def delete(instance: str, force: bool = False):
|
|
198
|
+
"""Delete an instance."""
|
|
199
|
+
from lamindb_setup._delete import delete
|
|
200
|
+
|
|
201
|
+
return delete(instance, force=force)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@main.command()
|
|
205
|
+
@click.argument("entity", type=str)
|
|
206
|
+
@click.option("--uid", help="The uid for the entity.")
|
|
207
|
+
@click.option("--key", help="The key for the entity.")
|
|
208
|
+
@click.option(
|
|
209
|
+
"--with-env", is_flag=True, help="Also return the environment for a tranform."
|
|
210
|
+
)
|
|
211
|
+
def get(entity: str, uid: str = None, key: str = None, with_env: bool = False):
|
|
212
|
+
"""Query an entity.
|
|
213
|
+
|
|
214
|
+
Pass a URL, `artifact`, or `transform`. For example:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
lamin get https://lamin.ai/account/instance/artifact/e2G7k9EVul4JbfsEYAy5
|
|
218
|
+
lamin get artifact --key mydatasets/mytable.parquet
|
|
219
|
+
lamin get artifact --uid e2G7k9EVul4JbfsEYAy5
|
|
220
|
+
lamin get transform --key analysis.ipynb
|
|
221
|
+
lamin get transform --uid Vul4JbfsEYAy5
|
|
222
|
+
lamin get transform --uid Vul4JbfsEYAy5 --with-env
|
|
223
|
+
```
|
|
224
|
+
"""
|
|
225
|
+
from lamin_cli._get import get
|
|
226
|
+
|
|
227
|
+
return get(entity, uid=uid, key=key, with_env=with_env)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@main.command()
|
|
231
|
+
@click.argument(
|
|
232
|
+
"filepath", type=click.Path(exists=True, dir_okay=False, file_okay=True)
|
|
233
|
+
)
|
|
234
|
+
@click.option("--key", type=str, default=None)
|
|
235
|
+
@click.option("--description", type=str, default=None)
|
|
236
|
+
@click.option("--registry", type=str, default=None)
|
|
237
|
+
def save(filepath: str, key: str, description: str, registry: str):
|
|
238
|
+
"""Save file or folder."""
|
|
239
|
+
from lamin_cli._save import save_from_filepath_cli
|
|
240
|
+
|
|
241
|
+
if save_from_filepath_cli(filepath, key, description, registry) is not None:
|
|
242
|
+
sys.exit(1)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
main.add_command(cache)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
@main.command(name="set")
|
|
249
|
+
@click.argument(
|
|
250
|
+
"setting",
|
|
251
|
+
type=click.Choice(["auto-connect", "private-django-api"], case_sensitive=False),
|
|
252
|
+
)
|
|
253
|
+
@click.argument("value", type=click.BOOL)
|
|
254
|
+
def set_(setting: str, value: bool):
|
|
255
|
+
"""Update settings.
|
|
256
|
+
|
|
257
|
+
- `auto-connect` → {attr}`~lamindb.setup.core.SetupSettings.auto_connect`
|
|
258
|
+
- `private-django-api` → {attr}`~lamindb.setup.core.SetupSettings.private_django_api`
|
|
259
|
+
"""
|
|
260
|
+
from lamindb_setup import settings
|
|
261
|
+
|
|
262
|
+
if setting == "auto-connect":
|
|
263
|
+
settings.auto_connect = value
|
|
264
|
+
if setting == "private-django-api":
|
|
265
|
+
settings.private_django_api = value
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
main.add_command(migrate)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
# https://stackoverflow.com/questions/57810659/automatically-generate-all-help-documentation-for-click-commands
|
|
272
|
+
# https://claude.ai/chat/73c28487-bec3-4073-8110-50d1a2dd6b84
|
|
273
|
+
def _generate_help():
|
|
274
|
+
out: dict[str, dict[str, str | None]] = {}
|
|
275
|
+
|
|
276
|
+
def recursive_help(
|
|
277
|
+
cmd: Command, parent: Optional[Context] = None, name: tuple[str, ...] = ()
|
|
278
|
+
):
|
|
279
|
+
ctx = click.Context(cmd, info_name=cmd.name, parent=parent)
|
|
280
|
+
assert cmd.name
|
|
281
|
+
name = (*name, cmd.name)
|
|
282
|
+
command_name = " ".join(name)
|
|
283
|
+
|
|
284
|
+
docstring = inspect.getdoc(cmd.callback)
|
|
285
|
+
usage = cmd.get_help(ctx).split("\n")[0]
|
|
286
|
+
options = cmd.get_help(ctx).split("Options:")[1]
|
|
287
|
+
out[command_name] = {
|
|
288
|
+
"help": usage + "\n\nOptions:" + options,
|
|
289
|
+
"docstring": docstring,
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
for sub in getattr(cmd, "commands", {}).values():
|
|
293
|
+
recursive_help(sub, ctx, name=name)
|
|
294
|
+
|
|
295
|
+
recursive_help(main)
|
|
296
|
+
return out
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
if __name__ == "__main__":
|
|
300
|
+
main()
|