pdfwright 0.1.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.
@@ -0,0 +1,11 @@
1
+ node_modules/
2
+ data/
3
+ dist/
4
+ .env
5
+ .env.local
6
+ *.local.json
7
+ test-output/
8
+ *.pdf
9
+ !docs/**/*.pdf
10
+ .DS_Store
11
+ Thumbs.db
@@ -0,0 +1,62 @@
1
+ Metadata-Version: 2.4
2
+ Name: pdfwright
3
+ Version: 0.1.0
4
+ Summary: Official Python client for PDFwright — the developer-first PDF API. HTML, URLs, Markdown, and JSON templates in; pixel-perfect PDFs out.
5
+ Project-URL: Homepage, https://pdfwright.dev
6
+ Project-URL: Documentation, https://pdfwright.dev/docs
7
+ Author-email: PDFwright <hello@pdfwright.dev>
8
+ License-Expression: MIT
9
+ Keywords: html-to-pdf,invoice,markdown-to-pdf,pdf,pdf-api,pdf-generation
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+
16
+ # pdfwright
17
+
18
+ Official Python client for [PDFwright](https://pdfwright.dev) — the developer-first PDF API.
19
+ Zero dependencies (stdlib only), Python 3.9+.
20
+
21
+ ```bash
22
+ pip install pdfwright
23
+ ```
24
+
25
+ (Package and module are both `pdfwright`.)
26
+
27
+ ```python
28
+ from pdfwright import PDFwright
29
+
30
+ client = PDFwright("pdfw_live_...") # free key at pdfwright.dev
31
+
32
+ # HTML → PDF
33
+ open("hello.pdf", "wb").write(client.html("<h1>Hello!</h1>", format="Letter"))
34
+
35
+ # JSON → invoice (totals & tax computed for you)
36
+ pdf = client.invoice({
37
+ "brand": {"name": "Acme Studio", "color": "#0f766e"},
38
+ "invoiceNumber": "INV-2043",
39
+ "currency": "USD",
40
+ "to": {"name": "Northwind Traders"},
41
+ "items": [{"description": "Design work", "quantity": 10, "unitPrice": 95}],
42
+ "taxRate": 8.5,
43
+ })
44
+
45
+ # Markdown → styled PDF
46
+ client.markdown("# Q2 Report\n\nRevenue grew **12%**.", theme="serif")
47
+
48
+ # Check your quota
49
+ print(client.usage()) # {'plan': ..., 'used': ..., 'remaining': ...}
50
+ ```
51
+
52
+ Get a free API key (50 PDFs/month) at [pdfwright.dev](https://pdfwright.dev/#get-key).
53
+ Full API reference: [pdfwright.dev/docs](https://pdfwright.dev/docs).
54
+
55
+ ## Publishing (maintainer note)
56
+
57
+ ```bash
58
+ cd clients/python
59
+ python -m pip install build twine
60
+ python -m build
61
+ python -m twine upload dist/* # requires a PyPI account/token
62
+ ```
@@ -0,0 +1,47 @@
1
+ # pdfwright
2
+
3
+ Official Python client for [PDFwright](https://pdfwright.dev) — the developer-first PDF API.
4
+ Zero dependencies (stdlib only), Python 3.9+.
5
+
6
+ ```bash
7
+ pip install pdfwright
8
+ ```
9
+
10
+ (Package and module are both `pdfwright`.)
11
+
12
+ ```python
13
+ from pdfwright import PDFwright
14
+
15
+ client = PDFwright("pdfw_live_...") # free key at pdfwright.dev
16
+
17
+ # HTML → PDF
18
+ open("hello.pdf", "wb").write(client.html("<h1>Hello!</h1>", format="Letter"))
19
+
20
+ # JSON → invoice (totals & tax computed for you)
21
+ pdf = client.invoice({
22
+ "brand": {"name": "Acme Studio", "color": "#0f766e"},
23
+ "invoiceNumber": "INV-2043",
24
+ "currency": "USD",
25
+ "to": {"name": "Northwind Traders"},
26
+ "items": [{"description": "Design work", "quantity": 10, "unitPrice": 95}],
27
+ "taxRate": 8.5,
28
+ })
29
+
30
+ # Markdown → styled PDF
31
+ client.markdown("# Q2 Report\n\nRevenue grew **12%**.", theme="serif")
32
+
33
+ # Check your quota
34
+ print(client.usage()) # {'plan': ..., 'used': ..., 'remaining': ...}
35
+ ```
36
+
37
+ Get a free API key (50 PDFs/month) at [pdfwright.dev](https://pdfwright.dev/#get-key).
38
+ Full API reference: [pdfwright.dev/docs](https://pdfwright.dev/docs).
39
+
40
+ ## Publishing (maintainer note)
41
+
42
+ ```bash
43
+ cd clients/python
44
+ python -m pip install build twine
45
+ python -m build
46
+ python -m twine upload dist/* # requires a PyPI account/token
47
+ ```
@@ -0,0 +1,107 @@
1
+ """Official Python client for PDFwright — https://pdfwright.dev/docs
2
+
3
+ Zero dependencies (stdlib urllib only), Python 3.9+.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ import urllib.error
10
+ import urllib.request
11
+ from typing import Any, Optional
12
+
13
+ __all__ = ["PDFwright", "PDFwrightError"]
14
+ __version__ = "0.1.0"
15
+
16
+
17
+ class PDFwrightError(Exception):
18
+ """Raised when the API returns an error response."""
19
+
20
+ def __init__(self, message: str, status: Optional[int] = None, code: Optional[str] = None):
21
+ super().__init__(message)
22
+ self.status = status
23
+ self.code = code
24
+
25
+
26
+ class PDFwright:
27
+ """Client for the PDFwright rendering API.
28
+
29
+ >>> pdfwright = PDFwright("pdfw_live_...")
30
+ >>> pdf_bytes = pdfwright.html("<h1>Hello!</h1>")
31
+ >>> open("hello.pdf", "wb").write(pdf_bytes)
32
+ """
33
+
34
+ def __init__(self, api_key: str, base_url: str = "https://pdfwright.dev", timeout: float = 60.0):
35
+ if not api_key:
36
+ raise PDFwrightError("An API key is required (get one free at pdfwright.dev)")
37
+ self.api_key = api_key
38
+ self.base_url = base_url.rstrip("/")
39
+ self.timeout = timeout
40
+
41
+ # ── core ──────────────────────────────────────────────────────────────
42
+
43
+ def render(self, **request: Any) -> bytes:
44
+ """Render a PDF. Provide exactly one of: html, url, markdown, template (+data)."""
45
+ req = urllib.request.Request(
46
+ f"{self.base_url}/v1/pdf",
47
+ data=json.dumps(request).encode("utf-8"),
48
+ headers={
49
+ "Authorization": f"Bearer {self.api_key}",
50
+ "Content-Type": "application/json",
51
+ },
52
+ method="POST",
53
+ )
54
+ try:
55
+ with urllib.request.urlopen(req, timeout=self.timeout) as res:
56
+ return res.read()
57
+ except urllib.error.HTTPError as e:
58
+ try:
59
+ body = json.loads(e.read().decode("utf-8"))
60
+ except Exception:
61
+ body = {}
62
+ raise PDFwrightError(
63
+ body.get("message", f"Render failed ({e.code})"),
64
+ status=e.code,
65
+ code=body.get("error"),
66
+ ) from None
67
+
68
+ # ── conveniences ──────────────────────────────────────────────────────
69
+
70
+ def html(self, html: str, **options: Any) -> bytes:
71
+ return self.render(html=html, options=options or None)
72
+
73
+ def url(self, url: str, **options: Any) -> bytes:
74
+ return self.render(url=url, options=options or None)
75
+
76
+ def markdown(self, markdown: str, theme: str = "clean", **options: Any) -> bytes:
77
+ return self.render(markdown=markdown, theme=theme, options=options or None)
78
+
79
+ def invoice(self, data: dict, **options: Any) -> bytes:
80
+ return self.render(template="invoice", data=data, options=options or None)
81
+
82
+ def receipt(self, data: dict, **options: Any) -> bytes:
83
+ return self.render(template="receipt", data=data, options=options or None)
84
+
85
+ def quote(self, data: dict, **options: Any) -> bytes:
86
+ return self.render(template="quote", data=data, options=options or None)
87
+
88
+ def report(self, data: dict, **options: Any) -> bytes:
89
+ return self.render(template="report", data=data, options=options or None)
90
+
91
+ def certificate(self, data: dict, **options: Any) -> bytes:
92
+ return self.render(template="certificate", data=data, options=options or None)
93
+
94
+ def usage(self) -> dict:
95
+ """Current plan/quota state."""
96
+ req = urllib.request.Request(
97
+ f"{self.base_url}/v1/usage",
98
+ headers={"Authorization": f"Bearer {self.api_key}"},
99
+ )
100
+ try:
101
+ with urllib.request.urlopen(req, timeout=self.timeout) as res:
102
+ return json.loads(res.read().decode("utf-8"))
103
+ except urllib.error.HTTPError as e:
104
+ body = json.loads(e.read().decode("utf-8"))
105
+ raise PDFwrightError(
106
+ body.get("message", "usage lookup failed"), status=e.code, code=body.get("error")
107
+ ) from None
@@ -0,0 +1,25 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "pdfwright"
7
+ version = "0.1.0"
8
+ description = "Official Python client for PDFwright — the developer-first PDF API. HTML, URLs, Markdown, and JSON templates in; pixel-perfect PDFs out."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ authors = [{ name = "PDFwright", email = "hello@pdfwright.dev" }]
12
+ requires-python = ">=3.9"
13
+ keywords = ["pdf", "html-to-pdf", "pdf-generation", "invoice", "pdf-api", "markdown-to-pdf"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "Programming Language :: Python :: 3",
18
+ ]
19
+
20
+ [project.urls]
21
+ Homepage = "https://pdfwright.dev"
22
+ Documentation = "https://pdfwright.dev/docs"
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages = ["pdfwright"]