lamin_cli 0.17.3__py2.py3-none-any.whl → 0.17.4__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/_get.py CHANGED
@@ -1,82 +1,82 @@
1
- from __future__ import annotations
2
- from typing import Tuple
3
- from lamin_utils import logger
4
- import lamindb_setup as ln_setup
5
- from pathlib import Path
6
-
7
-
8
- def decompose_url(url: str) -> Tuple[str, str, str]:
9
- assert "transform" in url or "artifact" in url
10
- for entity in ["transform", "artifact"]:
11
- if entity in url:
12
- break
13
- uid = url.split(f"{entity}/")[1]
14
- instance_slug = "/".join(url.replace("https://lamin.ai/", "").split("/")[:2])
15
- return instance_slug, entity, uid
16
-
17
-
18
- def get(entity: str, uid: str = None, key: str = None, with_env: bool = False):
19
- if entity.startswith("https://lamin.ai"):
20
- url = entity
21
- instance_slug, entity, uid = decompose_url(url)
22
- elif entity not in {"artifact", "transform"}:
23
- raise ValueError(
24
- "entity has to be a URL starting with https://lamin.ai or 'artifact' or"
25
- " 'transform'"
26
- )
27
- else:
28
- instance_slug = None
29
-
30
- if instance_slug is not None:
31
- auto_connect = ln_setup.settings.auto_connect
32
- # we don't want to auto-connect when importing lamindb
33
- ln_setup.settings.auto_connect = False
34
-
35
- import lamindb as ln
36
- from lamindb._finish import script_to_notebook
37
-
38
- ln_setup.settings.auto_connect = auto_connect
39
- ln.connect(instance_slug)
40
- else:
41
- import lamindb as ln
42
- from lamindb._finish import script_to_notebook
43
-
44
- # below is to silence warnings about missing run inputs
45
- ln.settings.track_run_inputs = False
46
-
47
- if entity == "transform":
48
- transform = (
49
- ln.Transform.get(uid) if uid is not None else ln.Transform.get(key=key)
50
- )
51
- target_filename = transform.key
52
- if transform._source_code_artifact_id is not None:
53
- # backward compat
54
- filepath_cache = transform._source_code_artifact.cache()
55
- if not target_filename.endswith(transform._source_code_artifact.suffix):
56
- target_filename += transform._source_code_artifact.suffix
57
- filepath_cache.rename(target_filename)
58
- elif transform.source_code is not None:
59
- if transform.key.endswith(".ipynb"):
60
- script_to_notebook(transform, target_filename)
61
- else:
62
- Path(target_filename).write_text(transform.source_code)
63
- else:
64
- raise ValueError("No source code available for this transform.")
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")
79
- elif entity == "artifact":
80
- artifact = ln.Artifact.get(uid) if uid is not None else ln.Artifact.get(key=key)
81
- cache_path = artifact.cache()
82
- logger.important(cache_path)
1
+ from __future__ import annotations
2
+ from typing import Tuple
3
+ from lamin_utils import logger
4
+ import lamindb_setup as ln_setup
5
+ from pathlib import Path
6
+
7
+
8
+ def decompose_url(url: str) -> Tuple[str, str, str]:
9
+ assert "transform" in url or "artifact" in url
10
+ for entity in ["transform", "artifact"]:
11
+ if entity in url:
12
+ break
13
+ uid = url.split(f"{entity}/")[1]
14
+ instance_slug = "/".join(url.replace("https://lamin.ai/", "").split("/")[:2])
15
+ return instance_slug, entity, uid
16
+
17
+
18
+ def get(entity: str, uid: str = None, key: str = None, with_env: bool = False):
19
+ if entity.startswith("https://lamin.ai"):
20
+ url = entity
21
+ instance_slug, entity, uid = decompose_url(url)
22
+ elif entity not in {"artifact", "transform"}:
23
+ raise ValueError(
24
+ "entity has to be a URL starting with https://lamin.ai or 'artifact' or"
25
+ " 'transform'"
26
+ )
27
+ else:
28
+ instance_slug = None
29
+
30
+ if instance_slug is not None:
31
+ auto_connect = ln_setup.settings.auto_connect
32
+ # we don't want to auto-connect when importing lamindb
33
+ ln_setup.settings.auto_connect = False
34
+
35
+ import lamindb as ln
36
+ from lamindb._finish import script_to_notebook
37
+
38
+ ln_setup.settings.auto_connect = auto_connect
39
+ ln.connect(instance_slug)
40
+ else:
41
+ import lamindb as ln
42
+ from lamindb._finish import script_to_notebook
43
+
44
+ # below is to silence warnings about missing run inputs
45
+ ln.settings.track_run_inputs = False
46
+
47
+ if entity == "transform":
48
+ transform = (
49
+ ln.Transform.get(uid) if uid is not None else ln.Transform.get(key=key)
50
+ )
51
+ target_filename = transform.key
52
+ if transform._source_code_artifact_id is not None:
53
+ # backward compat
54
+ filepath_cache = transform._source_code_artifact.cache()
55
+ if not target_filename.endswith(transform._source_code_artifact.suffix):
56
+ target_filename += transform._source_code_artifact.suffix
57
+ filepath_cache.rename(target_filename)
58
+ elif transform.source_code is not None:
59
+ if transform.key.endswith(".ipynb"):
60
+ script_to_notebook(transform, target_filename)
61
+ else:
62
+ Path(target_filename).write_text(transform.source_code)
63
+ else:
64
+ raise ValueError("No source code available for this transform.")
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")
79
+ elif entity == "artifact":
80
+ artifact = ln.Artifact.get(uid) if uid is not None else ln.Artifact.get(key=key)
81
+ cache_path = artifact.cache()
82
+ logger.important(cache_path)
lamin_cli/_migration.py CHANGED
@@ -1,48 +1,48 @@
1
- from __future__ import annotations
2
- import os
3
- from typing import Optional
4
-
5
- if os.environ.get("NO_RICH"):
6
- import click as click
7
- else:
8
- import rich_click as click
9
-
10
-
11
- @click.group()
12
- def migrate():
13
- """Manage migrations."""
14
-
15
-
16
- @migrate.command("create")
17
- def create():
18
- """Create a new migration."""
19
- from lamindb_setup._migrate import migrate
20
-
21
- return migrate.create()
22
-
23
-
24
- @migrate.command("deploy")
25
- def deploy():
26
- """Deploy migrations."""
27
- from lamindb_setup._migrate import migrate
28
-
29
- return migrate.deploy()
30
-
31
-
32
- @migrate.command("squash")
33
- @click.option("--package-name", type=str, default=None)
34
- @click.option("--end-number", type=str, default=None)
35
- @click.option("--start-number", type=str, default=None)
36
- def squash(
37
- package_name: Optional[str],
38
- end_number: Optional[str],
39
- start_number: Optional[str],
40
- ):
41
- """Squash migrations."""
42
- from lamindb_setup._migrate import migrate
43
-
44
- return migrate.squash(
45
- package_name=package_name,
46
- migration_nr=end_number,
47
- start_migration_nr=start_number,
48
- )
1
+ from __future__ import annotations
2
+ import os
3
+ from typing import Optional
4
+
5
+ if os.environ.get("NO_RICH"):
6
+ import click as click
7
+ else:
8
+ import rich_click as click
9
+
10
+
11
+ @click.group()
12
+ def migrate():
13
+ """Manage migrations."""
14
+
15
+
16
+ @migrate.command("create")
17
+ def create():
18
+ """Create a new migration."""
19
+ from lamindb_setup._migrate import migrate
20
+
21
+ return migrate.create()
22
+
23
+
24
+ @migrate.command("deploy")
25
+ def deploy():
26
+ """Deploy migrations."""
27
+ from lamindb_setup._migrate import migrate
28
+
29
+ return migrate.deploy()
30
+
31
+
32
+ @migrate.command("squash")
33
+ @click.option("--package-name", type=str, default=None)
34
+ @click.option("--end-number", type=str, default=None)
35
+ @click.option("--start-number", type=str, default=None)
36
+ def squash(
37
+ package_name: Optional[str],
38
+ end_number: Optional[str],
39
+ start_number: Optional[str],
40
+ ):
41
+ """Squash migrations."""
42
+ from lamindb_setup._migrate import migrate
43
+
44
+ return migrate.squash(
45
+ package_name=package_name,
46
+ migration_nr=end_number,
47
+ start_migration_nr=start_number,
48
+ )
lamin_cli/_save.py CHANGED
@@ -1,111 +1,111 @@
1
- from __future__ import annotations
2
- from pathlib import Path
3
- from typing import Optional, Union
4
- import lamindb_setup as ln_setup
5
- from lamin_utils import logger
6
- import re
7
-
8
-
9
- def get_stem_uid_and_version_from_file(
10
- file_path: Path,
11
- ) -> tuple[str | None, str | None, str | None]:
12
- # line-by-line matching might be faster, but let's go with this for now
13
- with open(file_path) as file:
14
- content = file.read()
15
-
16
- if file_path.suffix == ".py":
17
- uid_pattern = re.compile(r'\.context\.uid\s*=\s*["\']([^"\']+)["\']')
18
- stem_uid_pattern = re.compile(
19
- r'\.transform\.stem_uid\s*=\s*["\']([^"\']+)["\']'
20
- )
21
- version_pattern = re.compile(r'\.transform\.version\s*=\s*["\']([^"\']+)["\']')
22
- elif file_path.suffix == ".ipynb":
23
- uid_pattern = re.compile(r'\.context\.uid\s*=\s*\\["\']([^"\']+)\\["\']')
24
- stem_uid_pattern = re.compile(
25
- r'\.transform\.stem_uid\s*=\s*\\["\']([^"\']+)\\["\']'
26
- )
27
- version_pattern = re.compile(
28
- r'\.transform\.version\s*=\s*\\["\']([^"\']+)\\["\']'
29
- )
30
- else:
31
- raise ValueError("Only .py and .ipynb files are supported.")
32
-
33
- # Search for matches in the entire file content
34
- uid_match = uid_pattern.search(content)
35
- stem_uid_match = stem_uid_pattern.search(content)
36
- version_match = version_pattern.search(content)
37
-
38
- # Extract values if matches are found
39
- uid = uid_match.group(1) if uid_match else None
40
- stem_uid = stem_uid_match.group(1) if stem_uid_match else None
41
- version = version_match.group(1) if version_match else None
42
-
43
- if uid is None and (stem_uid is None or version is None):
44
- raise SystemExit(
45
- "ln.context.uid isn't"
46
- f" set in {file_path}\nCall ln.context.track() and copy/paste the output"
47
- " into the notebook"
48
- )
49
- return uid, stem_uid, version
50
-
51
-
52
- def save_from_filepath_cli(
53
- filepath: Union[str, Path], key: Optional[str], description: Optional[str]
54
- ) -> Optional[str]:
55
- if not isinstance(filepath, Path):
56
- filepath = Path(filepath)
57
-
58
- # this will be gone once we get rid of lamin load or enable loading multiple
59
- # instances sequentially
60
- auto_connect_state = ln_setup.settings.auto_connect
61
- ln_setup.settings.auto_connect = True
62
-
63
- import lamindb as ln
64
- from lamindb._finish import save_context_core
65
-
66
- ln_setup.settings.auto_connect = auto_connect_state
67
-
68
- if filepath.suffix not in {".py", ".ipynb"}:
69
- if key is None and description is None:
70
- logger.error("Please pass a key or description via --key or --description")
71
- return "missing-key-or-description"
72
- artifact = ln.Artifact(filepath, key=key, description=description)
73
- artifact.save()
74
- slug = ln_setup.settings.instance.slug
75
- logger.important(f"saved: {artifact}")
76
- logger.important(f"storage path: {artifact.path}")
77
- if ln_setup.settings.instance.is_remote:
78
- logger.important(f"go to: https://lamin.ai/{slug}/artifact/{artifact.uid}")
79
- if ln_setup.settings.storage.type == "s3":
80
- logger.important(f"storage url: {artifact.path.to_url()}")
81
- return None
82
- else:
83
- # consider notebooks & scripts a transform
84
- uid, stem_uid, transform_version = get_stem_uid_and_version_from_file(filepath)
85
- if uid is not None:
86
- transform = ln.Transform.filter(uid=uid).one_or_none()
87
- if transform is None:
88
- logger.error(
89
- f"Did not find uid '{uid}'"
90
- " in Transform registry. Did you run ln.context.track()?"
91
- )
92
- return "not-tracked-in-transform-registry"
93
- else:
94
- transform = ln.Transform.get(
95
- uid__startswith=stem_uid, version=transform_version
96
- )
97
- # latest run of this transform by user
98
- run = ln.Run.filter(transform=transform).order_by("-started_at").first()
99
- if run.created_by.id != ln_setup.settings.user.id:
100
- response = input(
101
- "You are trying to save a transform created by another user: Source and"
102
- " report files will be tagged with *your* user id. Proceed? (y/n)"
103
- )
104
- if response != "y":
105
- return "aborted-save-notebook-created-by-different-user"
106
- return save_context_core(
107
- run=run,
108
- transform=transform,
109
- filepath=filepath,
110
- from_cli=True,
111
- )
1
+ from __future__ import annotations
2
+ from pathlib import Path
3
+ from typing import Optional, Union
4
+ import lamindb_setup as ln_setup
5
+ from lamin_utils import logger
6
+ import re
7
+
8
+
9
+ def get_stem_uid_and_version_from_file(
10
+ file_path: Path,
11
+ ) -> tuple[str | None, str | None, str | None]:
12
+ # line-by-line matching might be faster, but let's go with this for now
13
+ with open(file_path) as file:
14
+ content = file.read()
15
+
16
+ if file_path.suffix == ".py":
17
+ uid_pattern = re.compile(r'\.context\.uid\s*=\s*["\']([^"\']+)["\']')
18
+ stem_uid_pattern = re.compile(
19
+ r'\.transform\.stem_uid\s*=\s*["\']([^"\']+)["\']'
20
+ )
21
+ version_pattern = re.compile(r'\.transform\.version\s*=\s*["\']([^"\']+)["\']')
22
+ elif file_path.suffix == ".ipynb":
23
+ uid_pattern = re.compile(r'\.context\.uid\s*=\s*\\["\']([^"\']+)\\["\']')
24
+ stem_uid_pattern = re.compile(
25
+ r'\.transform\.stem_uid\s*=\s*\\["\']([^"\']+)\\["\']'
26
+ )
27
+ version_pattern = re.compile(
28
+ r'\.transform\.version\s*=\s*\\["\']([^"\']+)\\["\']'
29
+ )
30
+ else:
31
+ raise ValueError("Only .py and .ipynb files are supported.")
32
+
33
+ # Search for matches in the entire file content
34
+ uid_match = uid_pattern.search(content)
35
+ stem_uid_match = stem_uid_pattern.search(content)
36
+ version_match = version_pattern.search(content)
37
+
38
+ # Extract values if matches are found
39
+ uid = uid_match.group(1) if uid_match else None
40
+ stem_uid = stem_uid_match.group(1) if stem_uid_match else None
41
+ version = version_match.group(1) if version_match else None
42
+
43
+ if uid is None and (stem_uid is None or version is None):
44
+ raise SystemExit(
45
+ "ln.context.uid isn't"
46
+ f" set in {file_path}\nCall ln.context.track() and copy/paste the output"
47
+ " into the notebook"
48
+ )
49
+ return uid, stem_uid, version
50
+
51
+
52
+ def save_from_filepath_cli(
53
+ filepath: Union[str, Path], key: Optional[str], description: Optional[str]
54
+ ) -> Optional[str]:
55
+ if not isinstance(filepath, Path):
56
+ filepath = Path(filepath)
57
+
58
+ # this will be gone once we get rid of lamin load or enable loading multiple
59
+ # instances sequentially
60
+ auto_connect_state = ln_setup.settings.auto_connect
61
+ ln_setup.settings.auto_connect = True
62
+
63
+ import lamindb as ln
64
+ from lamindb._finish import save_context_core
65
+
66
+ ln_setup.settings.auto_connect = auto_connect_state
67
+
68
+ if filepath.suffix not in {".py", ".ipynb"}:
69
+ if key is None and description is None:
70
+ logger.error("Please pass a key or description via --key or --description")
71
+ return "missing-key-or-description"
72
+ artifact = ln.Artifact(filepath, key=key, description=description)
73
+ artifact.save()
74
+ slug = ln_setup.settings.instance.slug
75
+ logger.important(f"saved: {artifact}")
76
+ logger.important(f"storage path: {artifact.path}")
77
+ if ln_setup.settings.instance.is_remote:
78
+ logger.important(f"go to: https://lamin.ai/{slug}/artifact/{artifact.uid}")
79
+ if ln_setup.settings.storage.type == "s3":
80
+ logger.important(f"storage url: {artifact.path.to_url()}")
81
+ return None
82
+ else:
83
+ # consider notebooks & scripts a transform
84
+ uid, stem_uid, transform_version = get_stem_uid_and_version_from_file(filepath)
85
+ if uid is not None:
86
+ transform = ln.Transform.filter(uid=uid).one_or_none()
87
+ if transform is None:
88
+ logger.error(
89
+ f"Did not find uid '{uid}'"
90
+ " in Transform registry. Did you run ln.context.track()?"
91
+ )
92
+ return "not-tracked-in-transform-registry"
93
+ else:
94
+ transform = ln.Transform.get(
95
+ uid__startswith=stem_uid, version=transform_version
96
+ )
97
+ # latest run of this transform by user
98
+ run = ln.Run.filter(transform=transform).order_by("-started_at").first()
99
+ if run.created_by.id != ln_setup.settings.user.id:
100
+ response = input(
101
+ "You are trying to save a transform created by another user: Source and"
102
+ " report files will be tagged with *your* user id. Proceed? (y/n)"
103
+ )
104
+ if response != "y":
105
+ return "aborted-save-notebook-created-by-different-user"
106
+ return save_context_core(
107
+ run=run,
108
+ transform=transform,
109
+ filepath=filepath,
110
+ from_cli=True,
111
+ )