diffbot 1.1.2__tar.gz → 3.0.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.
Files changed (43) hide show
  1. diffbot-3.0.0/.gitignore +11 -0
  2. diffbot-3.0.0/LICENSE +21 -0
  3. diffbot-3.0.0/PKG-INFO +410 -0
  4. diffbot-3.0.0/README.md +374 -0
  5. diffbot-3.0.0/pyproject.toml +79 -0
  6. diffbot-3.0.0/src/diffbot/__init__.py +63 -0
  7. diffbot-3.0.0/src/diffbot/_auth.py +41 -0
  8. diffbot-3.0.0/src/diffbot/ask.py +195 -0
  9. diffbot-3.0.0/src/diffbot/cli/__init__.py +430 -0
  10. diffbot-3.0.0/src/diffbot/cli/__main__.py +4 -0
  11. diffbot-3.0.0/src/diffbot/cli/_common.py +21 -0
  12. diffbot-3.0.0/src/diffbot/cli/dql.py +310 -0
  13. diffbot-3.0.0/src/diffbot/cli/entities.py +155 -0
  14. diffbot-3.0.0/src/diffbot/cli/ontology.py +74 -0
  15. diffbot-3.0.0/src/diffbot/client.py +362 -0
  16. diffbot-3.0.0/src/diffbot/crawl.py +270 -0
  17. diffbot-3.0.0/src/diffbot/errors.py +51 -0
  18. diffbot-3.0.0/src/diffbot/extract.py +45 -0
  19. diffbot-3.0.0/src/diffbot/kg.py +128 -0
  20. diffbot-3.0.0/src/diffbot/nlp.py +37 -0
  21. diffbot-3.0.0/src/diffbot/ontology.py +160 -0
  22. diffbot-3.0.0/src/diffbot/web_search.py +44 -0
  23. diffbot-3.0.0/tests/conftest.py +16 -0
  24. diffbot-3.0.0/tests/test_ask.py +274 -0
  25. diffbot-3.0.0/tests/test_async.py +94 -0
  26. diffbot-3.0.0/tests/test_crawl.py +63 -0
  27. diffbot-3.0.0/tests/test_dql.py +100 -0
  28. diffbot-3.0.0/tests/test_dql_cli.py +118 -0
  29. diffbot-3.0.0/tests/test_extract.py +170 -0
  30. diffbot-3.0.0/tests/test_ontology.py +119 -0
  31. diffbot-3.0.0/tests/test_readme_examples.py +290 -0
  32. diffbot-3.0.0/tests/test_web_search.py +12 -0
  33. diffbot-1.1.2/PKG-INFO +0 -119
  34. diffbot-1.1.2/README.rst +0 -98
  35. diffbot-1.1.2/diffbot.egg-info/PKG-INFO +0 -119
  36. diffbot-1.1.2/diffbot.egg-info/SOURCES.txt +0 -10
  37. diffbot-1.1.2/diffbot.egg-info/dependency_links.txt +0 -1
  38. diffbot-1.1.2/diffbot.egg-info/entry_points.txt +0 -3
  39. diffbot-1.1.2/diffbot.egg-info/top_level.txt +0 -1
  40. diffbot-1.1.2/diffbot.egg-info/zip-safe +0 -1
  41. diffbot-1.1.2/diffbot.py +0 -175
  42. diffbot-1.1.2/setup.cfg +0 -13
  43. diffbot-1.1.2/setup.py +0 -54
@@ -0,0 +1,11 @@
1
+ # Python
2
+ .venv
3
+ __pycache__
4
+ .pytest_cache
5
+ .env
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+
10
+ # Claude
11
+ .claude/settings.local.json
diffbot-3.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Diffbot
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
diffbot-3.0.0/PKG-INFO ADDED
@@ -0,0 +1,410 @@
1
+ Metadata-Version: 2.4
2
+ Name: diffbot
3
+ Version: 3.0.0
4
+ Summary: Python client library for Diffbot APIs
5
+ Project-URL: Homepage, https://github.com/diffbot/diffbot-python
6
+ Project-URL: Documentation, https://github.com/diffbot/diffbot-python#readme
7
+ Project-URL: Repository, https://github.com/diffbot/diffbot-python
8
+ Project-URL: Issues, https://github.com/diffbot/diffbot-python/issues
9
+ Author-email: Jerome Choo <jerome@diffbot.com>, Mike Tung <miket@diffbot.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: api-client,crawler,diffbot,extract,knowledge-graph,llm,nlp,web-scraping
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Internet :: WWW/HTTP
24
+ Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
25
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Classifier: Topic :: Text Processing :: Markup :: HTML
28
+ Classifier: Typing :: Typed
29
+ Requires-Python: >=3.9
30
+ Requires-Dist: click>=8.1.0
31
+ Requires-Dist: httpx>=0.27.0
32
+ Requires-Dist: rich>=13.0.0
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # Diffbot Python Library
38
+
39
+ > ⚠️ **The PyPI package is now [`diffbot`](https://pypi.org/project/diffbot/)** (`pip install diffbot`).
40
+ > `diffbot-python` is legacy and its final release (0.3.0) will never be updated.
41
+ > See [Installation](#installation) to migrate.
42
+
43
+ Python client library for [Diffbot](https://www.diffbot.com) APIs.
44
+
45
+
46
+ ## Installation
47
+
48
+ Install the [standalone CLI binary](#standalone-binary) for [agentic use](#how-to-use-with-an-agent):
49
+
50
+ ```bash
51
+ curl -fsSL https://raw.githubusercontent.com/diffbot/diffbot-python/main/install.sh | sh
52
+ ```
53
+
54
+ If you prefer, the full Python library can also be installed with pip:
55
+
56
+ ```bash
57
+ python3 -m pip install diffbot
58
+ ```
59
+
60
+ > This package was formerly published as `diffbot-python`, whose final release (0.3.0) gets no further updates.
61
+ > If you're upgrading from it, run `pip uninstall diffbot-python && pip install --force-reinstall diffbot`
62
+ > and replace `diffbot-python` with `diffbot` in your requirements.
63
+
64
+ For local development:
65
+
66
+ ```bash
67
+ pip install -e ".[dev]"
68
+ ```
69
+
70
+ ## Usage
71
+
72
+ ### Authentication
73
+
74
+ The CLI and the library can share a single credential. The token always has to be
75
+ passed to the client explicitly, but `resolve_token()` gives you the same lookup the
76
+ CLI uses, in this order:
77
+
78
+ 1. An explicit token passed to `resolve_token(token)`.
79
+ 2. The `DIFFBOT_API_TOKEN` environment variable.
80
+ 3. A `DIFFBOT_API_TOKEN=...` line in `~/.diffbot/credentials`.
81
+
82
+ Set it once and it works for both the CLI and your scripts. Either export it:
83
+
84
+ ```bash
85
+ export DIFFBOT_API_TOKEN=<TOKEN>
86
+ ```
87
+
88
+ …or write it to the shared credentials file (handy for keeping it out of your shell environment):
89
+
90
+ ```bash
91
+ mkdir -p ~/.diffbot
92
+ printf 'DIFFBOT_API_TOKEN=%s\n' '<TOKEN>' > ~/.diffbot/credentials
93
+ chmod 600 ~/.diffbot/credentials
94
+ ```
95
+
96
+ With either in place, resolve the token and pass it to the client:
97
+
98
+ ```python
99
+ from diffbot import Diffbot, resolve_token
100
+
101
+ db = Diffbot(token=resolve_token()) # from env var or ~/.diffbot/credentials
102
+ data = db.extract("https://www.example.com")
103
+ ```
104
+
105
+ ### Client configuration
106
+
107
+ `Diffbot` and `DiffbotAsync` take the same keyword arguments — the client is the single
108
+ place to configure the SDK.
109
+
110
+ | Argument | Default | Used by |
111
+ |----------|---------|---------|
112
+ | `token` | — (required) | all |
113
+ | `timeout` | `30.0` (seconds) | all |
114
+ | `transport` | httpx default | all |
115
+ | `analyze_url` | `https://api.diffbot.com/v3` | `extract` |
116
+ | `crawler_url` | `https://api.diffbot.com/v3/crawl` | `crawl`, `crawl_list_jobs`, `crawl_get_job`, `crawl_delete_job` |
117
+ | `llm_url` | `https://llm.diffbot.com/rag/v1/chat/completions` | `ask`, `ask_json` |
118
+ | `web_search_url` | `https://llm.diffbot.com/api/v1/web_search` | `web_search` |
119
+ | `nlp_url` | `https://nl.diffbot.com/v1/` | `entities` |
120
+ | `dql_url` | `https://kg.diffbot.com/kg/v3/dql` | `dql`, `dql_parallel` |
121
+ | `ontology_url` | `https://kg.diffbot.com/kg/ontology` | `dql_fetch_ontology`, `dql_refresh_ontology` |
122
+
123
+ ```python
124
+ from diffbot import Diffbot
125
+
126
+ db = Diffbot(
127
+ token="YOUR_TOKEN",
128
+ timeout=60.0,
129
+ dql_url="http://localhost:8080/kg/v3/dql",
130
+ )
131
+ ```
132
+
133
+ `analyze_url` is a base the SDK appends `/{api}` to, and `crawler_url` is used as given
134
+ for job management and with `/data` appended for crawl results. The rest are complete
135
+ endpoints, used as given.
136
+
137
+ Passing `transport` replaces the httpx transport, which is the hook for retries, proxies,
138
+ or mocking in tests. `Diffbot` takes an `httpx.BaseTransport`, `DiffbotAsync` an
139
+ `httpx.AsyncBaseTransport`:
140
+
141
+ ```python
142
+ import httpx
143
+ from diffbot import Diffbot
144
+
145
+ db = Diffbot(token="YOUR_TOKEN", transport=httpx.HTTPTransport(retries=3))
146
+ ```
147
+
148
+ ### Extract structured content
149
+ ```python
150
+ from diffbot import Diffbot
151
+
152
+ db = Diffbot(token="YOUR_TOKEN")
153
+ data = db.extract("https://www.example.com")
154
+ ```
155
+
156
+ ### Ask Diffbot LLM
157
+ ```python
158
+ from diffbot import Diffbot
159
+
160
+ db = Diffbot(token="YOUR_TOKEN")
161
+ for chunk in db.ask([{"role": "user", "content": "What's the capital of France?"}]):
162
+ print(chunk, end="")
163
+ ```
164
+
165
+ ### Structured output
166
+ Pass a JSON Schema to constrain the answer. The model is held to the schema by a grammar during decoding, so the result parses reliably even though the answer is retrieved live from the web.
167
+
168
+ ```python
169
+ from diffbot import Diffbot
170
+
171
+ db = Diffbot(token="YOUR_TOKEN")
172
+ schema = {
173
+ "type": "object",
174
+ "properties": {
175
+ "country": {"type": "string"},
176
+ "capital": {"type": "string"},
177
+ },
178
+ "required": ["country", "capital"],
179
+ }
180
+ answer = db.ask_json([{"role": "user", "content": "What's the capital of France?"}], schema)
181
+ print(answer["capital"])
182
+ ```
183
+
184
+ Omit the schema to let the model choose the shape, or use `ask` with `response_format` to stream a constrained answer:
185
+
186
+ ```python
187
+ from diffbot import Diffbot, json_schema_format
188
+
189
+ db = Diffbot(token="YOUR_TOKEN")
190
+ answer = db.ask_json([{"role": "user", "content": "What's the capital of France?"}])
191
+
192
+ for chunk in db.ask(
193
+ [{"role": "user", "content": "What's the capital of France?"}],
194
+ response_format=json_schema_format(schema),
195
+ ):
196
+ print(chunk, end="")
197
+ ```
198
+
199
+ > **Avoid `response_format={"type": "json_object"}`.** The endpoint accepts it, but applies no grammar to it — the RAG loop's internal tool call is itself a JSON object, so it can be returned as the final answer. This is reproducible whenever the request includes a system message. `ask_json` therefore defaults to a permissive JSON Schema instead, and raises `ValidationError` if it ever sees a tool call come back.
200
+
201
+ ### Crawl a site for structured content
202
+ ```python
203
+ from diffbot import Diffbot
204
+
205
+ db = Diffbot(token="YOUR_TOKEN")
206
+ for event in db.crawl("https://www.example.com", hops=1):
207
+ print(event)
208
+ ```
209
+
210
+ ### Query the Knowledge Graph
211
+ ```python
212
+ from diffbot import Diffbot
213
+
214
+ db = Diffbot(token="YOUR_TOKEN")
215
+ results = db.dql('type:Organization name:"Diffbot"')
216
+ ```
217
+
218
+ ### Web Search
219
+ ```python
220
+ from diffbot import Diffbot
221
+
222
+ db = Diffbot(token="YOUR_TOKEN")
223
+ results = db.web_search("diffbot knowledge graph")
224
+ for r in results["search_results"]:
225
+ print(r["score"], r["title"], r["pageUrl"])
226
+ print(r["content"])
227
+ ```
228
+
229
+ ### Entities (NLP)
230
+ ```python
231
+ from diffbot import Diffbot
232
+
233
+ db = Diffbot(token="YOUR_TOKEN")
234
+ result = db.entities("Apple CEO Tim Cook announced record quarterly earnings.")
235
+ for entity in result["entities"]:
236
+ print(entity["name"], entity.get("type"), entity.get("id"))
237
+ print("sentiment:", result.get("sentiment"))
238
+ ```
239
+
240
+ ## Async Usage
241
+
242
+ ### Extract structured content
243
+ ```python
244
+ import asyncio
245
+ from diffbot import DiffbotAsync
246
+
247
+ async def main():
248
+ async with DiffbotAsync(token="YOUR_TOKEN") as db:
249
+ data = await db.extract("https://www.example.com")
250
+ print(data)
251
+
252
+ asyncio.run(main())
253
+ ```
254
+
255
+ ### Ask Diffbot LLM
256
+ ```python
257
+ import asyncio
258
+ from diffbot import DiffbotAsync
259
+
260
+ async def main():
261
+ async with DiffbotAsync(token="YOUR_TOKEN") as db:
262
+ async for chunk in db.ask([{"role": "user", "content": "What's the capital of France?"}]):
263
+ print(chunk, end="")
264
+
265
+ asyncio.run(main())
266
+ ```
267
+
268
+ ### Structured output
269
+ ```python
270
+ import asyncio
271
+ from diffbot import DiffbotAsync
272
+
273
+ schema = {
274
+ "type": "object",
275
+ "properties": {
276
+ "country": {"type": "string"},
277
+ "capital": {"type": "string"},
278
+ },
279
+ "required": ["country", "capital"],
280
+ }
281
+
282
+ async def main():
283
+ async with DiffbotAsync(token="YOUR_TOKEN") as db:
284
+ answer = await db.ask_json(
285
+ [{"role": "user", "content": "What's the capital of France?"}], schema
286
+ )
287
+ print(answer["capital"])
288
+
289
+ asyncio.run(main())
290
+ ```
291
+
292
+ ### Crawl a site for structured content
293
+ ```python
294
+ import asyncio
295
+ from diffbot import DiffbotAsync
296
+
297
+ async def main():
298
+ async with DiffbotAsync(token="YOUR_TOKEN") as db:
299
+ async for event in db.crawl("https://www.example.com", hops=1):
300
+ print(event)
301
+
302
+ asyncio.run(main())
303
+ ```
304
+
305
+ ### Query the Knowledge Graph
306
+ ```python
307
+ import asyncio
308
+ from diffbot import DiffbotAsync
309
+
310
+ async def main():
311
+ async with DiffbotAsync(token="YOUR_TOKEN") as db:
312
+ results = await db.dql('type:Organization name:"Diffbot"')
313
+ print(results)
314
+
315
+ asyncio.run(main())
316
+ ```
317
+
318
+ ### Web Search
319
+ ```python
320
+ import asyncio
321
+ from diffbot import DiffbotAsync
322
+
323
+ async def main():
324
+ async with DiffbotAsync(token="YOUR_TOKEN") as db:
325
+ results = await db.web_search("diffbot knowledge graph")
326
+ for r in results["search_results"]:
327
+ print(r["score"], r["title"], r["pageUrl"])
328
+ print(r["content"])
329
+
330
+ asyncio.run(main())
331
+ ```
332
+
333
+ ### Entities (NLP)
334
+ ```python
335
+ import asyncio
336
+ from diffbot import DiffbotAsync
337
+
338
+ async def main():
339
+ async with DiffbotAsync(token="YOUR_TOKEN") as db:
340
+ result = await db.entities("Apple CEO Tim Cook announced record quarterly earnings.")
341
+ for entity in result["entities"]:
342
+ print(entity["name"], entity.get("type"), entity.get("id"))
343
+ print("sentiment:", result.get("sentiment"))
344
+
345
+ asyncio.run(main())
346
+ ```
347
+
348
+ ## CLI
349
+
350
+ This library also includes a CLI exposed as the `db` command.
351
+
352
+ To make `db` available from anywhere, install it as an isolated tool with [uv](https://docs.astral.sh/uv/):
353
+
354
+ ```bash
355
+ uv tool install .
356
+ ```
357
+
358
+ This drops a `db` executable into `~/.local/bin` (ensure it is on your `PATH`). Use `--force` to reinstall or upgrade after changes, or `--editable` to have source edits take effect immediately. Alternatively, a plain `pip install .` (or `pip install -e .`) also installs the `db` entry point into the active environment.
359
+
360
+ ### Standalone binary
361
+
362
+ Every release also ships a self-contained `db` binary for Linux (x86_64 and aarch64) and macOS (Apple Silicon) as a Python-free option. The installer detects your platform, verifies the SHA256 checksum, and installs (or upgrades) `db` into `~/.local/bin`:
363
+
364
+ ```bash
365
+ curl -fsSL https://raw.githubusercontent.com/diffbot/diffbot-python/main/install.sh | sh
366
+ ```
367
+
368
+ Pin a specific release or install location with flags (or the `DB_VERSION` / `DB_INSTALL_DIR` environment variables); re-running the installer upgrades an existing install in place:
369
+
370
+ ```bash
371
+ curl -fsSL https://raw.githubusercontent.com/diffbot/diffbot-python/main/install.sh | sh -s -- --version v0.2.1 --bin-dir ~/bin
372
+ ```
373
+
374
+ ### How to use
375
+
376
+ ```bash
377
+ export DIFFBOT_API_TOKEN=your-token-here
378
+
379
+ db extract https://www.example.com
380
+ db ask "What's the capital of France?"
381
+ db ask "What's the capital of France?" --json
382
+ db ask "What's the capital of France?" --schema capital.json
383
+ db crawl https://www.example.com --hops 1
384
+ db crawl-list-jobs
385
+ db crawl-delete-job crawl-1234567890
386
+ db web-search "diffbot knowledge graph"
387
+ db web-search "diffbot knowledge graph" -n 5 -f json
388
+ db entities "Apple CEO Tim Cook announced record quarterly earnings."
389
+ db entities "Apple CEO Tim Cook announced record quarterly earnings." -f dql
390
+ ```
391
+
392
+ ### How to use with an agent
393
+ Once installed, this library will work alongside [`diffbot-skills`](https://github.com/diffbot/diffbot-skills) to enable your agent full access to structuring web knowledge with Diffbot. Diffbot Agent Skills even unlocks some additional skills like crafting DQL from natural language.
394
+
395
+ `diffbot-skills` will pick up or install this library automatically.
396
+
397
+
398
+ ## Tests
399
+
400
+ Run the mock test suite:
401
+ ```bash
402
+ python -m pytest
403
+ ```
404
+
405
+ Run live integration tests against the real API (requires a valid token).
406
+ The token is resolved the same way as everywhere else — the `DIFFBOT_API_TOKEN`
407
+ environment variable or `~/.diffbot/credentials`:
408
+ ```bash
409
+ DIFFBOT_API_TOKEN=your_token python -m pytest -m live
410
+ ```