enconvert 0.0.1__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.
- enconvert-0.0.1/LICENSE +21 -0
- enconvert-0.0.1/PKG-INFO +362 -0
- enconvert-0.0.1/README.md +335 -0
- enconvert-0.0.1/enconvert/__init__.py +143 -0
- enconvert-0.0.1/enconvert/_internal.py +127 -0
- enconvert-0.0.1/enconvert/client.py +709 -0
- enconvert-0.0.1/enconvert/errors.py +40 -0
- enconvert-0.0.1/enconvert/formats.py +199 -0
- enconvert-0.0.1/enconvert/py.typed +0 -0
- enconvert-0.0.1/enconvert/types.py +604 -0
- enconvert-0.0.1/enconvert/v2.py +952 -0
- enconvert-0.0.1/enconvert.egg-info/PKG-INFO +362 -0
- enconvert-0.0.1/enconvert.egg-info/SOURCES.txt +16 -0
- enconvert-0.0.1/enconvert.egg-info/dependency_links.txt +1 -0
- enconvert-0.0.1/enconvert.egg-info/requires.txt +5 -0
- enconvert-0.0.1/enconvert.egg-info/top_level.txt +1 -0
- enconvert-0.0.1/pyproject.toml +54 -0
- enconvert-0.0.1/setup.cfg +4 -0
enconvert-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Enconvert
|
|
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.
|
enconvert-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: enconvert
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Python SDK for the Enconvert file conversion API
|
|
5
|
+
Author-email: Enconvert <support@enconvert.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://enconvert.com
|
|
8
|
+
Project-URL: Repository, https://github.com/conversionapi/python-sdk
|
|
9
|
+
Keywords: enconvert,pdf,screenshot,conversion,html-to-pdf,url-to-pdf,url-to-screenshot,url-to-markdown,image-convert,document-convert,heic-to-webp,docx-to-pdf,api,sdk
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: requests>=2.28
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
25
|
+
Requires-Dist: mypy>=1.8; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# enconvert
|
|
29
|
+
|
|
30
|
+
Python SDK for the [Enconvert](https://enconvert.com) file conversion API.
|
|
31
|
+
|
|
32
|
+
Convert URLs to PDFs, capture screenshots, extract Markdown, crawl whole websites, transform images, and convert documents — all with a single API call. Python 3.9+.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install enconvert
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from enconvert import Enconvert
|
|
44
|
+
|
|
45
|
+
client = Enconvert(api_key="sk_...")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### URL to PDF
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
result = client.convert_url_to_pdf("https://example.com", save_to="page.pdf")
|
|
52
|
+
print(result.presigned_url)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### URL to Screenshot
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
result = client.convert_url_to_screenshot(
|
|
59
|
+
"https://example.com",
|
|
60
|
+
viewport_width=1440,
|
|
61
|
+
save_to="screenshot.png",
|
|
62
|
+
)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### URL to Markdown
|
|
66
|
+
|
|
67
|
+
Extract clean GitHub-Flavored Markdown from any URL — strips nav/footer/ads/scripts, keeps the main article content, and adds YAML frontmatter (title, description, url, links, images).
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
result = client.convert_url_to_markdown(
|
|
71
|
+
"https://example.com/article",
|
|
72
|
+
save_to="article.md",
|
|
73
|
+
)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Website to PDF / Screenshot (whole-site batch)
|
|
77
|
+
|
|
78
|
+
Discover every page of a website (via sitemap, or full crawl on Pro/Business plans), convert each one in the background, and receive a single ZIP. Requires a private API key with crawl access.
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
batch = client.convert_website_to_pdf(
|
|
82
|
+
"https://example.com",
|
|
83
|
+
crawl_mode="sitemap", # "auto" (default) | "sitemap" | "full"
|
|
84
|
+
exclude_patterns=["/blog/tag/"], # full crawl mode only
|
|
85
|
+
)
|
|
86
|
+
print(batch.batch_id, batch.url_count, batch.discovery_method)
|
|
87
|
+
|
|
88
|
+
# Block until done and save the ZIP:
|
|
89
|
+
status = client.wait_for_batch(batch.batch_id, save_to="site.zip")
|
|
90
|
+
print(status.completed, "of", status.total, "pages converted")
|
|
91
|
+
|
|
92
|
+
# Or poll yourself:
|
|
93
|
+
s = client.get_batch_status(batch.batch_id)
|
|
94
|
+
if s.status != "processing":
|
|
95
|
+
print(s.zip_download_url)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`convert_website_to_screenshot` works the same way and produces a ZIP of PNGs.
|
|
99
|
+
|
|
100
|
+
### Image Conversion
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
result = client.convert_image(
|
|
104
|
+
"photo.heic",
|
|
105
|
+
output_format="webp",
|
|
106
|
+
save_to="photo.webp",
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Any pair among `jpeg`, `png`, `svg`, `heic`, `webp` — plus PDF rasterization:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
client.convert_image("scan.pdf", output_format="jpeg", save_to="scan.jpeg")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Document Conversion
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
client.convert_document("report.docx", save_to="report.pdf")
|
|
120
|
+
client.convert_document("data.json", output_format="yaml", save_to="data.yaml")
|
|
121
|
+
client.convert_document("notes.md", output_format="html", save_to="notes.html")
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Supported inputs: `doc`/`docx`, `xls`/`xlsx`, `ppt`/`pptx`, `odt`, `ods`, `odp`, `ots`, `pages`, `numbers`, `epub`, `html`, `markdown`, `csv`, `json`, `xml`, `yaml`, `toml`
|
|
125
|
+
|
|
126
|
+
The SDK validates every `{input}-to-{output}` pair against the conversions the API actually implements and raises immediately — with the list of valid outputs for that input — instead of sending a doomed request. Introspect programmatically:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from enconvert import IMPLEMENTED_CONVERSIONS, valid_outputs_for
|
|
130
|
+
|
|
131
|
+
valid_outputs_for("json") # ["csv", "toml", "xml", "yaml"]
|
|
132
|
+
valid_outputs_for("pdf") # ["jpeg"]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Supported conversions
|
|
136
|
+
|
|
137
|
+
| Input | Outputs |
|
|
138
|
+
|-------|---------|
|
|
139
|
+
| json | csv, toml, xml, yaml |
|
|
140
|
+
| xml | csv, json |
|
|
141
|
+
| yaml | json |
|
|
142
|
+
| csv | json, xml |
|
|
143
|
+
| toml | json |
|
|
144
|
+
| markdown | html, pdf |
|
|
145
|
+
| html | pdf |
|
|
146
|
+
| doc, excel, ppt, odt, ods, odp, ots, pages, numbers, epub | pdf |
|
|
147
|
+
| jpeg, png, svg, heic, webp | each other (all 20 pairs) |
|
|
148
|
+
| pdf | jpeg |
|
|
149
|
+
|
|
150
|
+
### Job Status (async polling)
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
status = client.get_job_status("job_abc123")
|
|
154
|
+
if status.status == "success":
|
|
155
|
+
print(status.presigned_url)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## PDF Options
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from enconvert import PdfHeaderFooter, PdfMargins, PdfOptions
|
|
162
|
+
|
|
163
|
+
result = client.convert_url_to_pdf(
|
|
164
|
+
"https://example.com",
|
|
165
|
+
pdf_options=PdfOptions(
|
|
166
|
+
page_size="A4", # or custom dimensions via page_width + page_height
|
|
167
|
+
orientation="landscape",
|
|
168
|
+
margins=PdfMargins(top=10, bottom=10, left=15, right=15),
|
|
169
|
+
header=PdfHeaderFooter(content="Quarterly Report", height=15),
|
|
170
|
+
footer=PdfHeaderFooter(content="Confidential", height=12),
|
|
171
|
+
),
|
|
172
|
+
save_to="report.pdf",
|
|
173
|
+
)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Authenticated Pages (plan-gated)
|
|
177
|
+
|
|
178
|
+
All URL and website conversions accept HTTP Basic Auth, cookies, and custom headers for pages behind a login:
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from enconvert import BrowserCookie, HttpBasicAuth
|
|
182
|
+
|
|
183
|
+
client.convert_url_to_pdf(
|
|
184
|
+
"https://internal.example.com/report",
|
|
185
|
+
auth=HttpBasicAuth(username="user", password="pass"),
|
|
186
|
+
# or cookies / headers:
|
|
187
|
+
cookies=[BrowserCookie(name="session", value="abc123", domain="internal.example.com")],
|
|
188
|
+
headers={"X-Tenant": "acme"},
|
|
189
|
+
save_to="report.pdf",
|
|
190
|
+
)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Do not combine `auth` with an `Authorization` header — the API rejects the conflict.
|
|
194
|
+
|
|
195
|
+
## Error Handling
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from enconvert import Enconvert, APIError, AuthenticationError, RateLimitError
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
client.convert_url_to_pdf("https://example.com")
|
|
202
|
+
except AuthenticationError:
|
|
203
|
+
print("Invalid API key")
|
|
204
|
+
except RateLimitError:
|
|
205
|
+
print("Too many requests — slow down")
|
|
206
|
+
except APIError as e:
|
|
207
|
+
print(f"API error [{e.status_code}]: {e.message}")
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Configuration
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
client = Enconvert(
|
|
214
|
+
api_key="sk_...",
|
|
215
|
+
timeout=300.0, # seconds, default
|
|
216
|
+
base_url="https://api.enconvert.com", # default
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## V2 API (`client.v2`)
|
|
221
|
+
|
|
222
|
+
The V2 namespace turns web pages into agent-ready data: render, search, extract, ingest, and monitor. All V2 endpoints require a **private API key** and are plan-gated — a disabled feature or exhausted monthly quota raises `QuotaError` (HTTP 402).
|
|
223
|
+
|
|
224
|
+
### Perceive — render a URL into artifacts
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
op = client.v2.perceive(
|
|
228
|
+
"https://example.com",
|
|
229
|
+
outputs=["markdown", "screenshot", "structured"],
|
|
230
|
+
extract=["tables", "metadata"],
|
|
231
|
+
)
|
|
232
|
+
print(op.outputs["markdown"].url) # 15-min signed URL
|
|
233
|
+
print(op.structured)
|
|
234
|
+
|
|
235
|
+
# Re-sign artifact URLs later:
|
|
236
|
+
again = client.v2.get_perceive_operation(op.operation_id)
|
|
237
|
+
|
|
238
|
+
# Batch (<=10 URLs runs inline; larger returns "queued" — poll):
|
|
239
|
+
batch = client.v2.perceive_batch(
|
|
240
|
+
["https://a.com", "https://b.com"],
|
|
241
|
+
outputs=["markdown"],
|
|
242
|
+
output_mode="zip",
|
|
243
|
+
)
|
|
244
|
+
done = client.v2.get_perceive_batch(batch.job_id)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Discover — enumerate a site's URLs (no rendering)
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
found = client.v2.discover(
|
|
251
|
+
"https://example.com",
|
|
252
|
+
mode="hybrid", # "sitemap" | "crawl" | "hybrid"
|
|
253
|
+
max_urls=200,
|
|
254
|
+
exclude_patterns=["/tag/"],
|
|
255
|
+
)
|
|
256
|
+
print(found.total, found.urls)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Lookup — web search with optional auto-perceive
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
search = client.v2.lookup(
|
|
263
|
+
"best static site generators",
|
|
264
|
+
category="web", # web | news | images | scholar | patents | maps
|
|
265
|
+
num_results=10,
|
|
266
|
+
perceive_top=3, # auto-render top 3 results (uses perceive quota)
|
|
267
|
+
)
|
|
268
|
+
for hit in search.results:
|
|
269
|
+
print(hit.title, hit.url, hit.perceive.outputs if hit.perceive else None)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Distill — schema-driven structured extraction
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
from enconvert import CssField, CssSchema
|
|
276
|
+
|
|
277
|
+
extraction = client.v2.distill(
|
|
278
|
+
urls=["https://example.com/pricing"],
|
|
279
|
+
schema={"plans": "list of plan names with monthly prices"},
|
|
280
|
+
css_schema=CssSchema( # optional free CSS pass before the LLM tier
|
|
281
|
+
base_selector=".plan-card",
|
|
282
|
+
fields=[
|
|
283
|
+
CssField(name="name", type="text", selector="h3"),
|
|
284
|
+
CssField(name="price", type="text", selector=".price"),
|
|
285
|
+
],
|
|
286
|
+
),
|
|
287
|
+
)
|
|
288
|
+
print(extraction.results[0].data, extraction.results[0].extraction_tier)
|
|
289
|
+
|
|
290
|
+
# Or discover-then-distill:
|
|
291
|
+
from enconvert import DistillDiscoverFrom
|
|
292
|
+
|
|
293
|
+
client.v2.distill(
|
|
294
|
+
discover_from=DistillDiscoverFrom(url="https://example.com", mode="sitemap", max_pages=10),
|
|
295
|
+
schema={"title": "page title", "summary": "one-line summary"},
|
|
296
|
+
)
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Ingest — site to RAG-ready JSONL (always async)
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
from enconvert import IngestChunkOptions
|
|
303
|
+
|
|
304
|
+
job = client.v2.ingest(
|
|
305
|
+
mode="sitemap",
|
|
306
|
+
url="https://docs.example.com",
|
|
307
|
+
max_pages=100,
|
|
308
|
+
chunk=IngestChunkOptions(max_words=512, sentence_overlap=1),
|
|
309
|
+
webhook_url="https://my.app/hooks/enconvert",
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
status = client.v2.get_ingest_job(job.job_id) # poll
|
|
313
|
+
if status.status == "completed":
|
|
314
|
+
print(status.output_url) # JSONL
|
|
315
|
+
|
|
316
|
+
client.v2.list_ingest_jobs(limit=20)
|
|
317
|
+
client.v2.cancel_ingest_job(job.job_id) # idempotent
|
|
318
|
+
|
|
319
|
+
# Webhook signing (HMAC):
|
|
320
|
+
secret = client.v2.get_webhook_secret()
|
|
321
|
+
print(secret.secret, secret.signature_header)
|
|
322
|
+
client.v2.rotate_webhook_secret() # invalidates old secret
|
|
323
|
+
client.v2.retry_ingest_webhook(job.job_id) # re-deliver
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Watch — recurring change monitoring
|
|
327
|
+
|
|
328
|
+
```python
|
|
329
|
+
watcher = client.v2.create_watcher(
|
|
330
|
+
"https://example.com/pricing",
|
|
331
|
+
frequency_minutes=60, # hourly floor
|
|
332
|
+
diff_mode="auto", # auto | text | structured | tables | metadata
|
|
333
|
+
webhook_url="https://my.app/hooks/changes",
|
|
334
|
+
notify_email=True,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
client.v2.list_watchers()
|
|
338
|
+
client.v2.get_watcher(watcher.watcher_id)
|
|
339
|
+
client.v2.get_watcher_snapshots(watcher.watcher_id, limit=10)
|
|
340
|
+
client.v2.update_watcher(watcher.watcher_id, status="paused")
|
|
341
|
+
client.v2.update_watcher(watcher.watcher_id, webhook_url="") # clears webhook
|
|
342
|
+
client.v2.delete_watcher(watcher.watcher_id) # soft-delete, idempotent
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### V2 error handling
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
from enconvert import QuotaError
|
|
349
|
+
|
|
350
|
+
try:
|
|
351
|
+
client.v2.ingest(urls=["https://example.com"])
|
|
352
|
+
except QuotaError:
|
|
353
|
+
print("Upgrade plan or wait for quota reset")
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Get an API Key
|
|
357
|
+
|
|
358
|
+
Sign up at [enconvert.com](https://enconvert.com) to get your API key.
|
|
359
|
+
|
|
360
|
+
## License
|
|
361
|
+
|
|
362
|
+
MIT
|