kovapdf 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,10 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ venv/
5
+ build/
6
+ dist/
7
+ *.egg-info/
8
+ .pytest_cache/
9
+ .mypy_cache/
10
+ .DS_Store
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (unreleased)
4
+
5
+ - First version: the `KovaPDF` client (files, jobs, `run`, one typed method per
6
+ tool, sign requests, verify, webhooks), the `kovapdf` command line tool, and
7
+ types generated from the KovaPDF tool manifest and OpenAPI file.
kovapdf-0.1.0/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KovaPDF
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.
22
+
23
+ ---
24
+
25
+ This licence covers the source code in this package only. The KovaPDF name,
26
+ logos, images, fonts and website text are not covered by it and are not
27
+ licensed for reuse.
kovapdf-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,180 @@
1
+ Metadata-Version: 2.5
2
+ Name: kovapdf
3
+ Version: 0.1.0
4
+ Summary: The official KovaPDF client for Python: compress, merge, split, convert, read scans, redact, check signatures and send documents for signature. Includes the kovapdf command line tool.
5
+ Project-URL: Homepage, https://www.kovapdf.com
6
+ Project-URL: Documentation, https://www.kovapdf.com/developers
7
+ Project-URL: Security, https://www.kovapdf.com/security
8
+ Author-email: KovaPDF <support@kovapdf.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: bijoy,compress,e-signature,kovapdf,merge,ocr,pdf,redact,unicode
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Office/Business
15
+ Classifier: Typing :: Typed
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+
19
+ # kovapdf
20
+
21
+ The official KovaPDF client for Python, with the `kovapdf` command line tool.
22
+ Compress, merge, split, reorder, convert, read scans, redact and check the
23
+ signatures of PDF files, convert Bangla and Hindi text between Bijoy,
24
+ Kruti Dev and Unicode, and send documents for signature.
25
+
26
+ The work is done by KovaPDF: https://www.kovapdf.com
27
+
28
+ ## Install
29
+
30
+ ```sh
31
+ pip install kovapdf
32
+ ```
33
+
34
+ Python 3.10 or newer. No dependencies: only the standard library.
35
+
36
+ ## Your API key
37
+
38
+ Make a key in your KovaPDF dashboard (Developer API) and put it in the
39
+ environment. The client reads `KOVAPDF_API_KEY`; never write a key into code.
40
+
41
+ ```sh
42
+ export KOVAPDF_API_KEY=kova_test_...
43
+ ```
44
+
45
+ A test key (`kova_test_`) is free to make and stamps its PDFs TEST. A live key
46
+ (`kova_live_`) needs API access on your account.
47
+
48
+ ## Use it
49
+
50
+ ```python
51
+ from kovapdf import KovaPDF
52
+
53
+ kova = KovaPDF() # the key comes from KOVAPDF_API_KEY
54
+
55
+ result = kova.compress("report.pdf", level="strong", save_to="report-small.pdf")
56
+ print(result.saved) # ['report-small.pdf']
57
+ print(result.attribution) # Done with KovaPDF (kovapdf.com).
58
+ ```
59
+
60
+ Every tool has its own method, made from KovaPDF's tool manifest:
61
+ `compress`, `merge`, `split`, `organize`, `convert`, `ocr`, `redact`,
62
+ `bijoy_to_unicode`, `unicode_to_bijoy`, `kruti_to_unicode` and `verify_job`.
63
+
64
+ ```python
65
+ kova.merge(["a.pdf", "b.pdf"], save_to="merged.pdf")
66
+ kova.split("big.pdf", mode="range", pages="1-3,5", save_to="out/")
67
+ print(kova.bijoy_to_unicode(text="Avwg evsjvq Mvb MvB").text)
68
+ ```
69
+
70
+ A file can be a path, an https address, bytes, an open file, or a dict:
71
+ `{"file_id": ...}` from an earlier upload, `{"url": ...}`, or
72
+ `{"data": b"...", "name": "a.pdf"}`.
73
+
74
+ ### Step by step
75
+
76
+ ```python
77
+ f = kova.files.upload("in.pdf") # kept for one hour
78
+ job = kova.jobs.create("compress", [f["id"]], {"level": "basic"})
79
+ done = kova.jobs.wait(job["id"], timeout=300)
80
+ data = kova.download(done["result"]["files"][0]["download"]["url"]) # the link works for 15 minutes
81
+ ```
82
+
83
+ `kova.run(tool, inputs, options)` does all of that in one call.
84
+
85
+ ### Signature requests and verify
86
+
87
+ ```python
88
+ request = kova.sign_requests.create("agreement.pdf", {
89
+ "title": "Service agreement",
90
+ "sequential": False,
91
+ "signers": [{"name": "Alex Rivera", "email": "alex@example.com", "order": 1}],
92
+ "fields": [{"signer": 0, "kind": "SIGNATURE", "page": 1, "x": 72, "y": 640, "width": 180, "height": 48}],
93
+ })
94
+ kova.sign_requests.list()
95
+ kova.sign_requests.get(request["id"])
96
+ kova.sign_requests.remind(request["id"])
97
+ kova.sign_requests.cancel(request["id"])
98
+ pdf = kova.sign_requests.document(request["id"], version="final")
99
+
100
+ report = kova.verify("signed.pdf") # every digital signature, checked
101
+ ```
102
+
103
+ ### Webhooks
104
+
105
+ ```python
106
+ from kovapdf import verify_webhook
107
+
108
+ # raw_body: the request body exactly as received, before JSON parsing
109
+ event = verify_webhook(raw_body, request.headers, os.environ["KOVAPDF_WEBHOOK_SECRET"])
110
+ ```
111
+
112
+ It checks the `KovaPDF-Signature` header (`t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<body>">`)
113
+ and refuses a timestamp older than five minutes.
114
+
115
+ ## Command line
116
+
117
+ ```sh
118
+ kovapdf compress in.pdf -o out.pdf --level strong
119
+ kovapdf merge a.pdf b.pdf -o merged.pdf
120
+ kovapdf verify signed.pdf
121
+ kovapdf bijoy-to-unicode "Avwg evsjvq Mvb MvB"
122
+ echo "Avwg" | kovapdf bijoy-to-unicode
123
+ kovapdf tools # every tool and its options
124
+ python -m kovapdf --help
125
+ ```
126
+
127
+ The command prints `Done with KovaPDF (kovapdf.com).` after each result. It
128
+ never overwrites a file unless you add `--force`.
129
+
130
+ ## Errors
131
+
132
+ Every error is a `KovaPDFError` with a stable `code` and a `message` you can
133
+ show to a person. A few need care:
134
+
135
+ | code | what it means |
136
+ |---|---|
137
+ | `integration_paused` | KovaPDF has paused connections from this kind of app for now. Nothing was changed. Try again later, or use https://www.kovapdf.com. |
138
+ | `tool_paused` | This tool is paused for apps right now. It still works on https://www.kovapdf.com. |
139
+ | `not_available` | This KovaPDF feature is not available yet. |
140
+ | `limit_reached`, `rate_limited`, `daily_limit` | A limit was reached; `retry_after` says when to try again. |
141
+ | `timeout` | The job is still running; ask for it later with `jobs.get(id)`. |
142
+
143
+ Paused answers are never retried.
144
+
145
+ ## Limits, and how the client behaves
146
+
147
+ Your account's own limits apply, exactly as on the website; your dashboard
148
+ shows them. Files you upload and results are deleted within an hour, and a
149
+ result link works for 15 minutes.
150
+
151
+ The client is gentle with KovaPDF by design:
152
+
153
+ - at most 2 calls at once per client, across threads (you can set up to 4);
154
+ - a job is checked no more often than every 2 seconds, slowing to every 10;
155
+ - `Retry-After` is always honoured; otherwise it waits 2 seconds, then longer
156
+ (up to a minute), and tries at most 5 more times, only after a busy answer
157
+ or a network error;
158
+ - every call says who it is: `User-Agent: kovapdf-sdk-python/<version> (+https://www.kovapdf.com)`
159
+ and `X-KovaPDF-Client: sdk`.
160
+
161
+ ## Attribution
162
+
163
+ Results carry `attribution = "Done with KovaPDF (kovapdf.com)."`. Please show
164
+ it to the person you did the work for, with a link to https://www.kovapdf.com.
165
+
166
+ ## Development
167
+
168
+ `src/kovapdf/_generated.py` is made from KovaPDF's tool manifest and OpenAPI
169
+ file by `packages/sdk-js/scripts/generate.mjs` in the KovaPDF repository; a
170
+ test fails when it drifts. Run the tests with:
171
+
172
+ ```sh
173
+ python -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
174
+ .venv/bin/pytest
175
+ ```
176
+
177
+ ## Licence
178
+
179
+ MIT for the code (see LICENSE). The KovaPDF name, logos and images are not
180
+ covered by it.
@@ -0,0 +1,162 @@
1
+ # kovapdf
2
+
3
+ The official KovaPDF client for Python, with the `kovapdf` command line tool.
4
+ Compress, merge, split, reorder, convert, read scans, redact and check the
5
+ signatures of PDF files, convert Bangla and Hindi text between Bijoy,
6
+ Kruti Dev and Unicode, and send documents for signature.
7
+
8
+ The work is done by KovaPDF: https://www.kovapdf.com
9
+
10
+ ## Install
11
+
12
+ ```sh
13
+ pip install kovapdf
14
+ ```
15
+
16
+ Python 3.10 or newer. No dependencies: only the standard library.
17
+
18
+ ## Your API key
19
+
20
+ Make a key in your KovaPDF dashboard (Developer API) and put it in the
21
+ environment. The client reads `KOVAPDF_API_KEY`; never write a key into code.
22
+
23
+ ```sh
24
+ export KOVAPDF_API_KEY=kova_test_...
25
+ ```
26
+
27
+ A test key (`kova_test_`) is free to make and stamps its PDFs TEST. A live key
28
+ (`kova_live_`) needs API access on your account.
29
+
30
+ ## Use it
31
+
32
+ ```python
33
+ from kovapdf import KovaPDF
34
+
35
+ kova = KovaPDF() # the key comes from KOVAPDF_API_KEY
36
+
37
+ result = kova.compress("report.pdf", level="strong", save_to="report-small.pdf")
38
+ print(result.saved) # ['report-small.pdf']
39
+ print(result.attribution) # Done with KovaPDF (kovapdf.com).
40
+ ```
41
+
42
+ Every tool has its own method, made from KovaPDF's tool manifest:
43
+ `compress`, `merge`, `split`, `organize`, `convert`, `ocr`, `redact`,
44
+ `bijoy_to_unicode`, `unicode_to_bijoy`, `kruti_to_unicode` and `verify_job`.
45
+
46
+ ```python
47
+ kova.merge(["a.pdf", "b.pdf"], save_to="merged.pdf")
48
+ kova.split("big.pdf", mode="range", pages="1-3,5", save_to="out/")
49
+ print(kova.bijoy_to_unicode(text="Avwg evsjvq Mvb MvB").text)
50
+ ```
51
+
52
+ A file can be a path, an https address, bytes, an open file, or a dict:
53
+ `{"file_id": ...}` from an earlier upload, `{"url": ...}`, or
54
+ `{"data": b"...", "name": "a.pdf"}`.
55
+
56
+ ### Step by step
57
+
58
+ ```python
59
+ f = kova.files.upload("in.pdf") # kept for one hour
60
+ job = kova.jobs.create("compress", [f["id"]], {"level": "basic"})
61
+ done = kova.jobs.wait(job["id"], timeout=300)
62
+ data = kova.download(done["result"]["files"][0]["download"]["url"]) # the link works for 15 minutes
63
+ ```
64
+
65
+ `kova.run(tool, inputs, options)` does all of that in one call.
66
+
67
+ ### Signature requests and verify
68
+
69
+ ```python
70
+ request = kova.sign_requests.create("agreement.pdf", {
71
+ "title": "Service agreement",
72
+ "sequential": False,
73
+ "signers": [{"name": "Alex Rivera", "email": "alex@example.com", "order": 1}],
74
+ "fields": [{"signer": 0, "kind": "SIGNATURE", "page": 1, "x": 72, "y": 640, "width": 180, "height": 48}],
75
+ })
76
+ kova.sign_requests.list()
77
+ kova.sign_requests.get(request["id"])
78
+ kova.sign_requests.remind(request["id"])
79
+ kova.sign_requests.cancel(request["id"])
80
+ pdf = kova.sign_requests.document(request["id"], version="final")
81
+
82
+ report = kova.verify("signed.pdf") # every digital signature, checked
83
+ ```
84
+
85
+ ### Webhooks
86
+
87
+ ```python
88
+ from kovapdf import verify_webhook
89
+
90
+ # raw_body: the request body exactly as received, before JSON parsing
91
+ event = verify_webhook(raw_body, request.headers, os.environ["KOVAPDF_WEBHOOK_SECRET"])
92
+ ```
93
+
94
+ It checks the `KovaPDF-Signature` header (`t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<body>">`)
95
+ and refuses a timestamp older than five minutes.
96
+
97
+ ## Command line
98
+
99
+ ```sh
100
+ kovapdf compress in.pdf -o out.pdf --level strong
101
+ kovapdf merge a.pdf b.pdf -o merged.pdf
102
+ kovapdf verify signed.pdf
103
+ kovapdf bijoy-to-unicode "Avwg evsjvq Mvb MvB"
104
+ echo "Avwg" | kovapdf bijoy-to-unicode
105
+ kovapdf tools # every tool and its options
106
+ python -m kovapdf --help
107
+ ```
108
+
109
+ The command prints `Done with KovaPDF (kovapdf.com).` after each result. It
110
+ never overwrites a file unless you add `--force`.
111
+
112
+ ## Errors
113
+
114
+ Every error is a `KovaPDFError` with a stable `code` and a `message` you can
115
+ show to a person. A few need care:
116
+
117
+ | code | what it means |
118
+ |---|---|
119
+ | `integration_paused` | KovaPDF has paused connections from this kind of app for now. Nothing was changed. Try again later, or use https://www.kovapdf.com. |
120
+ | `tool_paused` | This tool is paused for apps right now. It still works on https://www.kovapdf.com. |
121
+ | `not_available` | This KovaPDF feature is not available yet. |
122
+ | `limit_reached`, `rate_limited`, `daily_limit` | A limit was reached; `retry_after` says when to try again. |
123
+ | `timeout` | The job is still running; ask for it later with `jobs.get(id)`. |
124
+
125
+ Paused answers are never retried.
126
+
127
+ ## Limits, and how the client behaves
128
+
129
+ Your account's own limits apply, exactly as on the website; your dashboard
130
+ shows them. Files you upload and results are deleted within an hour, and a
131
+ result link works for 15 minutes.
132
+
133
+ The client is gentle with KovaPDF by design:
134
+
135
+ - at most 2 calls at once per client, across threads (you can set up to 4);
136
+ - a job is checked no more often than every 2 seconds, slowing to every 10;
137
+ - `Retry-After` is always honoured; otherwise it waits 2 seconds, then longer
138
+ (up to a minute), and tries at most 5 more times, only after a busy answer
139
+ or a network error;
140
+ - every call says who it is: `User-Agent: kovapdf-sdk-python/<version> (+https://www.kovapdf.com)`
141
+ and `X-KovaPDF-Client: sdk`.
142
+
143
+ ## Attribution
144
+
145
+ Results carry `attribution = "Done with KovaPDF (kovapdf.com)."`. Please show
146
+ it to the person you did the work for, with a link to https://www.kovapdf.com.
147
+
148
+ ## Development
149
+
150
+ `src/kovapdf/_generated.py` is made from KovaPDF's tool manifest and OpenAPI
151
+ file by `packages/sdk-js/scripts/generate.mjs` in the KovaPDF repository; a
152
+ test fails when it drifts. Run the tests with:
153
+
154
+ ```sh
155
+ python -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
156
+ .venv/bin/pytest
157
+ ```
158
+
159
+ ## Licence
160
+
161
+ MIT for the code (see LICENSE). The KovaPDF name, logos and images are not
162
+ covered by it.
@@ -0,0 +1,17 @@
1
+ # Security
2
+
3
+ Please report a security problem in this package, or in KovaPDF itself, to
4
+ **support@kovapdf.com** (the contact in https://www.kovapdf.com/.well-known/security.txt).
5
+ How we handle files, encryption and reports: https://www.kovapdf.com/security
6
+
7
+ Please do not open a public issue for a security problem. Tell us what you
8
+ found and how to reproduce it; we answer as soon as we can.
9
+
10
+ ## How this package handles your key
11
+
12
+ - The API key is read from the `api_key` argument or the `KOVAPDF_API_KEY`
13
+ environment variable. It is never written to disk or logged.
14
+ - The key is only sent over https (plain http is allowed for `localhost` only,
15
+ for local tests).
16
+ - Result download links need no key, and the key is never sent to them.
17
+ - There are no runtime dependencies.
@@ -0,0 +1,18 @@
1
+ """Compress a PDF. KOVAPDF_API_KEY=kova_... python examples/compress.py in.pdf [out.pdf]"""
2
+
3
+ import sys
4
+
5
+ from kovapdf import KovaPDF, KovaPDFError
6
+
7
+ if len(sys.argv) < 2:
8
+ sys.exit("Usage: python examples/compress.py in.pdf [out.pdf]")
9
+ source = sys.argv[1]
10
+ target = sys.argv[2] if len(sys.argv) > 2 else "compressed.pdf"
11
+
12
+ kova = KovaPDF() # the key comes from KOVAPDF_API_KEY
13
+ try:
14
+ result = kova.compress(source, level="strong", save_to=target)
15
+ except KovaPDFError as e:
16
+ sys.exit(f"{e.code}: {e.message}")
17
+ print("Saved", ", ".join(result.saved))
18
+ print(result.attribution) # Done with KovaPDF (kovapdf.com).
@@ -0,0 +1,22 @@
1
+ """Merge PDFs in order. KOVAPDF_API_KEY=kova_... python examples/merge.py a.pdf b.pdf [...] [-o merged.pdf]"""
2
+
3
+ import sys
4
+
5
+ from kovapdf import KovaPDF, KovaPDFError
6
+
7
+ args = sys.argv[1:]
8
+ target = "merged.pdf"
9
+ if "-o" in args:
10
+ i = args.index("-o")
11
+ target = args[i + 1]
12
+ del args[i : i + 2]
13
+ if len(args) < 2:
14
+ sys.exit("Usage: python examples/merge.py a.pdf b.pdf [...] [-o merged.pdf]")
15
+
16
+ kova = KovaPDF()
17
+ try:
18
+ result = kova.merge(args, save_to=target, timeout=300)
19
+ except KovaPDFError as e:
20
+ sys.exit(f"{e.code}: {e.message}")
21
+ print("Saved", ", ".join(result.saved))
22
+ print(result.attribution)
@@ -0,0 +1,31 @@
1
+ """Send a PDF for signature to one person, then list your requests.
2
+
3
+ KOVAPDF_API_KEY=kova_test_... python examples/sign_request.py agreement.pdf "Alex Rivera" alex@example.com
4
+
5
+ A test key (kova_test_) sends every email to your own address only.
6
+ """
7
+
8
+ import sys
9
+
10
+ from kovapdf import KovaPDF, KovaPDFError
11
+
12
+ if len(sys.argv) < 4:
13
+ sys.exit('Usage: python examples/sign_request.py file.pdf "Signer Name" signer@example.com')
14
+ file, name, email = sys.argv[1:4]
15
+
16
+ kova = KovaPDF()
17
+ try:
18
+ request = kova.sign_requests.create(
19
+ file,
20
+ {
21
+ "title": "Please sign",
22
+ "sequential": False,
23
+ "signers": [{"name": name, "email": email, "order": 1}],
24
+ "fields": [{"signer": 0, "kind": "SIGNATURE", "page": 1, "x": 72, "y": 640, "width": 180, "height": 48}],
25
+ },
26
+ )
27
+ print(f"Sent request {request['id']} ({request['status']})")
28
+ print(f"You have {len(kova.sign_requests.list())} signature request(s).")
29
+ print("Done with KovaPDF (kovapdf.com).")
30
+ except KovaPDFError as e:
31
+ sys.exit(f"{e.code}: {e.message}")
@@ -0,0 +1,50 @@
1
+ """A webhook receiver that checks KovaPDF's signature before trusting an event.
2
+
3
+ KOVAPDF_WEBHOOK_SECRET=whsec_... python examples/verify_webhook.py listens on PORT (default 3000)
4
+ python examples/verify_webhook.py --demo signs a sample the way KovaPDF does and checks it
5
+ """
6
+
7
+ import hashlib
8
+ import hmac
9
+ import json
10
+ import os
11
+ import sys
12
+ import time
13
+ from http.server import BaseHTTPRequestHandler, HTTPServer
14
+
15
+ from kovapdf import KovaPDFError, verify_webhook
16
+
17
+ if "--demo" in sys.argv:
18
+ secret = "whsec_demo_only"
19
+ body = json.dumps({"id": "d1", "type": "request.completed", "createdAt": "2026-11-10T10:00:00Z", "data": {"request": {"id": "sr1"}}})
20
+ t = int(time.time())
21
+ header = f"t={t},v1=" + hmac.new(secret.encode(), f"{t}.{body}".encode(), hashlib.sha256).hexdigest()
22
+ event = verify_webhook(body, {"KovaPDF-Signature": header}, secret)
23
+ print(f"Verified {event['type']} ({event['id']})")
24
+ try:
25
+ verify_webhook(body.replace("sr1", "sr2"), {"KovaPDF-Signature": header}, secret)
26
+ except KovaPDFError as e:
27
+ print(f"A changed body is refused: {e.code}")
28
+ sys.exit(0)
29
+
30
+ SECRET = os.environ.get("KOVAPDF_WEBHOOK_SECRET")
31
+ if not SECRET:
32
+ sys.exit("Set KOVAPDF_WEBHOOK_SECRET to the endpoint's signing secret from your dashboard.")
33
+
34
+
35
+ class Receiver(BaseHTTPRequestHandler):
36
+ def do_POST(self) -> None:
37
+ raw = self.rfile.read(int(self.headers.get("Content-Length") or 0)) # the raw body, before JSON parsing
38
+ try:
39
+ event = verify_webhook(raw, dict(self.headers), SECRET)
40
+ except KovaPDFError:
41
+ self.send_response(400)
42
+ self.end_headers()
43
+ return
44
+ print(event["type"], event.get("data"))
45
+ self.send_response(200)
46
+ self.end_headers()
47
+
48
+
49
+ print("Listening for KovaPDF webhooks")
50
+ HTTPServer(("", int(os.environ.get("PORT", "3000"))), Receiver).serve_forever()
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["hatchling==1.33.0"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "kovapdf"
7
+ version = "0.1.0"
8
+ description = "The official KovaPDF client for Python: compress, merge, split, convert, read scans, redact, check signatures and send documents for signature. Includes the kovapdf command line tool."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.10"
13
+ authors = [{ name = "KovaPDF", email = "support@kovapdf.com" }]
14
+ keywords = ["pdf", "kovapdf", "compress", "merge", "ocr", "redact", "e-signature", "bijoy", "unicode"]
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Operating System :: OS Independent",
18
+ "Topic :: Office/Business",
19
+ "Typing :: Typed",
20
+ ]
21
+ dependencies = []
22
+
23
+ [project.urls]
24
+ Homepage = "https://www.kovapdf.com"
25
+ Documentation = "https://www.kovapdf.com/developers"
26
+ Security = "https://www.kovapdf.com/security"
27
+
28
+ [project.scripts]
29
+ kovapdf = "kovapdf.cli:main"
30
+
31
+ [tool.hatch.build.targets.wheel]
32
+ packages = ["src/kovapdf"]
33
+
34
+ [tool.hatch.build.targets.sdist]
35
+ include = ["src/kovapdf", "tests", "examples", "README.md", "LICENSE", "SECURITY.md", "CHANGELOG.md"]
36
+
37
+ [tool.pytest.ini_options]
38
+ testpaths = ["tests"]
39
+ pythonpath = ["src"]
@@ -0,0 +1,34 @@
1
+ """KovaPDF for Python: compress, merge, split, convert, read scans, redact,
2
+ check signatures and send documents for signature.
3
+
4
+ from kovapdf import KovaPDF
5
+ kova = KovaPDF() # the key comes from KOVAPDF_API_KEY
6
+ result = kova.compress("in.pdf", level="strong", save_to="out.pdf")
7
+ print(result.attribution) # Done with KovaPDF (kovapdf.com).
8
+ """
9
+
10
+ from ._generated import API_BASE, ATTRIBUTION, ENDPOINTS, SDK_VERSION, SITE_URL, TOOL_IDS, TOOLS
11
+ from ._http import ClientIdentity, Transport, parse_retry_after
12
+ from .client import KovaPDF, ResultFile, RunResult
13
+ from .errors import FRIENDLY, KovaPDFError
14
+ from .webhooks import verify_webhook
15
+
16
+ __version__ = SDK_VERSION
17
+ __all__ = [
18
+ "API_BASE",
19
+ "ATTRIBUTION",
20
+ "ENDPOINTS",
21
+ "FRIENDLY",
22
+ "SDK_VERSION",
23
+ "SITE_URL",
24
+ "TOOLS",
25
+ "TOOL_IDS",
26
+ "ClientIdentity",
27
+ "KovaPDF",
28
+ "KovaPDFError",
29
+ "ResultFile",
30
+ "RunResult",
31
+ "Transport",
32
+ "parse_retry_after",
33
+ "verify_webhook",
34
+ ]
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ sys.exit(main())