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.
Files changed (25) hide show
  1. {databar-2.0.0/src/databar.egg-info → databar-2.0.2}/PKG-INFO +2 -2
  2. {databar-2.0.0 → databar-2.0.2}/README.md +1 -1
  3. {databar-2.0.0 → databar-2.0.2}/pyproject.toml +1 -1
  4. {databar-2.0.0 → databar-2.0.2}/src/databar/__init__.py +3 -1
  5. {databar-2.0.0 → databar-2.0.2}/src/databar/cli/_auth.py +15 -1
  6. {databar-2.0.0 → databar-2.0.2}/src/databar/cli/enrichments.py +14 -5
  7. {databar-2.0.0 → databar-2.0.2}/src/databar/cli/tables.py +9 -9
  8. {databar-2.0.0 → databar-2.0.2}/src/databar/cli/tasks.py +1 -1
  9. {databar-2.0.0 → databar-2.0.2}/src/databar/cli/waterfalls.py +13 -4
  10. {databar-2.0.0 → databar-2.0.2}/src/databar/client.py +13 -12
  11. {databar-2.0.0 → databar-2.0.2}/src/databar/models.py +24 -1
  12. {databar-2.0.0 → databar-2.0.2/src/databar.egg-info}/PKG-INFO +2 -2
  13. {databar-2.0.0 → databar-2.0.2}/tests/test_cli.py +2 -2
  14. {databar-2.0.0 → databar-2.0.2}/tests/test_client.py +4 -3
  15. {databar-2.0.0 → databar-2.0.2}/LICENSE +0 -0
  16. {databar-2.0.0 → databar-2.0.2}/setup.cfg +0 -0
  17. {databar-2.0.0 → databar-2.0.2}/src/databar/cli/__init__.py +0 -0
  18. {databar-2.0.0 → databar-2.0.2}/src/databar/cli/_output.py +0 -0
  19. {databar-2.0.0 → databar-2.0.2}/src/databar/cli/app.py +0 -0
  20. {databar-2.0.0 → databar-2.0.2}/src/databar/exceptions.py +0 -0
  21. {databar-2.0.0 → databar-2.0.2}/src/databar.egg-info/SOURCES.txt +0 -0
  22. {databar-2.0.0 → databar-2.0.2}/src/databar.egg-info/dependency_links.txt +0 -0
  23. {databar-2.0.0 → databar-2.0.2}/src/databar.egg-info/entry_points.txt +0 -0
  24. {databar-2.0.0 → databar-2.0.2}/src/databar.egg-info/requires.txt +0 -0
  25. {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.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.request_id)
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.request_id)
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.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.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]) -> TaskResponse:
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 TaskResponse.model_validate(data)
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
- ) -> TaskResponse:
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 TaskResponse.model_validate(data)
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.request_id)
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.request_id)
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
- ) -> TaskResponse:
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 TaskResponse.model_validate(data)
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
- ) -> TaskResponse:
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 TaskResponse.model_validate(data)
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.request_id)
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.request_id)
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
- request_id: str = Field(description="Unique identifier of the request.")
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.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.request_id)
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(request_id="t1", status="completed", data={"result": "ok"})
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.0" in result.output
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.request_id == "task-123"
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={"request_id": "task-123", "status": "failed", "data": None, "error": "upstream error"})
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.request_id == "task-123"
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