lamin_cli 0.17.2__tar.gz → 0.17.3__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.
Files changed (28) hide show
  1. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/PKG-INFO +1 -1
  2. lamin_cli-0.17.3/lamin_cli/__init__.py +3 -0
  3. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/lamin_cli/__main__.py +52 -56
  4. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/lamin_cli/_get.py +17 -1
  5. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/test_cli.py +22 -4
  6. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/test_get.py +2 -1
  7. lamin_cli-0.17.2/lamin_cli/__init__.py +0 -3
  8. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/.github/workflows/doc-changes.yml +0 -0
  9. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/.gitignore +0 -0
  10. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/.pre-commit-config.yaml +0 -0
  11. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/LICENSE +0 -0
  12. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/README.md +0 -0
  13. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/lamin_cli/_cache.py +0 -0
  14. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/lamin_cli/_migration.py +0 -0
  15. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/lamin_cli/_save.py +0 -0
  16. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/pyproject.toml +0 -0
  17. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/conftest.py +0 -0
  18. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/notebooks/not-initialized.ipynb +0 -0
  19. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/notebooks/with-title-and-initialized-consecutive.ipynb +0 -0
  20. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/notebooks/with-title-and-initialized-non-consecutive.ipynb +0 -0
  21. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/scripts/merely-import-lamindb.py +0 -0
  22. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/scripts/run-track-and-finish-sync-git.py +0 -0
  23. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/scripts/run-track-and-finish.py +0 -0
  24. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/test_migrate.py +0 -0
  25. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/test_multi_process.py +0 -0
  26. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/test_save_files.py +0 -0
  27. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/test_save_notebooks.py +0 -0
  28. {lamin_cli-0.17.2 → lamin_cli-0.17.3}/tests/test_save_scripts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamin_cli
3
- Version: 0.17.2
3
+ Version: 0.17.3
4
4
  Summary: Lamin CLI.
5
5
  Author-email: Lamin Labs <open-source@lamin.ai>
6
6
  Description-Content-Type: text/markdown
@@ -0,0 +1,3 @@
1
+ """Lamin CLI."""
2
+
3
+ __version__ = "0.17.3"
@@ -41,9 +41,7 @@ else:
41
41
  "init",
42
42
  "load",
43
43
  "info",
44
- "close",
45
44
  "delete",
46
- "logout",
47
45
  ],
48
46
  },
49
47
  {
@@ -55,8 +53,8 @@ else:
55
53
  "commands": ["cache", "set"],
56
54
  },
57
55
  {
58
- "name": "Schema commands",
59
- "commands": ["migrate", "schema"],
56
+ "name": "Schema migration",
57
+ "commands": ["migrate"],
60
58
  },
61
59
  ]
62
60
  }
@@ -98,7 +96,8 @@ def main():
98
96
  @main.command()
99
97
  @click.argument("user", type=str, default=None, required=False)
100
98
  @click.option("--key", type=str, default=None, help="The API key.")
101
- def login(user: str, key: Optional[str]):
99
+ @click.option("--logout", is_flag=True, help="Logout instead of logging in.")
100
+ def login(user: str, key: Optional[str], logout: bool = False):
102
101
  """Log into LaminHub.
103
102
 
104
103
  Upon logging in the first time, you need to pass your API key via:
@@ -119,17 +118,22 @@ def login(user: str, key: Optional[str]):
119
118
 
120
119
  You will be prompted for your Beta API key unless you set an environment variable `LAMIN_API_KEY`.
121
120
  """
122
- from lamindb_setup._setup_user import login
121
+ if logout:
122
+ from lamindb_setup._setup_user import logout as logout_func
123
123
 
124
- if user is None:
125
- if "LAMIN_API_KEY" in os.environ:
126
- api_key = os.environ["LAMIN_API_KEY"]
127
- else:
128
- api_key = input("Your API key: ")
124
+ return logout_func()
129
125
  else:
130
- api_key = None
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
131
135
 
132
- return login(user, key=key, api_key=api_key)
136
+ return login(user, key=key, api_key=api_key)
133
137
 
134
138
 
135
139
  # fmt: off
@@ -148,39 +152,45 @@ def init(storage: str, db: Optional[str], schema: Optional[str], name: Optional[
148
152
 
149
153
  # fmt: off
150
154
  @main.command()
151
- @click.argument("identifier", type=str, default=None)
155
+ @click.argument("instance", type=str, default=None)
152
156
  @click.option("--db", type=str, default=None, help="Update database URL.") # noqa: E501
153
157
  @click.option("--storage", type=str, default=None, help="Update storage while loading.")
158
+ @click.option("--unload", is_flag=True, help="Unload the current instance.")
154
159
  # fmt: on
155
- def load(identifier: str, db: Optional[str], storage: Optional[str]):
160
+ def load(
161
+ instance: Optional[str], db: Optional[str], storage: Optional[str], unload: bool
162
+ ):
156
163
  """Load an instance for auto-connection.
157
164
 
158
- `IDENTIFIER` is either a slug (`account/instance`) or a `URL`
159
- (`https://lamin.ai/account/instance`).
165
+ Pass a slug (`account/name`) or URL
166
+ (`https://lamin.ai/account/name`).
160
167
  """
161
- from lamindb_setup import settings, connect
162
-
163
- settings.auto_connect = True
164
- return connect(slug=identifier, db=db, storage=storage)
165
-
168
+ if unload:
169
+ from lamindb_setup._close import close as close_
166
170
 
167
- @main.command()
168
- def info():
169
- """Show user, settings & instance info."""
170
- import lamindb_setup
171
+ return close_()
172
+ else:
173
+ if instance is None:
174
+ raise click.UsageError("INSTANCE is required when loading an instance.")
175
+ from lamindb_setup import settings, connect
171
176
 
172
- print(lamindb_setup.settings)
177
+ settings.auto_connect = True
178
+ return connect(slug=instance, db=db, storage=storage)
173
179
 
174
180
 
175
181
  @main.command()
176
- def close():
177
- """Close an existing instance.
182
+ @click.option("--schema", is_flag=True, help="View schema.")
183
+ def info(schema: bool):
184
+ """Show info about current instance."""
185
+ if schema:
186
+ from lamindb_setup._schema import view
178
187
 
179
- Is the opposite of loading an instance.
180
- """
181
- from lamindb_setup._close import close as close_
188
+ print("Open in browser: http://127.0.0.1:8000/schema/")
189
+ return view()
190
+ else:
191
+ import lamindb_setup
182
192
 
183
- return close_()
193
+ print(lamindb_setup.settings)
184
194
 
185
195
 
186
196
  # fmt: off
@@ -195,22 +205,17 @@ def delete(instance: str, force: bool = False):
195
205
  return delete(instance, force=force)
196
206
 
197
207
 
198
- @main.command()
199
- def logout():
200
- """Logout."""
201
- from lamindb_setup._setup_user import logout
202
-
203
- return logout()
204
-
205
-
206
208
  @main.command()
207
209
  @click.argument("entity", type=str)
208
- @click.option("--uid", help="Filter by creator")
209
- @click.option("--key", help="The key for the entity")
210
- def get(entity: str, uid: str = None, key: str = None):
210
+ @click.option("--uid", help="The uid for the entity.")
211
+ @click.option("--key", help="The key for the entity.")
212
+ @click.option(
213
+ "--with-env", is_flag=True, help="Also return the environment for a tranform."
214
+ )
215
+ def get(entity: str, uid: str = None, key: str = None, with_env: bool = False):
211
216
  """Query an entity.
212
217
 
213
- Pass a lamin.ai URL, 'artifact', or 'transform', for example:
218
+ Pass a URL, `artifact`, or `transform`. For example:
214
219
 
215
220
  ```
216
221
  lamin get https://lamin.ai/account/instance/artifact/e2G7k9EVul4JbfsEYAy5
@@ -218,11 +223,12 @@ def get(entity: str, uid: str = None, key: str = None):
218
223
  lamin get artifact --uid e2G7k9EVul4JbfsEYAy5
219
224
  lamin get transform --key analysis.ipynb
220
225
  lamin get transform --uid Vul4JbfsEYAy5
226
+ lamin get transform --uid Vul4JbfsEYAy5 --with-env
221
227
  ```
222
228
  """
223
229
  from lamin_cli._get import get
224
230
 
225
- return get(entity, uid, key)
231
+ return get(entity, uid=uid, key=key, with_env=with_env)
226
232
 
227
233
 
228
234
  @main.command()
@@ -265,16 +271,6 @@ def set_(setting: str, value: bool):
265
271
  main.add_command(migrate)
266
272
 
267
273
 
268
- @main.command()
269
- @click.argument("action", type=click.Choice(["view"]))
270
- def schema(action: str):
271
- """View schema."""
272
- from lamindb_setup._schema import view
273
-
274
- if action == "view":
275
- return view()
276
-
277
-
278
274
  # https://stackoverflow.com/questions/57810659/automatically-generate-all-help-documentation-for-click-commands
279
275
  # https://claude.ai/chat/73c28487-bec3-4073-8110-50d1a2dd6b84
280
276
  def _generate_help():
@@ -15,7 +15,7 @@ def decompose_url(url: str) -> Tuple[str, str, str]:
15
15
  return instance_slug, entity, uid
16
16
 
17
17
 
18
- def get(entity: str, uid: str = None, key: str = None):
18
+ def get(entity: str, uid: str = None, key: str = None, with_env: bool = False):
19
19
  if entity.startswith("https://lamin.ai"):
20
20
  url = entity
21
21
  instance_slug, entity, uid = decompose_url(url)
@@ -41,6 +41,9 @@ def get(entity: str, uid: str = None, key: str = None):
41
41
  import lamindb as ln
42
42
  from lamindb._finish import script_to_notebook
43
43
 
44
+ # below is to silence warnings about missing run inputs
45
+ ln.settings.track_run_inputs = False
46
+
44
47
  if entity == "transform":
45
48
  transform = (
46
49
  ln.Transform.get(uid) if uid is not None else ln.Transform.get(key=key)
@@ -60,6 +63,19 @@ def get(entity: str, uid: str = None, key: str = None):
60
63
  else:
61
64
  raise ValueError("No source code available for this transform.")
62
65
  logger.important(target_filename)
66
+ if with_env:
67
+ if (
68
+ transform.latest_run is not None
69
+ and transform.latest_run.environment is not None
70
+ ):
71
+ filepath_env_cache = transform.latest_run.environment.cache()
72
+ target_env_filename = (
73
+ ".".join(target_filename.split(".")[:-1]) + "__requirements.txt"
74
+ )
75
+ filepath_env_cache.rename(target_env_filename)
76
+ logger.important(target_env_filename)
77
+ else:
78
+ logger.warning("latest transform run with environment doesn't exist")
63
79
  elif entity == "artifact":
64
80
  artifact = ln.Artifact.get(uid) if uid is not None else ln.Artifact.get(key=key)
65
81
  cache_path = artifact.cache()
@@ -1,5 +1,6 @@
1
1
  import os
2
2
  from datetime import datetime, timedelta, timezone
3
+ from lamindb_setup import settings
3
4
  from lamindb_setup.core._hub_client import connect_hub_with_auth
4
5
  from lamindb_setup.core._hub_core import create_api_key
5
6
 
@@ -13,13 +14,20 @@ def test_cli_login():
13
14
  exit_status = os.system("lamin login testuser1")
14
15
  assert exit_status == 0
15
16
 
16
- exit_status = os.system(
17
- "lamin login testuser1 --key cEvcwMJFX4OwbsYVaMt2Os6GxxGgDUlBGILs2RyS"
18
- )
17
+ assert settings.user.handle == "testuser1"
18
+ password = settings.user.password
19
+ assert password is not None
20
+
21
+ exit_status = os.system(f"lamin login testuser1 --key {password}")
19
22
  assert exit_status == 0
20
23
 
21
24
 
22
25
  def test_cli_login_api_key():
26
+ settings._user_settings = None # this is to refresh a settings instance
27
+ assert settings.user.handle == "testuser1"
28
+ password = settings.user.password
29
+ assert password is not None
30
+
23
31
  expires_at = datetime.now(tz=timezone.utc) + timedelta(days=1)
24
32
  api_key = create_api_key(
25
33
  {
@@ -35,8 +43,18 @@ def test_cli_login_api_key():
35
43
  exit_status = os.system("lamin login")
36
44
  assert exit_status == 0
37
45
 
46
+ settings._user_settings = None
47
+ assert settings.user.handle == "testuser1"
48
+ assert settings.user.api_key == api_key
49
+
38
50
  hub = connect_hub_with_auth()
39
51
  hub.table("api_key").delete().eq("description", "test_cli_login_api_key").execute()
40
52
  hub.auth.sign_out({"scope": "local"})
41
53
 
42
- os.system("lamin login testuser1@lamin.ai")
54
+ exit_status = os.system(f"lamin login testuser1@lamin.ai --key {password}")
55
+ assert exit_status == 0
56
+
57
+ settings._user_settings = None
58
+ assert settings.user.handle == "testuser1"
59
+ assert settings.user.api_key is None
60
+ assert settings.user.password == password
@@ -14,7 +14,8 @@ def test_decompose_url():
14
14
  def test_get_transform():
15
15
  result = subprocess.run(
16
16
  "lamin get"
17
- " 'https://lamin.ai/laminlabs/arrayloader-benchmarks/transform/1GCKs8zLtkc85zKv'", # noqa
17
+ " 'https://lamin.ai/laminlabs/arrayloader-benchmarks/transform/1GCKs8zLtkc85zKv'"
18
+ " --with-env", # noqa
18
19
  shell=True,
19
20
  capture_output=True,
20
21
  )
@@ -1,3 +0,0 @@
1
- """Lamin CLI."""
2
-
3
- __version__ = "0.17.2"
File without changes
File without changes
File without changes
File without changes
File without changes