datalegion-cli 1.7.0__tar.gz → 1.8.0__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.
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/PKG-INFO +25 -18
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/README.md +24 -17
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/pyproject.toml +1 -1
- datalegion_cli-1.8.0/src/datalegion_cli/commands/__init__.py +26 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/commands/company.py +13 -3
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/commands/person.py +13 -3
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/test_commands.py +30 -0
- datalegion_cli-1.7.0/src/datalegion_cli/commands/__init__.py +0 -1
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/.gitignore +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/LICENSE +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/__init__.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/async_typer.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/client.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/commands/credits.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/commands/utility.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/config.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/logging.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/login.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/main.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/output.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/src/datalegion_cli/update.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/__init__.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/conftest.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/test_client.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/test_config.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/test_live.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/test_logging.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/test_login.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/test_output.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/test_package_contents.py +0 -0
- {datalegion_cli-1.7.0 → datalegion_cli-1.8.0}/tests/test_update.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: datalegion-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0
|
|
4
4
|
Summary: CLI for the Data Legion API — agent-friendly, fully async
|
|
5
5
|
Project-URL: Homepage, https://www.datalegion.ai
|
|
6
6
|
Project-URL: Documentation, https://www.datalegion.ai/docs
|
|
@@ -62,7 +62,7 @@ datalegion-cli person enrich --email john@example.com
|
|
|
62
62
|
brew install datalegion-ai/tap/datalegion-cli
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
### From PyPI (or
|
|
65
|
+
### From PyPI (or Private Index)
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
68
|
uv pip install datalegion-cli
|
|
@@ -80,7 +80,7 @@ To install from a private index:
|
|
|
80
80
|
uv pip install datalegion-cli --extra-index-url https://your-private-index.com/simple
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
### From GitHub
|
|
83
|
+
### From GitHub Release
|
|
84
84
|
|
|
85
85
|
Download the `.whl` from the [latest release](https://github.com/datalegion-ai/datalegion-cli/releases/latest) and install:
|
|
86
86
|
|
|
@@ -88,7 +88,7 @@ Download the `.whl` from the [latest release](https://github.com/datalegion-ai/d
|
|
|
88
88
|
uv pip install datalegion_cli-*.whl
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
### From
|
|
91
|
+
### From Source
|
|
92
92
|
|
|
93
93
|
```bash
|
|
94
94
|
git clone https://github.com/datalegion-ai/datalegion-cli.git
|
|
@@ -120,7 +120,7 @@ Or via environment variable (takes precedence over file config):
|
|
|
120
120
|
export LEGION_API_KEY=legion_your_key_here
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
### Other
|
|
123
|
+
### Other Config Options
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
126
|
# Set the API base URL
|
|
@@ -138,7 +138,7 @@ datalegion-cli config path
|
|
|
138
138
|
|
|
139
139
|
Config is stored at `~/.datalegion/config.toml`. Override the location with `LEGION_CONFIG_DIR`.
|
|
140
140
|
|
|
141
|
-
### Install
|
|
141
|
+
### Install Method Detection
|
|
142
142
|
|
|
143
143
|
The `update` command auto-detects how the CLI was installed:
|
|
144
144
|
|
|
@@ -153,7 +153,7 @@ You can override detection by setting `install_method` in config. For pip instal
|
|
|
153
153
|
|
|
154
154
|
## Usage
|
|
155
155
|
|
|
156
|
-
### Person
|
|
156
|
+
### Person Enrichment
|
|
157
157
|
|
|
158
158
|
```bash
|
|
159
159
|
# By email
|
|
@@ -165,28 +165,35 @@ datalegion-cli person enrich --name "Jane Smith" --company "Acme Corp" --city "N
|
|
|
165
165
|
# By LinkedIn
|
|
166
166
|
datalegion-cli person enrich --social-url "https://linkedin.com/in/johndoe"
|
|
167
167
|
|
|
168
|
-
#
|
|
168
|
+
# Minimum confidence
|
|
169
169
|
datalegion-cli person enrich --email john@example.com --min-confidence high
|
|
170
170
|
|
|
171
171
|
# Select specific fields
|
|
172
172
|
datalegion-cli person enrich --email john@example.com --fields "full_name,emails,phones"
|
|
173
173
|
```
|
|
174
174
|
|
|
175
|
-
### Person
|
|
175
|
+
### Person Search
|
|
176
176
|
|
|
177
177
|
```bash
|
|
178
178
|
# SQL-based search
|
|
179
179
|
datalegion-cli person search "SELECT * FROM people WHERE company_name ILIKE '%google%' AND state = 'CA'" --limit 5
|
|
180
180
|
```
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
`query` can also be an Elasticsearch-style query object as JSON (`bool`, `term`, `terms`, `match`, `match_phrase`, `range`, `exists`, `prefix`, `wildcard`, `nested`), on the response's own field names. For deep paging, pass each page's `next_cursor` back with `--cursor`; the last page has none. Company search takes both too.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
datalegion-cli person search '{"bool": {"filter": [{"term": {"company_name": "google"}}, {"match": {"job_title": "engineer"}}]}}' --limit 100
|
|
186
|
+
datalegion-cli person search "SELECT * FROM people WHERE state = 'ohio'" --limit 100 --cursor "<next_cursor from the last page>"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Person Discovery (Beta)
|
|
183
190
|
|
|
184
191
|
```bash
|
|
185
192
|
# Natural-language search
|
|
186
193
|
datalegion-cli person discover "software engineers in San Francisco who know Rust" --limit 10
|
|
187
194
|
```
|
|
188
195
|
|
|
189
|
-
### Company
|
|
196
|
+
### Company Enrichment
|
|
190
197
|
|
|
191
198
|
```bash
|
|
192
199
|
# By domain
|
|
@@ -199,21 +206,21 @@ datalegion-cli company enrich --ticker AAPL
|
|
|
199
206
|
datalegion-cli company enrich --name "Stripe" --industry "Financial Services"
|
|
200
207
|
```
|
|
201
208
|
|
|
202
|
-
### Company
|
|
209
|
+
### Company Search
|
|
203
210
|
|
|
204
211
|
```bash
|
|
205
212
|
# SQL-based search
|
|
206
213
|
datalegion-cli company search "SELECT * FROM companies WHERE industry ILIKE '%software%' AND legion_employee_count > 100"
|
|
207
214
|
```
|
|
208
215
|
|
|
209
|
-
### Company
|
|
216
|
+
### Company Discovery (Beta)
|
|
210
217
|
|
|
211
218
|
```bash
|
|
212
219
|
# Natural-language search
|
|
213
220
|
datalegion-cli company discover "fintech startups in New York with under 50 employees"
|
|
214
221
|
```
|
|
215
222
|
|
|
216
|
-
### Utility
|
|
223
|
+
### Utility Commands
|
|
217
224
|
|
|
218
225
|
```bash
|
|
219
226
|
# Clean and normalize fields
|
|
@@ -240,7 +247,7 @@ datalegion-cli credits balance
|
|
|
240
247
|
datalegion-cli credits usage --from 2026-01-01 --to 2026-03-01
|
|
241
248
|
```
|
|
242
249
|
|
|
243
|
-
### Other
|
|
250
|
+
### Other Commands
|
|
244
251
|
|
|
245
252
|
```bash
|
|
246
253
|
# Check for updates
|
|
@@ -253,7 +260,7 @@ datalegion-cli update
|
|
|
253
260
|
datalegion-cli version
|
|
254
261
|
```
|
|
255
262
|
|
|
256
|
-
## Agent /
|
|
263
|
+
## Agent / Automation Usage
|
|
257
264
|
|
|
258
265
|
The CLI is designed to be called by AI agents and scripts. Key patterns:
|
|
259
266
|
|
|
@@ -274,13 +281,13 @@ datalegion-cli person enrich --email bad 2>/dev/null
|
|
|
274
281
|
|
|
275
282
|
## Sandbox
|
|
276
283
|
|
|
277
|
-
Try commands without spending credits: `--sandbox` (or `LEGION_SANDBOX=1`, or `datalegion-cli config set sandbox true`) makes
|
|
284
|
+
Try commands without spending credits: `--sandbox` (or `LEGION_SANDBOX=1`, or `datalegion-cli config set sandbox true`) makes Enrich, Bulk Enrich, Search and Discover return sample records with every field a real record has. Utilities, which are free, still call the real API. Sandbox discover answers only a few fixed example queries.
|
|
278
285
|
|
|
279
286
|
```bash
|
|
280
287
|
datalegion-cli --sandbox person enrich --email anyone@example.com
|
|
281
288
|
```
|
|
282
289
|
|
|
283
|
-
## Global
|
|
290
|
+
## Global Flags
|
|
284
291
|
|
|
285
292
|
| Flag | Description |
|
|
286
293
|
|------|-------------|
|
|
@@ -27,7 +27,7 @@ datalegion-cli person enrich --email john@example.com
|
|
|
27
27
|
brew install datalegion-ai/tap/datalegion-cli
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
### From PyPI (or
|
|
30
|
+
### From PyPI (or Private Index)
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
33
|
uv pip install datalegion-cli
|
|
@@ -45,7 +45,7 @@ To install from a private index:
|
|
|
45
45
|
uv pip install datalegion-cli --extra-index-url https://your-private-index.com/simple
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
### From GitHub
|
|
48
|
+
### From GitHub Release
|
|
49
49
|
|
|
50
50
|
Download the `.whl` from the [latest release](https://github.com/datalegion-ai/datalegion-cli/releases/latest) and install:
|
|
51
51
|
|
|
@@ -53,7 +53,7 @@ Download the `.whl` from the [latest release](https://github.com/datalegion-ai/d
|
|
|
53
53
|
uv pip install datalegion_cli-*.whl
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
### From
|
|
56
|
+
### From Source
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
59
|
git clone https://github.com/datalegion-ai/datalegion-cli.git
|
|
@@ -85,7 +85,7 @@ Or via environment variable (takes precedence over file config):
|
|
|
85
85
|
export LEGION_API_KEY=legion_your_key_here
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
### Other
|
|
88
|
+
### Other Config Options
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
91
|
# Set the API base URL
|
|
@@ -103,7 +103,7 @@ datalegion-cli config path
|
|
|
103
103
|
|
|
104
104
|
Config is stored at `~/.datalegion/config.toml`. Override the location with `LEGION_CONFIG_DIR`.
|
|
105
105
|
|
|
106
|
-
### Install
|
|
106
|
+
### Install Method Detection
|
|
107
107
|
|
|
108
108
|
The `update` command auto-detects how the CLI was installed:
|
|
109
109
|
|
|
@@ -118,7 +118,7 @@ You can override detection by setting `install_method` in config. For pip instal
|
|
|
118
118
|
|
|
119
119
|
## Usage
|
|
120
120
|
|
|
121
|
-
### Person
|
|
121
|
+
### Person Enrichment
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
124
|
# By email
|
|
@@ -130,28 +130,35 @@ datalegion-cli person enrich --name "Jane Smith" --company "Acme Corp" --city "N
|
|
|
130
130
|
# By LinkedIn
|
|
131
131
|
datalegion-cli person enrich --social-url "https://linkedin.com/in/johndoe"
|
|
132
132
|
|
|
133
|
-
#
|
|
133
|
+
# Minimum confidence
|
|
134
134
|
datalegion-cli person enrich --email john@example.com --min-confidence high
|
|
135
135
|
|
|
136
136
|
# Select specific fields
|
|
137
137
|
datalegion-cli person enrich --email john@example.com --fields "full_name,emails,phones"
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
-
### Person
|
|
140
|
+
### Person Search
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
143
|
# SQL-based search
|
|
144
144
|
datalegion-cli person search "SELECT * FROM people WHERE company_name ILIKE '%google%' AND state = 'CA'" --limit 5
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
`query` can also be an Elasticsearch-style query object as JSON (`bool`, `term`, `terms`, `match`, `match_phrase`, `range`, `exists`, `prefix`, `wildcard`, `nested`), on the response's own field names. For deep paging, pass each page's `next_cursor` back with `--cursor`; the last page has none. Company search takes both too.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
datalegion-cli person search '{"bool": {"filter": [{"term": {"company_name": "google"}}, {"match": {"job_title": "engineer"}}]}}' --limit 100
|
|
151
|
+
datalegion-cli person search "SELECT * FROM people WHERE state = 'ohio'" --limit 100 --cursor "<next_cursor from the last page>"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Person Discovery (Beta)
|
|
148
155
|
|
|
149
156
|
```bash
|
|
150
157
|
# Natural-language search
|
|
151
158
|
datalegion-cli person discover "software engineers in San Francisco who know Rust" --limit 10
|
|
152
159
|
```
|
|
153
160
|
|
|
154
|
-
### Company
|
|
161
|
+
### Company Enrichment
|
|
155
162
|
|
|
156
163
|
```bash
|
|
157
164
|
# By domain
|
|
@@ -164,21 +171,21 @@ datalegion-cli company enrich --ticker AAPL
|
|
|
164
171
|
datalegion-cli company enrich --name "Stripe" --industry "Financial Services"
|
|
165
172
|
```
|
|
166
173
|
|
|
167
|
-
### Company
|
|
174
|
+
### Company Search
|
|
168
175
|
|
|
169
176
|
```bash
|
|
170
177
|
# SQL-based search
|
|
171
178
|
datalegion-cli company search "SELECT * FROM companies WHERE industry ILIKE '%software%' AND legion_employee_count > 100"
|
|
172
179
|
```
|
|
173
180
|
|
|
174
|
-
### Company
|
|
181
|
+
### Company Discovery (Beta)
|
|
175
182
|
|
|
176
183
|
```bash
|
|
177
184
|
# Natural-language search
|
|
178
185
|
datalegion-cli company discover "fintech startups in New York with under 50 employees"
|
|
179
186
|
```
|
|
180
187
|
|
|
181
|
-
### Utility
|
|
188
|
+
### Utility Commands
|
|
182
189
|
|
|
183
190
|
```bash
|
|
184
191
|
# Clean and normalize fields
|
|
@@ -205,7 +212,7 @@ datalegion-cli credits balance
|
|
|
205
212
|
datalegion-cli credits usage --from 2026-01-01 --to 2026-03-01
|
|
206
213
|
```
|
|
207
214
|
|
|
208
|
-
### Other
|
|
215
|
+
### Other Commands
|
|
209
216
|
|
|
210
217
|
```bash
|
|
211
218
|
# Check for updates
|
|
@@ -218,7 +225,7 @@ datalegion-cli update
|
|
|
218
225
|
datalegion-cli version
|
|
219
226
|
```
|
|
220
227
|
|
|
221
|
-
## Agent /
|
|
228
|
+
## Agent / Automation Usage
|
|
222
229
|
|
|
223
230
|
The CLI is designed to be called by AI agents and scripts. Key patterns:
|
|
224
231
|
|
|
@@ -239,13 +246,13 @@ datalegion-cli person enrich --email bad 2>/dev/null
|
|
|
239
246
|
|
|
240
247
|
## Sandbox
|
|
241
248
|
|
|
242
|
-
Try commands without spending credits: `--sandbox` (or `LEGION_SANDBOX=1`, or `datalegion-cli config set sandbox true`) makes
|
|
249
|
+
Try commands without spending credits: `--sandbox` (or `LEGION_SANDBOX=1`, or `datalegion-cli config set sandbox true`) makes Enrich, Bulk Enrich, Search and Discover return sample records with every field a real record has. Utilities, which are free, still call the real API. Sandbox discover answers only a few fixed example queries.
|
|
243
250
|
|
|
244
251
|
```bash
|
|
245
252
|
datalegion-cli --sandbox person enrich --email anyone@example.com
|
|
246
253
|
```
|
|
247
254
|
|
|
248
|
-
## Global
|
|
255
|
+
## Global Flags
|
|
249
256
|
|
|
250
257
|
| Flag | Description |
|
|
251
258
|
|------|-------------|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""CLI command modules."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Annotated, Any
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
|
|
10
|
+
CursorOpt = Annotated[
|
|
11
|
+
str | None,
|
|
12
|
+
typer.Option(
|
|
13
|
+
"--cursor",
|
|
14
|
+
help="The previous page's next_cursor, for deep paging (instead of an offset).",
|
|
15
|
+
),
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def search_query(text: str) -> str | dict[str, Any]:
|
|
20
|
+
"""SQL as given, or a query object when the argument is a JSON object."""
|
|
21
|
+
if not text.lstrip().startswith("{"):
|
|
22
|
+
return text
|
|
23
|
+
try:
|
|
24
|
+
return json.loads(text)
|
|
25
|
+
except json.JSONDecodeError as e:
|
|
26
|
+
raise typer.BadParameter(f"The query looks like JSON but doesn't parse: {e.msg}.") from e
|
|
@@ -10,6 +10,7 @@ import typer
|
|
|
10
10
|
|
|
11
11
|
from datalegion_cli.async_typer import async_command
|
|
12
12
|
from datalegion_cli.client import APIError, LegionClient
|
|
13
|
+
from datalegion_cli.commands import CursorOpt, search_query
|
|
13
14
|
from datalegion_cli.output import emit_credits, emit_error, emit_json, emit_search_warning
|
|
14
15
|
|
|
15
16
|
app = typer.Typer(name="company", help="Company enrichment, search, and discovery.")
|
|
@@ -102,24 +103,33 @@ async def enrich(
|
|
|
102
103
|
@app.command()
|
|
103
104
|
@async_command
|
|
104
105
|
async def search(
|
|
105
|
-
query: Annotated[
|
|
106
|
+
query: Annotated[
|
|
107
|
+
str,
|
|
108
|
+
typer.Argument(
|
|
109
|
+
help="SQL SELECT query against the companies table, or a query object as JSON."
|
|
110
|
+
),
|
|
111
|
+
],
|
|
106
112
|
limit: LimitOpt = 1,
|
|
113
|
+
cursor: CursorOpt = None,
|
|
107
114
|
titlecase: TitleOpt = False,
|
|
108
115
|
include_fields: FieldsInclude = None,
|
|
109
116
|
exclude_fields: FieldsExclude = None,
|
|
110
117
|
) -> None:
|
|
111
|
-
"""Search for companies with a SQL SELECT over the companies table, no LIMIT
|
|
118
|
+
"""Search for companies with a SQL SELECT over the companies table, no LIMIT.
|
|
112
119
|
|
|
113
120
|
Examples:
|
|
114
121
|
datalegion-cli company search "SELECT * FROM companies WHERE industry ILIKE '%software%' AND legion_employee_count > 100"
|
|
115
122
|
datalegion-cli company search "SELECT * FROM companies WHERE name ILIKE '%tech%'" --limit 20
|
|
116
123
|
datalegion-cli company search "SELECT * FROM companies WHERE domain = 'stripe.com'" --fields "name,domain,industry"
|
|
124
|
+
datalegion-cli company search '{"term": {"domain": "stripe.com"}}'
|
|
125
|
+
datalegion-cli company search "SELECT * FROM companies WHERE industry = 'banking'" --limit 100 --cursor <next_cursor>
|
|
117
126
|
"""
|
|
118
127
|
client = LegionClient()
|
|
119
128
|
try:
|
|
120
129
|
result = await client.company_search(
|
|
121
|
-
query=query,
|
|
130
|
+
query=search_query(query),
|
|
122
131
|
limit=limit,
|
|
132
|
+
cursor=cursor,
|
|
123
133
|
titlecase=titlecase,
|
|
124
134
|
include_fields=include_fields,
|
|
125
135
|
exclude_fields=exclude_fields,
|
|
@@ -10,6 +10,7 @@ import typer
|
|
|
10
10
|
|
|
11
11
|
from datalegion_cli.async_typer import async_command
|
|
12
12
|
from datalegion_cli.client import APIError, LegionClient
|
|
13
|
+
from datalegion_cli.commands import CursorOpt, search_query
|
|
13
14
|
from datalegion_cli.output import emit_credits, emit_error, emit_json, emit_search_warning
|
|
14
15
|
|
|
15
16
|
app = typer.Typer(name="person", help="Person enrichment, search, and discovery.")
|
|
@@ -128,23 +129,32 @@ async def enrich(
|
|
|
128
129
|
@app.command()
|
|
129
130
|
@async_command
|
|
130
131
|
async def search(
|
|
131
|
-
query: Annotated[
|
|
132
|
+
query: Annotated[
|
|
133
|
+
str,
|
|
134
|
+
typer.Argument(
|
|
135
|
+
help="SQL SELECT query against the people table, or a query object as JSON."
|
|
136
|
+
),
|
|
137
|
+
],
|
|
132
138
|
limit: LimitOpt = 1,
|
|
139
|
+
cursor: CursorOpt = None,
|
|
133
140
|
titlecase: TitleOpt = False,
|
|
134
141
|
include_fields: FieldsInclude = None,
|
|
135
142
|
exclude_fields: FieldsExclude = None,
|
|
136
143
|
) -> None:
|
|
137
|
-
"""Search for people with a SQL SELECT over the people table, no LIMIT
|
|
144
|
+
"""Search for people with a SQL SELECT over the people table, no LIMIT.
|
|
138
145
|
|
|
139
146
|
Examples:
|
|
140
147
|
datalegion-cli person search "SELECT * FROM people WHERE job_title = 'ceo' AND company_name ILIKE '%acme%'"
|
|
141
148
|
datalegion-cli person search "SELECT * FROM people WHERE city = 'san francisco'" --limit 20
|
|
149
|
+
datalegion-cli person search '{"term": {"company_name": "acme"}}' --limit 100
|
|
150
|
+
datalegion-cli person search "SELECT * FROM people WHERE state = 'ohio'" --limit 100 --cursor <next_cursor>
|
|
142
151
|
"""
|
|
143
152
|
client = LegionClient()
|
|
144
153
|
try:
|
|
145
154
|
result = await client.person_search(
|
|
146
|
-
query=query,
|
|
155
|
+
query=search_query(query),
|
|
147
156
|
limit=limit,
|
|
157
|
+
cursor=cursor,
|
|
148
158
|
titlecase=titlecase,
|
|
149
159
|
include_fields=include_fields,
|
|
150
160
|
exclude_fields=exclude_fields,
|
|
@@ -168,6 +168,36 @@ class TestPersonSearch:
|
|
|
168
168
|
assert result.exit_code == 0
|
|
169
169
|
|
|
170
170
|
|
|
171
|
+
class TestSearchQueryObjectAndCursor:
|
|
172
|
+
@pytest.mark.parametrize("entity", ["person", "company"])
|
|
173
|
+
def test_a_json_query_goes_as_an_object_with_the_cursor(self, monkeypatch, entity):
|
|
174
|
+
_mock_config(monkeypatch)
|
|
175
|
+
sent = []
|
|
176
|
+
|
|
177
|
+
async def fake_request(self, method, endpoint, *, payload=None, params=None):
|
|
178
|
+
sent.append(payload)
|
|
179
|
+
return {"matches": [], "total": 0, "next_cursor": "abc"}
|
|
180
|
+
|
|
181
|
+
monkeypatch.setattr("datalegion_cli.client.LegionClient.request", fake_request)
|
|
182
|
+
result = runner.invoke(
|
|
183
|
+
app, [entity, "search", '{"exists": {"field": "legion_id"}}', "--cursor", "abc"]
|
|
184
|
+
)
|
|
185
|
+
assert result.exit_code == 0, result.output
|
|
186
|
+
assert sent[0]["query"] == {"exists": {"field": "legion_id"}}
|
|
187
|
+
assert sent[0]["cursor"] == "abc"
|
|
188
|
+
assert json.loads(result.stdout)["next_cursor"] == "abc"
|
|
189
|
+
|
|
190
|
+
def test_a_query_that_looks_like_json_but_does_not_parse_is_refused(self, monkeypatch):
|
|
191
|
+
_mock_config(monkeypatch)
|
|
192
|
+
result = runner.invoke(app, ["person", "search", "{not json"])
|
|
193
|
+
assert result.exit_code == 2
|
|
194
|
+
|
|
195
|
+
def test_sql_stays_a_string(self):
|
|
196
|
+
from datalegion_cli.commands import search_query
|
|
197
|
+
|
|
198
|
+
assert search_query("SELECT * FROM people") == "SELECT * FROM people"
|
|
199
|
+
|
|
200
|
+
|
|
171
201
|
class TestPersonDiscover:
|
|
172
202
|
def test_discover(self, monkeypatch):
|
|
173
203
|
_mock_config(monkeypatch)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""CLI command modules."""
|
|
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
|
|
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
|
|
File without changes
|