databar 2.0.0__tar.gz → 2.0.2__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.
- {databar-2.0.0/src/databar.egg-info → databar-2.0.2}/PKG-INFO +2 -2
- {databar-2.0.0 → databar-2.0.2}/README.md +1 -1
- {databar-2.0.0 → databar-2.0.2}/pyproject.toml +1 -1
- {databar-2.0.0 → databar-2.0.2}/src/databar/__init__.py +3 -1
- {databar-2.0.0 → databar-2.0.2}/src/databar/cli/_auth.py +15 -1
- {databar-2.0.0 → databar-2.0.2}/src/databar/cli/enrichments.py +14 -5
- {databar-2.0.0 → databar-2.0.2}/src/databar/cli/tables.py +9 -9
- {databar-2.0.0 → databar-2.0.2}/src/databar/cli/tasks.py +1 -1
- {databar-2.0.0 → databar-2.0.2}/src/databar/cli/waterfalls.py +13 -4
- {databar-2.0.0 → databar-2.0.2}/src/databar/client.py +13 -12
- {databar-2.0.0 → databar-2.0.2}/src/databar/models.py +24 -1
- {databar-2.0.0 → databar-2.0.2/src/databar.egg-info}/PKG-INFO +2 -2
- {databar-2.0.0 → databar-2.0.2}/tests/test_cli.py +2 -2
- {databar-2.0.0 → databar-2.0.2}/tests/test_client.py +4 -3
- {databar-2.0.0 → databar-2.0.2}/LICENSE +0 -0
- {databar-2.0.0 → databar-2.0.2}/setup.cfg +0 -0
- {databar-2.0.0 → databar-2.0.2}/src/databar/cli/__init__.py +0 -0
- {databar-2.0.0 → databar-2.0.2}/src/databar/cli/_output.py +0 -0
- {databar-2.0.0 → databar-2.0.2}/src/databar/cli/app.py +0 -0
- {databar-2.0.0 → databar-2.0.2}/src/databar/exceptions.py +0 -0
- {databar-2.0.0 → databar-2.0.2}/src/databar.egg-info/SOURCES.txt +0 -0
- {databar-2.0.0 → databar-2.0.2}/src/databar.egg-info/dependency_links.txt +0 -0
- {databar-2.0.0 → databar-2.0.2}/src/databar.egg-info/entry_points.txt +0 -0
- {databar-2.0.0 → databar-2.0.2}/src/databar.egg-info/requires.txt +0 -0
- {databar-2.0.0 → databar-2.0.2}/src/databar.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: databar
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: Official Databar.ai Python SDK and CLI — connect to enrichments, waterfalls, and tables via api.databar.ai
|
|
5
5
|
Author-email: "Databar.ai Team" <info@databar.ai>
|
|
6
6
|
License: MIT License
|
|
@@ -139,7 +139,7 @@ for param in enrichment.params:
|
|
|
139
139
|
|
|
140
140
|
# Run single enrichment (async — returns task)
|
|
141
141
|
task = client.run_enrichment(123, {"email": "alice@example.com"})
|
|
142
|
-
data = client.poll_task(task.
|
|
142
|
+
data = client.poll_task(task.task_id)
|
|
143
143
|
|
|
144
144
|
# Run single enrichment (sync convenience wrapper)
|
|
145
145
|
data = client.run_enrichment_sync(123, {"email": "alice@example.com"})
|
|
@@ -84,7 +84,7 @@ for param in enrichment.params:
|
|
|
84
84
|
|
|
85
85
|
# Run single enrichment (async — returns task)
|
|
86
86
|
task = client.run_enrichment(123, {"email": "alice@example.com"})
|
|
87
|
-
data = client.poll_task(task.
|
|
87
|
+
data = client.poll_task(task.task_id)
|
|
88
88
|
|
|
89
89
|
# Run single enrichment (sync convenience wrapper)
|
|
90
90
|
data = client.run_enrichment_sync(123, {"email": "alice@example.com"})
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "databar"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.2"
|
|
8
8
|
description = "Official Databar.ai Python SDK and CLI — connect to enrichments, waterfalls, and tables via api.databar.ai"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -45,6 +45,7 @@ from .models import (
|
|
|
45
45
|
EnrichmentSummary,
|
|
46
46
|
InsertOptions,
|
|
47
47
|
InsertRow,
|
|
48
|
+
RunResponse,
|
|
48
49
|
Table,
|
|
49
50
|
TableEnrichment,
|
|
50
51
|
TaskResponse,
|
|
@@ -56,7 +57,7 @@ from .models import (
|
|
|
56
57
|
WaterfallEnrichment,
|
|
57
58
|
)
|
|
58
59
|
|
|
59
|
-
__version__ = "2.0.
|
|
60
|
+
__version__ = "2.0.2"
|
|
60
61
|
__all__ = [
|
|
61
62
|
"DatabarClient",
|
|
62
63
|
# exceptions
|
|
@@ -78,6 +79,7 @@ __all__ = [
|
|
|
78
79
|
"ChoiceItem",
|
|
79
80
|
"Choices",
|
|
80
81
|
"ChoicesResponse",
|
|
82
|
+
"RunResponse",
|
|
81
83
|
"TaskResponse",
|
|
82
84
|
"TaskStatus",
|
|
83
85
|
"Waterfall",
|
|
@@ -10,6 +10,7 @@ Key resolution order (same as MCP server):
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
12
|
import os
|
|
13
|
+
import shutil
|
|
13
14
|
from pathlib import Path
|
|
14
15
|
|
|
15
16
|
import typer
|
|
@@ -87,10 +88,23 @@ def login(
|
|
|
87
88
|
success(f"API key saved to {CONFIG_FILE}")
|
|
88
89
|
console.print("[dim]Tip: You can also set DATABAR_API_KEY as an environment variable.[/dim]")
|
|
89
90
|
|
|
91
|
+
# Check if the databar binary is on PATH and print a hint if not
|
|
92
|
+
if shutil.which("databar") is None:
|
|
93
|
+
import sys
|
|
94
|
+
bin_dir = Path(sys.executable).parent
|
|
95
|
+
console.print(
|
|
96
|
+
f"\n[yellow]Note:[/yellow] The [bold]databar[/bold] command is not on your PATH.\n"
|
|
97
|
+
f"Add this to your shell profile ([dim]~/.zshrc[/dim] or [dim]~/.bashrc[/dim]):\n\n"
|
|
98
|
+
f" [bold]export PATH=\"{bin_dir}:$PATH\"[/bold]\n\n"
|
|
99
|
+
f"Then restart your terminal, or run:\n\n"
|
|
100
|
+
f" [bold]source ~/.zshrc[/bold]\n\n"
|
|
101
|
+
f"Until then, use the full path: [bold]{bin_dir}/databar[/bold]"
|
|
102
|
+
)
|
|
103
|
+
|
|
90
104
|
|
|
91
105
|
@app.command("whoami")
|
|
92
106
|
def whoami(
|
|
93
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f", help="Output format.")
|
|
107
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f", help="Output format.")
|
|
94
108
|
) -> None:
|
|
95
109
|
"""Show current user info and credit balance."""
|
|
96
110
|
client = get_client()
|
|
@@ -28,7 +28,7 @@ app = typer.Typer(help="Search and run data enrichments.")
|
|
|
28
28
|
@app.command("list")
|
|
29
29
|
def list_enrichments(
|
|
30
30
|
query: Optional[str] = typer.Option(None, "--query", "-q", help="Search query."),
|
|
31
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
31
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
32
32
|
) -> None:
|
|
33
33
|
"""List available enrichments."""
|
|
34
34
|
client = get_client()
|
|
@@ -59,7 +59,7 @@ def list_enrichments(
|
|
|
59
59
|
@app.command("get")
|
|
60
60
|
def get_enrichment(
|
|
61
61
|
enrichment_id: int = typer.Argument(..., help="Enrichment ID."),
|
|
62
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
62
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
63
63
|
) -> None:
|
|
64
64
|
"""Get full details for an enrichment including parameters."""
|
|
65
65
|
client = get_client()
|
|
@@ -99,11 +99,20 @@ def get_enrichment(
|
|
|
99
99
|
output(rows, OutputFormat.TABLE, table_columns=["name", "type"])
|
|
100
100
|
|
|
101
101
|
|
|
102
|
+
@app.command("info", hidden=True)
|
|
103
|
+
def info_enrichment(
|
|
104
|
+
enrichment_id: int = typer.Argument(..., help="Enrichment ID."),
|
|
105
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
106
|
+
) -> None:
|
|
107
|
+
"""Alias for 'get'. Get full details for an enrichment including parameters."""
|
|
108
|
+
get_enrichment(enrichment_id, fmt)
|
|
109
|
+
|
|
110
|
+
|
|
102
111
|
@app.command("run")
|
|
103
112
|
def run_enrichment(
|
|
104
113
|
enrichment_id: int = typer.Argument(..., help="Enrichment ID."),
|
|
105
114
|
params_json: str = typer.Option(..., "--params", "-p", help='JSON params, e.g. \'{"email":"alice@example.com"}\''),
|
|
106
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
115
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
107
116
|
raw: bool = typer.Option(False, "--raw", help="Print raw result without formatting."),
|
|
108
117
|
) -> None:
|
|
109
118
|
"""Run a single enrichment and wait for results."""
|
|
@@ -132,7 +141,7 @@ def run_enrichment(
|
|
|
132
141
|
def bulk_enrichment(
|
|
133
142
|
enrichment_id: int = typer.Argument(..., help="Enrichment ID."),
|
|
134
143
|
input_file: Path = typer.Option(..., "--input", "-i", help="CSV file with one row per input.", exists=True),
|
|
135
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
144
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
136
145
|
out: Optional[Path] = typer.Option(None, "--out", "-o", help="Output file (for CSV format)."),
|
|
137
146
|
) -> None:
|
|
138
147
|
"""Run a bulk enrichment from a CSV input file."""
|
|
@@ -159,7 +168,7 @@ def param_choices(
|
|
|
159
168
|
query: Optional[str] = typer.Option(None, "--query", "-q", help="Filter choices."),
|
|
160
169
|
page: int = typer.Option(1, "--page", help="Page number."),
|
|
161
170
|
limit: int = typer.Option(50, "--limit", help="Results per page."),
|
|
162
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
171
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
163
172
|
) -> None:
|
|
164
173
|
"""List available choices for a select/mselect enrichment parameter."""
|
|
165
174
|
client = get_client()
|
|
@@ -33,7 +33,7 @@ app = typer.Typer(help="Manage tables and rows.")
|
|
|
33
33
|
|
|
34
34
|
@app.command("list")
|
|
35
35
|
def list_tables(
|
|
36
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
36
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
37
37
|
) -> None:
|
|
38
38
|
"""List all tables in your workspace."""
|
|
39
39
|
client = get_client()
|
|
@@ -59,7 +59,7 @@ def list_tables(
|
|
|
59
59
|
def create_table(
|
|
60
60
|
name: Optional[str] = typer.Option(None, "--name", "-n", help="Table name."),
|
|
61
61
|
columns: Optional[str] = typer.Option(None, "--columns", "-c", help="Comma-separated column names."),
|
|
62
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
62
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
63
63
|
) -> None:
|
|
64
64
|
"""Create a new empty table."""
|
|
65
65
|
col_list = [c.strip() for c in columns.split(",")] if columns else None
|
|
@@ -79,7 +79,7 @@ def create_table(
|
|
|
79
79
|
@app.command("columns")
|
|
80
80
|
def get_columns(
|
|
81
81
|
table_uuid: str = typer.Argument(..., help="Table UUID."),
|
|
82
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
82
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
83
83
|
) -> None:
|
|
84
84
|
"""List columns defined on a table."""
|
|
85
85
|
client = get_client()
|
|
@@ -106,7 +106,7 @@ def get_rows(
|
|
|
106
106
|
table_uuid: str = typer.Argument(..., help="Table UUID."),
|
|
107
107
|
page: int = typer.Option(1, "--page", help="Page number."),
|
|
108
108
|
per_page: int = typer.Option(1000, "--per-page", help="Rows per page (max 1000)."),
|
|
109
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
109
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
110
110
|
out: Optional[Path] = typer.Option(None, "--out", "-o", help="Output file (for CSV format)."),
|
|
111
111
|
) -> None:
|
|
112
112
|
"""Get rows from a table."""
|
|
@@ -143,7 +143,7 @@ def insert_rows(
|
|
|
143
143
|
input_file: Optional[Path] = typer.Option(None, "--input", "-i", help="CSV file.", exists=True),
|
|
144
144
|
allow_new_columns: bool = typer.Option(False, "--allow-new-columns", help="Auto-create unknown columns."),
|
|
145
145
|
dedupe_keys: Optional[str] = typer.Option(None, "--dedupe-keys", help="Comma-separated column names for deduplication."),
|
|
146
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
146
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
147
147
|
) -> None:
|
|
148
148
|
"""Insert rows into a table."""
|
|
149
149
|
raw_rows = _load_rows(data_json, input_file)
|
|
@@ -183,7 +183,7 @@ def patch_rows(
|
|
|
183
183
|
data_json: Optional[str] = typer.Option(None, "--data", "-d", help='JSON array: [{"id":"<uuid>","fields":{...}}]'),
|
|
184
184
|
input_file: Optional[Path] = typer.Option(None, "--input", "-i", help="CSV file (must have an 'id' column).", exists=True),
|
|
185
185
|
no_overwrite: bool = typer.Option(False, "--no-overwrite", help="Only fill empty cells; keep existing values."),
|
|
186
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
186
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
187
187
|
) -> None:
|
|
188
188
|
"""Update existing rows by row UUID."""
|
|
189
189
|
raw_rows = _load_rows(data_json, input_file)
|
|
@@ -219,7 +219,7 @@ def upsert_rows(
|
|
|
219
219
|
key_col: str = typer.Option(..., "--key-col", "-k", help="Column name to match on (e.g. 'email')."),
|
|
220
220
|
data_json: Optional[str] = typer.Option(None, "--data", "-d", help="JSON array of row objects."),
|
|
221
221
|
input_file: Optional[Path] = typer.Option(None, "--input", "-i", help="CSV file.", exists=True),
|
|
222
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
222
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
223
223
|
) -> None:
|
|
224
224
|
"""Insert or update rows matched by a key column."""
|
|
225
225
|
raw_rows = _load_rows(data_json, input_file)
|
|
@@ -253,7 +253,7 @@ def upsert_rows(
|
|
|
253
253
|
@app.command("enrichments")
|
|
254
254
|
def table_enrichments(
|
|
255
255
|
table_uuid: str = typer.Argument(..., help="Table UUID."),
|
|
256
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
256
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
257
257
|
) -> None:
|
|
258
258
|
"""List enrichments configured on a table."""
|
|
259
259
|
client = get_client()
|
|
@@ -277,7 +277,7 @@ def add_enrichment(
|
|
|
277
277
|
table_uuid: str = typer.Argument(..., help="Table UUID."),
|
|
278
278
|
enrichment_id: int = typer.Option(..., "--enrichment-id", "-e", help="Enrichment ID to add."),
|
|
279
279
|
mapping_json: str = typer.Option(..., "--mapping", "-m", help='JSON mapping of param → column, e.g. \'{"email": "email_col"}\''),
|
|
280
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
280
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
281
281
|
) -> None:
|
|
282
282
|
"""Add an enrichment to a table with a column mapping."""
|
|
283
283
|
try:
|
|
@@ -19,7 +19,7 @@ app = typer.Typer(help="Check the status of async tasks.")
|
|
|
19
19
|
@app.command("get")
|
|
20
20
|
def get_task(
|
|
21
21
|
task_id: str = typer.Argument(..., help="Task ID returned by a run or bulk-run call."),
|
|
22
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
22
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
23
23
|
poll: bool = typer.Option(
|
|
24
24
|
False,
|
|
25
25
|
"--poll",
|
|
@@ -27,7 +27,7 @@ app = typer.Typer(help="Search and run waterfall enrichments.")
|
|
|
27
27
|
@app.command("list")
|
|
28
28
|
def list_waterfalls(
|
|
29
29
|
query: Optional[str] = typer.Option(None, "--query", "-q", help="Filter by name/description."),
|
|
30
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
30
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
31
31
|
) -> None:
|
|
32
32
|
"""List available waterfall enrichments."""
|
|
33
33
|
client = get_client()
|
|
@@ -64,7 +64,7 @@ def list_waterfalls(
|
|
|
64
64
|
@app.command("get")
|
|
65
65
|
def get_waterfall(
|
|
66
66
|
identifier: str = typer.Argument(..., help="Waterfall identifier."),
|
|
67
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
67
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
68
68
|
) -> None:
|
|
69
69
|
"""Get details for a specific waterfall."""
|
|
70
70
|
client = get_client()
|
|
@@ -103,13 +103,22 @@ def get_waterfall(
|
|
|
103
103
|
output(rows, OutputFormat.TABLE, table_columns=["id", "name", "price"])
|
|
104
104
|
|
|
105
105
|
|
|
106
|
+
@app.command("info", hidden=True)
|
|
107
|
+
def info_waterfall(
|
|
108
|
+
identifier: str = typer.Argument(..., help="Waterfall identifier."),
|
|
109
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
110
|
+
) -> None:
|
|
111
|
+
"""Alias for 'get'. Get details for a specific waterfall."""
|
|
112
|
+
get_waterfall(identifier, fmt)
|
|
113
|
+
|
|
114
|
+
|
|
106
115
|
@app.command("run")
|
|
107
116
|
def run_waterfall(
|
|
108
117
|
identifier: str = typer.Argument(..., help="Waterfall identifier."),
|
|
109
118
|
params_json: str = typer.Option(..., "--params", "-p", help='JSON params, e.g. \'{"linkedin_url":"https://..."}\''),
|
|
110
119
|
providers: Optional[str] = typer.Option(None, "--providers", help="Comma-separated provider IDs (default: all)."),
|
|
111
120
|
email_verifier: Optional[int] = typer.Option(None, "--email-verifier", help="Email verifier enrichment ID."),
|
|
112
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
121
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
113
122
|
raw: bool = typer.Option(False, "--raw", help="Print raw result without formatting."),
|
|
114
123
|
) -> None:
|
|
115
124
|
"""Run a waterfall enrichment and wait for results."""
|
|
@@ -151,7 +160,7 @@ def bulk_waterfall(
|
|
|
151
160
|
input_file: Path = typer.Option(..., "--input", "-i", help="CSV file with one row per input.", exists=True),
|
|
152
161
|
providers: Optional[str] = typer.Option(None, "--providers", help="Comma-separated provider IDs (default: all)."),
|
|
153
162
|
email_verifier: Optional[int] = typer.Option(None, "--email-verifier", help="Email verifier enrichment ID."),
|
|
154
|
-
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "-f"),
|
|
163
|
+
fmt: OutputFormat = typer.Option(OutputFormat.TABLE, "--format", "--output", "-f"),
|
|
155
164
|
out: Optional[Path] = typer.Option(None, "--out", "-o", help="Output file (for CSV format)."),
|
|
156
165
|
) -> None:
|
|
157
166
|
"""Run a waterfall enrichment in bulk from a CSV input file."""
|
|
@@ -42,6 +42,7 @@ from .models import (
|
|
|
42
42
|
EnrichmentSummary,
|
|
43
43
|
InsertOptions,
|
|
44
44
|
InsertRow,
|
|
45
|
+
RunResponse,
|
|
45
46
|
Table,
|
|
46
47
|
TableEnrichment,
|
|
47
48
|
TaskResponse,
|
|
@@ -270,31 +271,31 @@ class DatabarClient:
|
|
|
270
271
|
data = self._request("GET", f"/enrichments/{enrichment_id}")
|
|
271
272
|
return Enrichment.model_validate(data)
|
|
272
273
|
|
|
273
|
-
def run_enrichment(self, enrichment_id: int, params: Dict[str, Any]) ->
|
|
274
|
+
def run_enrichment(self, enrichment_id: int, params: Dict[str, Any]) -> RunResponse:
|
|
274
275
|
"""Submit an enrichment run. Returns a task — use poll_task() or run_enrichment_sync()."""
|
|
275
276
|
data = self._request("POST", f"/enrichments/{enrichment_id}/run", json={"params": params})
|
|
276
|
-
return
|
|
277
|
+
return RunResponse.model_validate(data)
|
|
277
278
|
|
|
278
279
|
def run_enrichment_bulk(
|
|
279
280
|
self, enrichment_id: int, params: List[Dict[str, Any]]
|
|
280
|
-
) ->
|
|
281
|
+
) -> RunResponse:
|
|
281
282
|
"""Submit a bulk enrichment run for multiple inputs."""
|
|
282
283
|
data = self._request("POST", f"/enrichments/{enrichment_id}/bulk-run", json={"params": params})
|
|
283
|
-
return
|
|
284
|
+
return RunResponse.model_validate(data)
|
|
284
285
|
|
|
285
286
|
def run_enrichment_sync(
|
|
286
287
|
self, enrichment_id: int, params: Dict[str, Any]
|
|
287
288
|
) -> Any:
|
|
288
289
|
"""Submit and poll an enrichment, returning final data when complete."""
|
|
289
290
|
task = self.run_enrichment(enrichment_id, params)
|
|
290
|
-
return self.poll_task(task.
|
|
291
|
+
return self.poll_task(task.task_id)
|
|
291
292
|
|
|
292
293
|
def run_enrichment_bulk_sync(
|
|
293
294
|
self, enrichment_id: int, params: List[Dict[str, Any]]
|
|
294
295
|
) -> Any:
|
|
295
296
|
"""Submit and poll a bulk enrichment, returning final data when complete."""
|
|
296
297
|
task = self.run_enrichment_bulk(enrichment_id, params)
|
|
297
|
-
return self.poll_task(task.
|
|
298
|
+
return self.poll_task(task.task_id)
|
|
298
299
|
|
|
299
300
|
def get_param_choices(
|
|
300
301
|
self,
|
|
@@ -335,7 +336,7 @@ class DatabarClient:
|
|
|
335
336
|
params: Dict[str, Any],
|
|
336
337
|
enrichments: Optional[List[int]] = None,
|
|
337
338
|
email_verifier: Optional[int] = None,
|
|
338
|
-
) ->
|
|
339
|
+
) -> RunResponse:
|
|
339
340
|
"""
|
|
340
341
|
Submit a waterfall run.
|
|
341
342
|
|
|
@@ -351,7 +352,7 @@ class DatabarClient:
|
|
|
351
352
|
payload["email_verifier"] = email_verifier
|
|
352
353
|
|
|
353
354
|
data = self._request("POST", f"/waterfalls/{identifier}/run", json=payload)
|
|
354
|
-
return
|
|
355
|
+
return RunResponse.model_validate(data)
|
|
355
356
|
|
|
356
357
|
def run_waterfall_bulk(
|
|
357
358
|
self,
|
|
@@ -359,7 +360,7 @@ class DatabarClient:
|
|
|
359
360
|
params: List[Dict[str, Any]],
|
|
360
361
|
enrichments: Optional[List[int]] = None,
|
|
361
362
|
email_verifier: Optional[int] = None,
|
|
362
|
-
) ->
|
|
363
|
+
) -> RunResponse:
|
|
363
364
|
"""Submit a bulk waterfall run for multiple inputs."""
|
|
364
365
|
if not enrichments:
|
|
365
366
|
waterfall = self.get_waterfall(identifier)
|
|
@@ -370,7 +371,7 @@ class DatabarClient:
|
|
|
370
371
|
payload["email_verifier"] = email_verifier
|
|
371
372
|
|
|
372
373
|
data = self._request("POST", f"/waterfalls/{identifier}/bulk-run", json=payload)
|
|
373
|
-
return
|
|
374
|
+
return RunResponse.model_validate(data)
|
|
374
375
|
|
|
375
376
|
def run_waterfall_sync(
|
|
376
377
|
self,
|
|
@@ -381,7 +382,7 @@ class DatabarClient:
|
|
|
381
382
|
) -> Any:
|
|
382
383
|
"""Submit and poll a waterfall, returning final data when complete."""
|
|
383
384
|
task = self.run_waterfall(identifier, params, enrichments, email_verifier)
|
|
384
|
-
return self.poll_task(task.
|
|
385
|
+
return self.poll_task(task.task_id)
|
|
385
386
|
|
|
386
387
|
def run_waterfall_bulk_sync(
|
|
387
388
|
self,
|
|
@@ -392,7 +393,7 @@ class DatabarClient:
|
|
|
392
393
|
) -> Any:
|
|
393
394
|
"""Submit and poll a bulk waterfall, returning final data when complete."""
|
|
394
395
|
task = self.run_waterfall_bulk(identifier, params, enrichments, email_verifier)
|
|
395
|
-
return self.poll_task(task.
|
|
396
|
+
return self.poll_task(task.task_id)
|
|
396
397
|
|
|
397
398
|
# -----------------------------------------------------------------------
|
|
398
399
|
# Tables
|
|
@@ -104,8 +104,24 @@ class TaskStatus(str, Enum):
|
|
|
104
104
|
GONE = "gone"
|
|
105
105
|
|
|
106
106
|
|
|
107
|
+
class RunResponse(BaseModel):
|
|
108
|
+
"""Returned by all /run and /bulk-run endpoints. Contains the task_id to poll."""
|
|
109
|
+
|
|
110
|
+
task_id: str = Field(description="Unique identifier of the submitted task.")
|
|
111
|
+
status: str = Field(default="processing")
|
|
112
|
+
|
|
113
|
+
|
|
107
114
|
class TaskResponse(BaseModel):
|
|
108
|
-
|
|
115
|
+
"""Returned by GET /v1/tasks/{task_id}.
|
|
116
|
+
|
|
117
|
+
The backend currently uses 'request_id' as the field name; this model
|
|
118
|
+
accepts both 'task_id' and 'request_id' so it works before and after
|
|
119
|
+
the backend renames the field.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
task_id: str = Field(
|
|
123
|
+
description="Unique identifier of the task.",
|
|
124
|
+
)
|
|
109
125
|
status: str = Field(
|
|
110
126
|
description="Current status: processing, completed, failed, or gone."
|
|
111
127
|
)
|
|
@@ -114,6 +130,13 @@ class TaskResponse(BaseModel):
|
|
|
114
130
|
description="Resulting data once completed.",
|
|
115
131
|
)
|
|
116
132
|
error: Optional[Union[str, List[str]]] = None
|
|
133
|
+
credits_spent: float = 0
|
|
134
|
+
|
|
135
|
+
@classmethod
|
|
136
|
+
def model_validate(cls, obj: Any, **kwargs: Any) -> "TaskResponse":
|
|
137
|
+
if isinstance(obj, dict) and "task_id" not in obj and "request_id" in obj:
|
|
138
|
+
obj = {**obj, "task_id": obj["request_id"]}
|
|
139
|
+
return super().model_validate(obj, **kwargs)
|
|
117
140
|
|
|
118
141
|
|
|
119
142
|
# ===========================================================================
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: databar
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: Official Databar.ai Python SDK and CLI — connect to enrichments, waterfalls, and tables via api.databar.ai
|
|
5
5
|
Author-email: "Databar.ai Team" <info@databar.ai>
|
|
6
6
|
License: MIT License
|
|
@@ -139,7 +139,7 @@ for param in enrichment.params:
|
|
|
139
139
|
|
|
140
140
|
# Run single enrichment (async — returns task)
|
|
141
141
|
task = client.run_enrichment(123, {"email": "alice@example.com"})
|
|
142
|
-
data = client.poll_task(task.
|
|
142
|
+
data = client.poll_task(task.task_id)
|
|
143
143
|
|
|
144
144
|
# Run single enrichment (sync convenience wrapper)
|
|
145
145
|
data = client.run_enrichment_sync(123, {"email": "alice@example.com"})
|
|
@@ -110,7 +110,7 @@ def _client_mock(**method_overrides):
|
|
|
110
110
|
m.get_table_enrichments.return_value = [TableEnrichment(id=5, name="My Enrichment")]
|
|
111
111
|
m.add_enrichment.return_value = {"status": "ok"}
|
|
112
112
|
m.run_table_enrichment.return_value = {"status": "triggered"}
|
|
113
|
-
m.get_task.return_value = TaskResponse(
|
|
113
|
+
m.get_task.return_value = TaskResponse(task_id="t1", status="completed", data={"result": "ok"})
|
|
114
114
|
m.poll_task.return_value = {"result": "ok"}
|
|
115
115
|
|
|
116
116
|
for method, return_value in method_overrides.items():
|
|
@@ -329,4 +329,4 @@ def test_task_get_poll(monkeypatch):
|
|
|
329
329
|
def test_version_flag():
|
|
330
330
|
result = runner.invoke(app, ["--version"])
|
|
331
331
|
assert result.exit_code == 0
|
|
332
|
-
assert "2.0.
|
|
332
|
+
assert "2.0.2" in result.output
|
|
@@ -29,6 +29,7 @@ from databar.models import (
|
|
|
29
29
|
BatchUpdateResponse,
|
|
30
30
|
BatchUpdateRow,
|
|
31
31
|
InsertRow,
|
|
32
|
+
RunResponse,
|
|
32
33
|
UpsertResponse,
|
|
33
34
|
UpsertRow,
|
|
34
35
|
)
|
|
@@ -150,7 +151,7 @@ def test_get_enrichment(client: DatabarClient, httpx_mock: HTTPXMock):
|
|
|
150
151
|
def test_run_enrichment_returns_task(client: DatabarClient, httpx_mock: HTTPXMock):
|
|
151
152
|
httpx_mock.add_response(url=f"{BASE_URL}/enrichments/1/run", json=task_payload("processing"))
|
|
152
153
|
task = client.run_enrichment(1, {"email": "test@example.com"})
|
|
153
|
-
assert task.
|
|
154
|
+
assert task.task_id == "task-123"
|
|
154
155
|
assert task.status == "processing"
|
|
155
156
|
|
|
156
157
|
|
|
@@ -163,7 +164,7 @@ def test_run_enrichment_sync(client: DatabarClient, httpx_mock: HTTPXMock):
|
|
|
163
164
|
|
|
164
165
|
def test_run_enrichment_sync_failed(client: DatabarClient, httpx_mock: HTTPXMock):
|
|
165
166
|
httpx_mock.add_response(url=f"{BASE_URL}/enrichments/1/run", json=task_payload("processing"))
|
|
166
|
-
httpx_mock.add_response(url=f"{BASE_URL}/tasks/task-123", json={"
|
|
167
|
+
httpx_mock.add_response(url=f"{BASE_URL}/tasks/task-123", json={"task_id": "task-123", "status": "failed", "data": None, "error": "upstream error"})
|
|
167
168
|
with pytest.raises(DatabarTaskFailedError, match="upstream error"):
|
|
168
169
|
client.run_enrichment_sync(1, {"email": "test@example.com"})
|
|
169
170
|
|
|
@@ -193,7 +194,7 @@ def test_run_waterfall_auto_resolves_providers(client: DatabarClient, httpx_mock
|
|
|
193
194
|
httpx_mock.add_response(url=f"{BASE_URL}/waterfalls/email_getter", json=waterfall_payload())
|
|
194
195
|
httpx_mock.add_response(url=f"{BASE_URL}/waterfalls/email_getter/run", json=task_payload("processing"))
|
|
195
196
|
task = client.run_waterfall("email_getter", {"linkedin_url": "https://linkedin.com/in/alice"})
|
|
196
|
-
assert task.
|
|
197
|
+
assert task.task_id == "task-123"
|
|
197
198
|
req = httpx_mock.get_requests()[-1]
|
|
198
199
|
body = json.loads(req.content)
|
|
199
200
|
assert body["enrichments"] == [10, 11]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|