decompressed-cli 0.1.0__tar.gz → 0.1.1__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 (19) hide show
  1. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/PKG-INFO +1 -1
  2. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/pyproject.toml +1 -1
  3. decompressed_cli-0.1.1/src/decompressed_cli/commands/imports_cmd.py +220 -0
  4. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli/main.py +2 -1
  5. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli.egg-info/PKG-INFO +1 -1
  6. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli.egg-info/SOURCES.txt +1 -0
  7. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/README.md +0 -0
  8. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/setup.cfg +0 -0
  9. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli/__init__.py +0 -0
  10. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli/commands/__init__.py +0 -0
  11. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli/commands/config_cmd.py +0 -0
  12. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli/commands/data_cmd.py +0 -0
  13. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli/commands/datasets_cmd.py +0 -0
  14. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli/commands/versions_cmd.py +0 -0
  15. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli/config.py +0 -0
  16. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli.egg-info/dependency_links.txt +0 -0
  17. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli.egg-info/entry_points.txt +0 -0
  18. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli.egg-info/requires.txt +0 -0
  19. {decompressed_cli-0.1.0 → decompressed_cli-0.1.1}/src/decompressed_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: decompressed-cli
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: CLI for Decompressed - Git-like version control for vector datasets
5
5
  Author-email: Decompressed <support@decompressed.io>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "decompressed-cli"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "CLI for Decompressed - Git-like version control for vector datasets"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -0,0 +1,220 @@
1
+ """Import commands for pulling vectors from external databases."""
2
+
3
+ import time
4
+ import typer
5
+ from rich.console import Console
6
+ from rich.table import Table
7
+ from rich.panel import Panel
8
+ from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn
9
+
10
+ from ..config import get_client
11
+
12
+ app = typer.Typer(no_args_is_help=True)
13
+ console = Console()
14
+
15
+
16
+ @app.command("pull")
17
+ def pull(
18
+ connector: str = typer.Argument(..., help="Connector name or ID to import from"),
19
+ dataset_name: str = typer.Argument(..., help="Name for the new dataset"),
20
+ project: str = typer.Option(None, "--project", "-p", help="Project name or ID"),
21
+ no_metadata: bool = typer.Option(False, "--no-metadata", help="Skip importing metadata"),
22
+ batch_size: int = typer.Option(100, "--batch-size", "-b", help="Vectors per batch"),
23
+ no_wait: bool = typer.Option(False, "--no-wait", help="Don't wait for completion"),
24
+ ):
25
+ """
26
+ Pull vectors from an external database into a new dataset.
27
+
28
+ Example:
29
+ dcp imports pull pinecone-prod my-backup
30
+ dcp imports pull qdrant-index imported-vectors --project ml-team
31
+ """
32
+ try:
33
+ client = get_client()
34
+
35
+ console.print(f"[cyan]Connecting to connector:[/cyan] {connector}")
36
+
37
+ # Initialize import
38
+ session = client.imports.init(
39
+ connector_id=connector,
40
+ dataset_name=dataset_name,
41
+ project=project,
42
+ include_metadata=not no_metadata,
43
+ batch_size=batch_size,
44
+ )
45
+
46
+ console.print(Panel(
47
+ f"[green]✓[/green] Connected to [cyan]{session.connector_type}[/cyan]\n"
48
+ f"[dim]Estimated vectors:[/dim] {session.estimated_vectors:,}\n"
49
+ f"[dim]Dimension:[/dim] {session.dimension}\n"
50
+ f"[dim]Dataset ID:[/dim] {session.dataset_id}",
51
+ title="Import Initialized",
52
+ border_style="green"
53
+ ))
54
+
55
+ # Start the import
56
+ result = client.imports.start(session.import_session_id)
57
+ console.print(f"[cyan]Import job started:[/cyan] {result.job_id[:8]}...")
58
+
59
+ if no_wait:
60
+ console.print(f"\n[yellow]Import running in background.[/yellow]")
61
+ console.print(f"Check status: [cyan]dcp imports status {session.import_session_id}[/cyan]")
62
+ return
63
+
64
+ # Wait with progress
65
+ with Progress(
66
+ SpinnerColumn(),
67
+ TextColumn("[progress.description]{task.description}"),
68
+ BarColumn(),
69
+ TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
70
+ console=console,
71
+ ) as progress:
72
+ task = progress.add_task("Importing vectors...", total=100)
73
+
74
+ while True:
75
+ job = client.imports.status(session.import_session_id)
76
+
77
+ if job.progress:
78
+ progress.update(task, completed=job.progress)
79
+
80
+ if job.status == "completed":
81
+ progress.update(task, completed=100)
82
+ break
83
+ elif job.status == "failed":
84
+ console.print(f"\n[red]✗ Import failed:[/red] {job.error_message}")
85
+ raise typer.Exit(1)
86
+
87
+ time.sleep(2)
88
+
89
+ console.print(Panel(
90
+ f"[green]✓[/green] Import complete!\n"
91
+ f"[dim]Dataset:[/dim] {dataset_name}\n"
92
+ f"[dim]Dataset ID:[/dim] {session.dataset_id}",
93
+ title="Success",
94
+ border_style="green"
95
+ ))
96
+
97
+ except ValueError as e:
98
+ console.print(f"[red]Error:[/red] {e}")
99
+ raise typer.Exit(1)
100
+ except Exception as e:
101
+ console.print(f"[red]Error:[/red] {e}")
102
+ raise typer.Exit(1)
103
+
104
+
105
+ @app.command("append")
106
+ def append(
107
+ connector: str = typer.Argument(..., help="Connector name or ID to import from"),
108
+ dataset: str = typer.Argument(..., help="Existing dataset name or ID to append to"),
109
+ no_metadata: bool = typer.Option(False, "--no-metadata", help="Skip importing metadata"),
110
+ batch_size: int = typer.Option(100, "--batch-size", "-b", help="Vectors per batch"),
111
+ no_wait: bool = typer.Option(False, "--no-wait", help="Don't wait for completion"),
112
+ ):
113
+ """
114
+ Append vectors from an external database to an existing dataset.
115
+
116
+ Example:
117
+ dcp imports append pinecone-prod my-dataset
118
+ """
119
+ try:
120
+ client = get_client()
121
+
122
+ # Resolve dataset ID
123
+ ds = client.datasets.get(dataset)
124
+
125
+ console.print(f"[cyan]Connecting to connector:[/cyan] {connector}")
126
+ console.print(f"[cyan]Appending to dataset:[/cyan] {ds.name} (v{ds.current_version})")
127
+
128
+ # Initialize append import
129
+ session = client.imports.init_append(
130
+ connector_id=connector,
131
+ dataset_id=ds.id,
132
+ include_metadata=not no_metadata,
133
+ batch_size=batch_size,
134
+ )
135
+
136
+ console.print(Panel(
137
+ f"[green]✓[/green] Connected to [cyan]{session.connector_type}[/cyan]\n"
138
+ f"[dim]Estimated vectors:[/dim] {session.estimated_vectors:,}\n"
139
+ f"[dim]Dimension:[/dim] {session.dimension}",
140
+ title="Append Import Initialized",
141
+ border_style="green"
142
+ ))
143
+
144
+ # Start the import
145
+ result = client.imports.start(session.import_session_id)
146
+ console.print(f"[cyan]Import job started:[/cyan] {result.job_id[:8]}...")
147
+
148
+ if no_wait:
149
+ console.print(f"\n[yellow]Import running in background.[/yellow]")
150
+ console.print(f"Check status: [cyan]dcp imports status {session.import_session_id}[/cyan]")
151
+ return
152
+
153
+ # Wait with progress
154
+ with Progress(
155
+ SpinnerColumn(),
156
+ TextColumn("[progress.description]{task.description}"),
157
+ BarColumn(),
158
+ TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
159
+ console=console,
160
+ ) as progress:
161
+ task = progress.add_task("Importing vectors...", total=100)
162
+
163
+ while True:
164
+ job = client.imports.status(session.import_session_id)
165
+
166
+ if job.progress:
167
+ progress.update(task, completed=job.progress)
168
+
169
+ if job.status == "completed":
170
+ progress.update(task, completed=100)
171
+ break
172
+ elif job.status == "failed":
173
+ console.print(f"\n[red]✗ Import failed:[/red] {job.error_message}")
174
+ raise typer.Exit(1)
175
+
176
+ time.sleep(2)
177
+
178
+ console.print(f"[green]✓[/green] Appended vectors to [cyan]{ds.name}[/cyan]")
179
+
180
+ except ValueError as e:
181
+ console.print(f"[red]Error:[/red] {e}")
182
+ raise typer.Exit(1)
183
+ except Exception as e:
184
+ console.print(f"[red]Error:[/red] {e}")
185
+ raise typer.Exit(1)
186
+
187
+
188
+ @app.command("status")
189
+ def status(
190
+ session_id: str = typer.Argument(..., help="Import session ID"),
191
+ ):
192
+ """Check status of an import job."""
193
+ try:
194
+ client = get_client()
195
+ job = client.imports.status(session_id)
196
+
197
+ status_color = {
198
+ "initialized": "yellow",
199
+ "in_progress": "cyan",
200
+ "completed": "green",
201
+ "failed": "red",
202
+ }.get(job.status, "white")
203
+
204
+ panel_content = f"""[cyan]Session ID:[/cyan] {job.import_session_id}
205
+ [cyan]Dataset ID:[/cyan] {job.dataset_id or 'N/A'}
206
+ [cyan]Status:[/cyan] [{status_color}]{job.status}[/{status_color}]
207
+ [cyan]Progress:[/cyan] {job.progress or 0}%
208
+ [cyan]Job ID:[/cyan] {job.job_id or 'N/A'}"""
209
+
210
+ if job.error_message:
211
+ panel_content += f"\n[red]Error:[/red] {job.error_message}"
212
+
213
+ console.print(Panel(panel_content, title="Import Status", border_style=status_color))
214
+
215
+ except ValueError as e:
216
+ console.print(f"[red]Error:[/red] {e}")
217
+ raise typer.Exit(1)
218
+ except Exception as e:
219
+ console.print(f"[red]Error:[/red] {e}")
220
+ raise typer.Exit(1)
@@ -4,7 +4,7 @@ import typer
4
4
  from rich.console import Console
5
5
 
6
6
  from . import __version__
7
- from .commands import config_cmd, datasets_cmd, versions_cmd, data_cmd
7
+ from .commands import config_cmd, datasets_cmd, versions_cmd, data_cmd, imports_cmd
8
8
 
9
9
  app = typer.Typer(
10
10
  name="dcp",
@@ -17,6 +17,7 @@ console = Console()
17
17
  app.add_typer(config_cmd.app, name="config", help="Manage CLI configuration")
18
18
  app.add_typer(datasets_cmd.app, name="datasets", help="Manage datasets")
19
19
  app.add_typer(data_cmd.app, name="data", help="Pull/push data (alias)")
20
+ app.add_typer(imports_cmd.app, name="imports", help="Import vectors from external databases")
20
21
 
21
22
  # Register top-level versioning commands
22
23
  app.command("log")(versions_cmd.log)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: decompressed-cli
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: CLI for Decompressed - Git-like version control for vector datasets
5
5
  Author-email: Decompressed <support@decompressed.io>
6
6
  License: MIT
@@ -13,4 +13,5 @@ src/decompressed_cli/commands/__init__.py
13
13
  src/decompressed_cli/commands/config_cmd.py
14
14
  src/decompressed_cli/commands/data_cmd.py
15
15
  src/decompressed_cli/commands/datasets_cmd.py
16
+ src/decompressed_cli/commands/imports_cmd.py
16
17
  src/decompressed_cli/commands/versions_cmd.py