databar 2.0.3__tar.gz → 2.0.5__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 (26) hide show
  1. {databar-2.0.3/src/databar.egg-info → databar-2.0.5}/PKG-INFO +1 -1
  2. {databar-2.0.3 → databar-2.0.5}/pyproject.toml +1 -1
  3. {databar-2.0.3 → databar-2.0.5}/src/databar/__init__.py +3 -1
  4. databar-2.0.5/src/databar/cli/_guide.py +137 -0
  5. {databar-2.0.3 → databar-2.0.5}/src/databar/cli/app.py +8 -0
  6. {databar-2.0.3 → databar-2.0.5}/src/databar/client.py +14 -4
  7. {databar-2.0.3 → databar-2.0.5}/src/databar/models.py +152 -11
  8. {databar-2.0.3 → databar-2.0.5/src/databar.egg-info}/PKG-INFO +1 -1
  9. {databar-2.0.3 → databar-2.0.5}/src/databar.egg-info/SOURCES.txt +1 -0
  10. {databar-2.0.3 → databar-2.0.5}/tests/test_cli.py +1 -1
  11. {databar-2.0.3 → databar-2.0.5}/LICENSE +0 -0
  12. {databar-2.0.3 → databar-2.0.5}/README.md +0 -0
  13. {databar-2.0.3 → databar-2.0.5}/setup.cfg +0 -0
  14. {databar-2.0.3 → databar-2.0.5}/src/databar/cli/__init__.py +0 -0
  15. {databar-2.0.3 → databar-2.0.5}/src/databar/cli/_auth.py +0 -0
  16. {databar-2.0.3 → databar-2.0.5}/src/databar/cli/_output.py +0 -0
  17. {databar-2.0.3 → databar-2.0.5}/src/databar/cli/enrichments.py +0 -0
  18. {databar-2.0.3 → databar-2.0.5}/src/databar/cli/tables.py +0 -0
  19. {databar-2.0.3 → databar-2.0.5}/src/databar/cli/tasks.py +0 -0
  20. {databar-2.0.3 → databar-2.0.5}/src/databar/cli/waterfalls.py +0 -0
  21. {databar-2.0.3 → databar-2.0.5}/src/databar/exceptions.py +0 -0
  22. {databar-2.0.3 → databar-2.0.5}/src/databar.egg-info/dependency_links.txt +0 -0
  23. {databar-2.0.3 → databar-2.0.5}/src/databar.egg-info/entry_points.txt +0 -0
  24. {databar-2.0.3 → databar-2.0.5}/src/databar.egg-info/requires.txt +0 -0
  25. {databar-2.0.3 → databar-2.0.5}/src/databar.egg-info/top_level.txt +0 -0
  26. {databar-2.0.3 → databar-2.0.5}/tests/test_client.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databar
3
- Version: 2.0.3
3
+ Version: 2.0.5
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "databar"
7
- version = "2.0.3"
7
+ version = "2.0.5"
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
+ RowsResponse,
48
49
  RunResponse,
49
50
  Table,
50
51
  TableEnrichment,
@@ -57,7 +58,7 @@ from .models import (
57
58
  WaterfallEnrichment,
58
59
  )
59
60
 
60
- __version__ = "2.0.3"
61
+ __version__ = "2.0.5"
61
62
  __all__ = [
62
63
  "DatabarClient",
63
64
  # exceptions
@@ -87,6 +88,7 @@ __all__ = [
87
88
  "Table",
88
89
  "Column",
89
90
  "TableEnrichment",
91
+ "RowsResponse",
90
92
  "InsertRow",
91
93
  "InsertOptions",
92
94
  "DedupeOptions",
@@ -0,0 +1,137 @@
1
+ """Embedded agent guide — printed by `databar agent-guide`."""
2
+
3
+ AGENT_GUIDE = r"""# Databar SDK & CLI — Agent Guide
4
+
5
+ Official Databar Python SDK and CLI (`pip install databar`).
6
+ Run data enrichments, waterfall lookups, and manage tables via api.databar.ai/v1.
7
+
8
+ ## Setup
9
+
10
+ ```bash
11
+ pip install databar
12
+ export DATABAR_API_KEY=YOUR_API_KEY # or: databar login --api-key YOUR_API_KEY
13
+ databar whoami # verify auth
14
+ ```
15
+
16
+ If `databar` command not found after install:
17
+ ```bash
18
+ export PATH="$(python3 -m site --user-base)/bin:$PATH"
19
+ ```
20
+
21
+ ## CLI Quick Reference
22
+
23
+ All commands support `--format table|json|csv` (default: table) and `--help`.
24
+ **For machine-parseable output, always use `--format json`.**
25
+
26
+ ### Enrichments
27
+ ```
28
+ databar enrich list # list all enrichments
29
+ databar enrich list --query "linkedin" # search enrichments
30
+ databar enrich get <id> # get enrichment details (params, response fields)
31
+ databar enrich choices <id> <param> # list choices for a select param
32
+ databar enrich run <id> --params '{"key": "value"}' # run single
33
+ databar enrich bulk <id> --input data.csv --out results.csv
34
+ ```
35
+
36
+ ### Waterfalls
37
+ ```
38
+ databar waterfall list
39
+ databar waterfall get <identifier> # e.g. email_getter
40
+ databar waterfall run <identifier> --params '{"key": "value"}'
41
+ databar waterfall bulk <identifier> --input data.csv --out results.csv
42
+ ```
43
+
44
+ ### Tables
45
+ ```
46
+ databar table list
47
+ databar table create --name "My Table" --columns "email,name,company"
48
+ databar table columns <table-uuid>
49
+ databar table rows <table-uuid>
50
+ databar table rows <table-uuid> --format json
51
+
52
+ databar table insert <table-uuid> --data '[{"email":"a@b.com","name":"Alice"}]'
53
+ databar table insert <table-uuid> --input data.csv --allow-new-columns
54
+
55
+ databar table enrichments <table-uuid>
56
+ databar table add-enrichment <table-uuid> --enrichment-id <id> --mapping '{"param": "column_name"}'
57
+ databar table run-enrichment <table-uuid> --enrichment-id <TABLE-ENRICHMENT-ID>
58
+ ```
59
+
60
+ Note: `run-enrichment` uses the TABLE-ENRICHMENT ID (from `add-enrichment` or `table enrichments`), NOT the catalog enrichment ID.
61
+
62
+ ### Tasks
63
+ ```
64
+ databar task get <task-id> # check status once
65
+ databar task get <task-id> --poll # poll until complete
66
+ ```
67
+
68
+ ### Account
69
+ ```
70
+ databar whoami
71
+ databar whoami --format json
72
+ ```
73
+
74
+ ## Python SDK Quick Reference
75
+
76
+ ```python
77
+ from databar import DatabarClient
78
+
79
+ client = DatabarClient() # reads DATABAR_API_KEY from env
80
+
81
+ # Enrichments
82
+ enrichments = client.list_enrichments(q="linkedin")
83
+ enrichment = client.get_enrichment(123)
84
+ # enrichment.params → list of EnrichmentParam (fields: .name, .is_required, .description)
85
+ # enrichment.response_fields → list of EnrichmentResponseField (fields: .name, .type_field)
86
+
87
+ result = client.run_enrichment_sync(123, {"email": "alice@example.com"})
88
+
89
+ # Waterfalls
90
+ waterfalls = client.list_waterfalls()
91
+ # waterfall.identifier → slug like "email_getter" (also available as .slug)
92
+ result = client.run_waterfall_sync("email_getter", {"linkedin_url": "..."})
93
+
94
+ # Tables
95
+ tables = client.list_tables()
96
+ # table.identifier → UUID (also available as .id and .uuid)
97
+ table = client.create_table(name="Leads", columns=["email", "name"])
98
+ resp = client.get_rows(table.identifier)
99
+ # resp.data → list of row dicts, resp.has_next_page, resp.total_count, resp.page
100
+
101
+ from databar import InsertRow
102
+ client.create_rows(table.identifier, [
103
+ InsertRow(fields={"email": "alice@example.com", "name": "Alice"}),
104
+ ])
105
+ ```
106
+
107
+ ## Key Concepts
108
+
109
+ - All enrichment/waterfall runs are async: submit → get task_id → poll until completed.
110
+ The `*_sync` methods handle this automatically.
111
+ - task_id is the universal identifier for polling. Use it with poll_task() or `databar task get`.
112
+ - Results expire after 1 hour (status becomes "gone").
113
+ - Table enrichments are a two-step process: add_enrichment() then run_table_enrichment().
114
+ The ID from add_enrichment is a TABLE-ENRICHMENT ID, different from the catalog enrichment ID.
115
+ - The SDK auto-resolves column names to UUIDs in add_enrichment().
116
+
117
+ ## Model Field Aliases
118
+
119
+ Common aliases that work on all models:
120
+ - Table: .id, .uuid → .identifier
121
+ - Waterfall: .slug → .identifier
122
+ - EnrichmentParam: .slug → .name, .label → .description, .required → .is_required
123
+ - EnrichmentResponseField: .slug → .name, .label → .name
124
+
125
+ ## Error Handling
126
+
127
+ ```python
128
+ from databar import (
129
+ DatabarAuthError, # 401/403
130
+ DatabarInsufficientCreditsError, # 406
131
+ DatabarNotFoundError, # 404
132
+ DatabarTaskFailedError, # task completed with error
133
+ DatabarTimeoutError, # polling timed out
134
+ DatabarGoneError, # task data expired (>1 hour)
135
+ )
136
+ ```
137
+ """
@@ -30,6 +30,14 @@ app.add_typer(tables.app, name="table")
30
30
  app.add_typer(tasks.app, name="task")
31
31
 
32
32
 
33
+ @app.command("agent-guide")
34
+ def agent_guide() -> None:
35
+ """Print the full agent usage guide (SDK + CLI reference for AI agents)."""
36
+ from ._guide import AGENT_GUIDE
37
+
38
+ typer.echo(AGENT_GUIDE)
39
+
40
+
33
41
  def _version_callback(value: bool) -> None:
34
42
  if value:
35
43
  typer.echo(f"databar {__version__}")
@@ -43,6 +43,7 @@ from .models import (
43
43
  EnrichmentSummary,
44
44
  InsertOptions,
45
45
  InsertRow,
46
+ RowsResponse,
46
47
  RunResponse,
47
48
  Table,
48
49
  TableEnrichment,
@@ -521,14 +522,23 @@ class DatabarClient:
521
522
  self,
522
523
  table_uuid: str,
523
524
  page: int = 1,
524
- per_page: int = 1000,
525
- ) -> Dict[str, Any]:
526
- """Get rows from a table with pagination. Returns raw dict with has_next_page etc."""
527
- return self._request(
525
+ per_page: int = 100,
526
+ ) -> RowsResponse:
527
+ """
528
+ Get rows from a table with pagination.
529
+
530
+ Returns a :class:`RowsResponse` with ``.data`` (list of row dicts),
531
+ ``.has_next_page``, ``.total_count``, ``.page``.
532
+ Each row dict is keyed by column name and includes an ``id`` key.
533
+
534
+ ``per_page`` max is 500 (API limit). Default is 100.
535
+ """
536
+ data = self._request(
528
537
  "GET",
529
538
  f"/table/{table_uuid}/rows",
530
539
  params={"page": page, "per_page": per_page},
531
540
  )
541
+ return RowsResponse.model_validate(data)
532
542
 
533
543
  def create_rows(
534
544
  self,
@@ -20,6 +20,11 @@ from pydantic import BaseModel, Field
20
20
 
21
21
 
22
22
  class User(BaseModel):
23
+ """Authenticated user profile.
24
+
25
+ Fields: first_name, email, balance, plan.
26
+ """
27
+
23
28
  first_name: Optional[str] = None
24
29
  email: str
25
30
  balance: float
@@ -51,22 +56,64 @@ class Choices(BaseModel):
51
56
 
52
57
 
53
58
  class EnrichmentParam(BaseModel):
54
- name: str
55
- is_required: bool
59
+ """A parameter required or accepted by an enrichment.
60
+
61
+ Fields: name, is_required, type_field, description, choices.
62
+
63
+ Property aliases: .slug → .name, .label → .description, .required → .is_required.
64
+ """
65
+
66
+ name: str = Field(description="Parameter slug used as the key in the params dict.")
67
+ is_required: bool = Field(description="Whether this parameter is required.")
56
68
  type_field: str = Field(
57
69
  description="Input type. Common values: text, select, mselect, datetime."
58
70
  )
59
- description: str
71
+ description: str = Field(description="Human-readable label / description.")
60
72
  choices: Optional[Choices] = None
61
73
 
74
+ @property
75
+ def slug(self) -> str:
76
+ """Alias for name."""
77
+ return self.name
78
+
79
+ @property
80
+ def label(self) -> str:
81
+ """Alias for description."""
82
+ return self.description
83
+
84
+ @property
85
+ def required(self) -> bool:
86
+ """Alias for is_required."""
87
+ return self.is_required
88
+
62
89
 
63
90
  class EnrichmentResponseField(BaseModel):
64
- name: str
65
- type_field: str
91
+ """A field returned in the enrichment result data.
92
+
93
+ Fields: name, type_field.
94
+
95
+ Property aliases: .slug → .name, .label → .name.
96
+ """
97
+
98
+ name: str = Field(description="Field name as it appears in the result data.")
99
+ type_field: str = Field(description="Data type of this field.")
100
+
101
+ @property
102
+ def slug(self) -> str:
103
+ """Alias for name."""
104
+ return self.name
105
+
106
+ @property
107
+ def label(self) -> str:
108
+ """Alias for name."""
109
+ return self.name
66
110
 
67
111
 
68
112
  class EnrichmentSummary(BaseModel):
69
- """Enrichment as returned by the list endpoint (no params/response_fields)."""
113
+ """Enrichment as returned by the list endpoint (no params/response_fields).
114
+
115
+ Fields: id, name, description, data_source, price, auth_method.
116
+ """
70
117
 
71
118
  id: int
72
119
  name: str
@@ -77,7 +124,16 @@ class EnrichmentSummary(BaseModel):
77
124
 
78
125
 
79
126
  class Enrichment(EnrichmentSummary):
80
- """Full enrichment detail including params and response fields."""
127
+ """Full enrichment detail including params and response fields.
128
+
129
+ Fields: id, name, description, data_source, price, auth_method, params, response_fields.
130
+
131
+ Usage::
132
+
133
+ enrichment = client.get_enrichment(123)
134
+ for p in enrichment.params:
135
+ print(p.name, p.is_required, p.description)
136
+ """
81
137
 
82
138
  params: Optional[List[EnrichmentParam]] = None
83
139
  response_fields: Optional[List[EnrichmentResponseField]] = None
@@ -153,7 +209,20 @@ class WaterfallEnrichment(BaseModel):
153
209
 
154
210
 
155
211
  class Waterfall(BaseModel):
156
- identifier: str
212
+ """A waterfall enrichment that tries multiple providers in sequence.
213
+
214
+ Fields: identifier, name, description, input_params, output_fields,
215
+ available_enrichments, is_email_verifying, email_verifiers.
216
+
217
+ Property aliases: .slug → .identifier.
218
+
219
+ Usage::
220
+
221
+ wf = client.get_waterfall("email_getter")
222
+ result = client.run_waterfall_sync(wf.identifier, {...})
223
+ """
224
+
225
+ identifier: str = Field(description="Slug-style identifier, e.g. 'email_getter'. Use this when calling run_waterfall().")
157
226
  name: str
158
227
  description: str
159
228
  input_params: List[Dict[str, Any]]
@@ -162,6 +231,11 @@ class Waterfall(BaseModel):
162
231
  is_email_verifying: bool
163
232
  email_verifiers: List[Any]
164
233
 
234
+ @property
235
+ def slug(self) -> str:
236
+ """Alias for identifier."""
237
+ return self.identifier
238
+
165
239
 
166
240
  # ===========================================================================
167
241
  # Tables
@@ -169,25 +243,92 @@ class Waterfall(BaseModel):
169
243
 
170
244
 
171
245
  class Table(BaseModel):
172
- identifier: str
246
+ """A Databar table.
247
+
248
+ Fields: identifier, name, created_at, updated_at.
249
+
250
+ Property aliases: .id → .identifier, .uuid → .identifier.
251
+
252
+ Usage::
253
+
254
+ table = client.create_table(name="Leads", columns=["email", "name"])
255
+ rows = client.get_rows(table.identifier)
256
+ """
257
+
258
+ identifier: str = Field(description="Table UUID. Use this in all table operations.")
173
259
  name: str
174
260
  created_at: str
175
261
  updated_at: str
176
262
 
263
+ @property
264
+ def id(self) -> str:
265
+ """Alias for identifier."""
266
+ return self.identifier
267
+
268
+ @property
269
+ def uuid(self) -> str:
270
+ """Alias for identifier."""
271
+ return self.identifier
272
+
177
273
 
178
274
  class Column(BaseModel):
179
- identifier: str
275
+ """A column defined on a table.
276
+
277
+ Fields: identifier, internal_name, name, type_of_value, data_processor_id.
278
+ """
279
+
280
+ identifier: str = Field(description="Column UUID.")
180
281
  internal_name: str
181
- name: str
282
+ name: str = Field(description="Human-readable column name.")
182
283
  type_of_value: str
183
284
  data_processor_id: Optional[int] = None
184
285
 
185
286
 
186
287
  class TableEnrichment(BaseModel):
288
+ """An enrichment configured on a table.
289
+
290
+ Fields: id, name.
291
+
292
+ The id here is the TABLE-ENRICHMENT id — use it with run_table_enrichment(),
293
+ not the enrichment catalog id.
294
+ """
295
+
187
296
  id: int
188
297
  name: str
189
298
 
190
299
 
300
+ # ===========================================================================
301
+ # Rows — Query
302
+ # ===========================================================================
303
+
304
+
305
+ class RowsResponse(BaseModel):
306
+ """Paginated rows returned by get_rows().
307
+
308
+ Fields: data, has_next_page, total_count, page.
309
+
310
+ Property alias: .rows → .data.
311
+
312
+ Usage::
313
+
314
+ resp = client.get_rows(table.identifier)
315
+ for row in resp.data:
316
+ print(row["email"])
317
+ if resp.has_next_page:
318
+ resp2 = client.get_rows(table.identifier, page=2)
319
+ """
320
+
321
+ data: List[Dict[str, Any]] = Field(description="List of row dicts keyed by column name. Each row also has an 'id' key with the row UUID.")
322
+ has_next_page: bool = Field(default=False)
323
+ total_count: int = Field(default=0)
324
+ page: int = Field(default=1)
325
+
326
+ @property
327
+ def rows(self) -> List[Dict[str, Any]]:
328
+ """Alias for data."""
329
+ return self.data
330
+
331
+
191
332
  # ===========================================================================
192
333
  # Rows — Insert
193
334
  # ===========================================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databar
3
- Version: 2.0.3
3
+ Version: 2.0.5
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
@@ -13,6 +13,7 @@ src/databar.egg-info/requires.txt
13
13
  src/databar.egg-info/top_level.txt
14
14
  src/databar/cli/__init__.py
15
15
  src/databar/cli/_auth.py
16
+ src/databar/cli/_guide.py
16
17
  src/databar/cli/_output.py
17
18
  src/databar/cli/app.py
18
19
  src/databar/cli/enrichments.py
@@ -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.2" in result.output
332
+ assert "2.0.5" in result.output
File without changes
File without changes
File without changes
File without changes