lamin_cli 1.11.0__py2.py3-none-any.whl → 1.12.1__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/_io.py CHANGED
@@ -1,144 +1,147 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- import os
5
- import subprocess
6
- import sys
7
- import tempfile
8
- from pathlib import Path
9
-
10
- import lamindb_setup as ln_setup
11
-
12
- from lamin_cli.clone._clone_verification import (
13
- _count_instance_records,
14
- )
15
-
16
- if os.environ.get("NO_RICH"):
17
- import click as click
18
- else:
19
- import rich_click as click
20
-
21
-
22
- @click.group()
23
- def io():
24
- """Import and export instances."""
25
-
26
-
27
- # fmt: off
28
- @io.command("snapshot")
29
- @click.option("--upload/--no-upload", is_flag=True, help="Whether to upload the snapshot.", default=True)
30
- @click.option("--track/--no-track", is_flag=True, help="Whether to track snapshot generation.", default=True)
31
- # fmt: on
32
- def snapshot(upload: bool, track: bool) -> None:
33
- """Create a SQLite snapshot of the connected instance."""
34
- if not ln_setup.settings._instance_exists:
35
- raise click.ClickException(
36
- "Not connected to an instance. Please run: lamin connect account/name"
37
- )
38
-
39
- instance_owner = ln_setup.settings.instance.owner
40
- instance_name = ln_setup.settings.instance.name
41
-
42
- ln_setup.connect(f"{instance_owner}/{instance_name}", use_root_db_user=True)
43
-
44
- import lamindb as ln
45
-
46
- original_counts = _count_instance_records()
47
-
48
- modules_without_lamindb = ln_setup.settings.instance.modules
49
- modules_complete = modules_without_lamindb.copy()
50
- modules_complete.add("lamindb")
51
-
52
-
53
- with tempfile.TemporaryDirectory() as export_dir:
54
- if track:
55
- ln.track()
56
- ln_setup.io.export_db(module_names=modules_complete, output_dir=export_dir)
57
- if track:
58
- ln.finish()
59
-
60
- script_path = (
61
- Path(__file__).parent / "clone" / "create_sqlite_clone_and_import_db.py"
62
- )
63
- result = subprocess.run(
64
- [
65
- sys.executable,
66
- str(script_path),
67
- "--instance-name",
68
- instance_name,
69
- "--export-dir",
70
- export_dir,
71
- "--modules",
72
- ",".join(modules_without_lamindb),
73
- "--original-counts",
74
- json.dumps(original_counts),
75
- ],
76
- check=False,
77
- stderr=subprocess.PIPE,
78
- text=True,
79
- cwd=Path.cwd(),
80
- )
81
- if result.returncode != 0:
82
- try:
83
- mismatches = json.loads(result.stderr.strip())
84
- error_msg = "Record count mismatch detected:\n" + "\n".join(
85
- [f" {table}: original={orig}, clone={clone}"
86
- for table, (orig, clone) in mismatches.items()]
87
- )
88
- raise click.ClickException(error_msg)
89
- except (json.JSONDecodeError, AttributeError, ValueError, TypeError):
90
- raise click.ClickException(f"Clone verification failed:\n{result.stderr}") from None
91
-
92
-
93
- ln_setup.connect(f"{instance_owner}/{instance_name}", use_root_db_user=True)
94
- if upload:
95
- ln_setup.core._clone.upload_sqlite_clone(
96
- local_sqlite_path=f"{instance_name}-clone/.lamindb/lamin.db",
97
- compress=True,
98
- )
99
-
100
- ln_setup.disconnect()
101
-
102
-
103
- # fmt: off
104
- @io.command("exportdb")
105
- @click.option("--modules", type=str, default=None, help="Comma-separated list of modules to export (e.g., 'lamindb,bionty').",)
106
- @click.option("--output-dir", type=str, help="Output directory for exported parquet files.")
107
- @click.option("--max-workers", type=int, default=8, help="Number of parallel workers.")
108
- @click.option("--chunk-size", type=int, default=500_000, help="Number of rows per chunk for large tables.")
109
- # fmt: on
110
- def exportdb(modules: str | None, output_dir: str, max_workers: int, chunk_size: int):
111
- """Export registry tables to parquet files."""
112
- if not ln_setup.settings._instance_exists:
113
- raise click.ClickException(
114
- "Not connected to an instance. Please run: lamin connect account/name"
115
- )
116
-
117
- module_list = modules.split(",") if modules else None
118
- ln_setup.io.export_db(
119
- module_names=module_list,
120
- output_dir=output_dir,
121
- max_workers=max_workers,
122
- chunk_size=chunk_size,
123
- )
124
-
125
-
126
- # fmt: off
127
- @io.command("importdb")
128
- @click.option("--modules", type=str, default=None, help="Comma-separated list of modules to import (e.g., 'lamindb,bionty').")
129
- @click.option("--input-dir", type=str, help="Input directory containing exported parquet files.")
130
- @click.option("--if-exists", type=click.Choice(["fail", "replace", "append"]), default="replace", help="How to handle existing data.")
131
- # fmt: on
132
- def importdb(modules: str | None, input_dir: str, if_exists: str):
133
- """Import registry tables from parquet files."""
134
- if not ln_setup.settings._instance_exists:
135
- raise click.ClickException(
136
- "Not connected to an instance. Please run: lamin connect account/name"
137
- )
138
-
139
- module_list = modules.split(",") if modules else None
140
- ln_setup.io.import_db(
141
- module_names=module_list,
142
- input_dir=input_dir,
143
- if_exists=if_exists,
144
- )
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import subprocess
6
+ import sys
7
+ import tempfile
8
+ from pathlib import Path
9
+
10
+ import lamindb_setup as ln_setup
11
+
12
+ from lamin_cli.clone._clone_verification import (
13
+ _count_instance_records,
14
+ )
15
+
16
+ if os.environ.get("NO_RICH"):
17
+ import click as click
18
+ else:
19
+ import rich_click as click
20
+
21
+
22
+ @click.group()
23
+ def io():
24
+ """Import and export instances."""
25
+
26
+
27
+ # fmt: off
28
+ @io.command("snapshot")
29
+ @click.option("--upload/--no-upload", is_flag=True, help="Whether to upload the snapshot.", default=True)
30
+ @click.option("--track/--no-track", is_flag=True, help="Whether to track snapshot generation.", default=True)
31
+ # fmt: on
32
+ def snapshot(upload: bool, track: bool) -> None:
33
+ """Create a SQLite snapshot of the connected instance."""
34
+ from lamindb_setup.io import export_db
35
+ if not ln_setup.settings._instance_exists:
36
+ raise click.ClickException(
37
+ "Not connected to an instance. Please run: lamin connect account/name"
38
+ )
39
+
40
+ instance_owner = ln_setup.settings.instance.owner
41
+ instance_name = ln_setup.settings.instance.name
42
+
43
+ ln_setup.connect(f"{instance_owner}/{instance_name}", use_root_db_user=True)
44
+
45
+ import lamindb as ln
46
+
47
+ original_counts = _count_instance_records()
48
+
49
+ modules_without_lamindb = ln_setup.settings.instance.modules
50
+ modules_complete = modules_without_lamindb.copy()
51
+ modules_complete.add("lamindb")
52
+
53
+
54
+ with tempfile.TemporaryDirectory() as export_dir:
55
+ if track:
56
+ ln.track("o39ljgTzvFew", key="__lamin_io_snapshot__.py")
57
+ export_db(module_names=modules_complete, output_dir=export_dir)
58
+ if track:
59
+ ln.finish()
60
+
61
+ script_path = (
62
+ Path(__file__).parent / "clone" / "create_sqlite_clone_and_import_db.py"
63
+ )
64
+ result = subprocess.run(
65
+ [
66
+ sys.executable,
67
+ str(script_path),
68
+ "--instance-name",
69
+ instance_name,
70
+ "--export-dir",
71
+ export_dir,
72
+ "--modules",
73
+ ",".join(modules_without_lamindb),
74
+ "--original-counts",
75
+ json.dumps(original_counts),
76
+ ],
77
+ check=False,
78
+ stderr=subprocess.PIPE,
79
+ text=True,
80
+ cwd=Path.cwd(),
81
+ )
82
+ if result.returncode != 0:
83
+ try:
84
+ mismatches = json.loads(result.stderr.strip())
85
+ error_msg = "Record count mismatch detected:\n" + "\n".join(
86
+ [f" {table}: original={orig}, clone={clone}"
87
+ for table, (orig, clone) in mismatches.items()]
88
+ )
89
+ raise click.ClickException(error_msg)
90
+ except (json.JSONDecodeError, AttributeError, ValueError, TypeError):
91
+ raise click.ClickException(f"Clone verification failed:\n{result.stderr}") from None
92
+
93
+
94
+ ln_setup.connect(f"{instance_owner}/{instance_name}", use_root_db_user=True)
95
+ if upload:
96
+ ln_setup.core._clone.upload_sqlite_clone(
97
+ local_sqlite_path=f"{instance_name}-clone/.lamindb/lamin.db",
98
+ compress=True,
99
+ )
100
+
101
+ ln_setup.disconnect()
102
+
103
+
104
+ # fmt: off
105
+ @io.command("exportdb")
106
+ @click.option("--modules", type=str, default=None, help="Comma-separated list of modules to export (e.g., 'lamindb,bionty').",)
107
+ @click.option("--output-dir", type=str, help="Output directory for exported parquet files.")
108
+ @click.option("--max-workers", type=int, default=8, help="Number of parallel workers.")
109
+ @click.option("--chunk-size", type=int, default=500_000, help="Number of rows per chunk for large tables.")
110
+ # fmt: on
111
+ def exportdb(modules: str | None, output_dir: str, max_workers: int, chunk_size: int):
112
+ """Export registry tables to parquet files."""
113
+ from lamindb_setup.io import export_db
114
+ if not ln_setup.settings._instance_exists:
115
+ raise click.ClickException(
116
+ "Not connected to an instance. Please run: lamin connect account/name"
117
+ )
118
+
119
+ module_list = modules.split(",") if modules else None
120
+ export_db(
121
+ module_names=module_list,
122
+ output_dir=output_dir,
123
+ max_workers=max_workers,
124
+ chunk_size=chunk_size,
125
+ )
126
+
127
+
128
+ # fmt: off
129
+ @io.command("importdb")
130
+ @click.option("--modules", type=str, default=None, help="Comma-separated list of modules to import (e.g., 'lamindb,bionty').")
131
+ @click.option("--input-dir", type=str, help="Input directory containing exported parquet files.")
132
+ @click.option("--if-exists", type=click.Choice(["fail", "replace", "append"]), default="replace", help="How to handle existing data.")
133
+ # fmt: on
134
+ def importdb(modules: str | None, input_dir: str, if_exists: str):
135
+ """Import registry tables from parquet files."""
136
+ from lamindb_setup.io import import_db
137
+ if not ln_setup.settings._instance_exists:
138
+ raise click.ClickException(
139
+ "Not connected to an instance. Please run: lamin connect account/name"
140
+ )
141
+
142
+ module_list = modules.split(",") if modules else None
143
+ import_db(
144
+ module_names=module_list,
145
+ input_dir=input_dir,
146
+ if_exists=if_exists,
147
+ )