gowkhtmltopdf 0.2.5__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,7 @@
1
+ include README.md
2
+ include src/gowkhtmltopdf/py.typed
3
+ recursive-include tests *.py
4
+ recursive-include examples *.py
5
+ prune docs
6
+ prune frontend
7
+ prune testdata
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.4
2
+ Name: gowkhtmltopdf
3
+ Version: 0.2.5
4
+ Summary: In-process Python bindings for the gowkhtmltopdf HTML-to-PDF engine via a ctypes-loaded c-shared library
5
+ Author: Chinmay Sawant
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/chinmay-sawant/gowkhtmltopdf
8
+ Project-URL: Issues, https://github.com/chinmay-sawant/gowkhtmltopdf/issues
9
+ Keywords: html,pdf,wkhtmltopdf,ctypes,invoice
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Operating System :: MacOS :: MacOS X
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
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 :: Text Processing :: Markup :: HTML
24
+ Classifier: Topic :: Printing
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+
28
+ # gowkhtmltopdf (Python)
29
+
30
+ In-process Python bindings for the gowkhtmltopdf HTML-to-PDF engine. The
31
+ package loads `libgowkhtmltopdf` (a Go `-buildmode=c-shared` library) with
32
+ stdlib `ctypes`; there is no subprocess and no compiled Python extension.
33
+
34
+ Requires Python 3.8+. Linux is the first-supported platform; macOS and
35
+ Windows builds follow the wheel matrix.
36
+
37
+ ## Document style
38
+
39
+ Mirrors the Go `Document` API:
40
+
41
+ ```python
42
+ from gowkhtmltopdf import Document, Page, Content
43
+
44
+ doc = Document(
45
+ pages=[Page(source=Content(html=b"<html><body><h1>Invoice</h1></body></html>"))],
46
+ page_size="A4",
47
+ )
48
+ pdf_bytes: bytes = doc.pdf() # or doc.pdf(timeout=30)
49
+ ```
50
+
51
+ ## Helper style
52
+
53
+ ```python
54
+ from gowkhtmltopdf import convert_html_to_pdf, PDFOptions
55
+
56
+ pdf_bytes = convert_html_to_pdf(
57
+ html=b"<html><body><h1>Invoice #42</h1><p>Total: $19.00</p></body></html>",
58
+ options=PDFOptions(page_size="A4", orientation="portrait"),
59
+ )
60
+
61
+ with open("invoice.pdf", "wb") as f:
62
+ f.write(pdf_bytes)
63
+ ```
64
+
65
+ Images work the same way via `ImageDocument` or
66
+ `convert_html_to_image(html, options=ImageOptions(width=1024))`.
67
+
68
+ The full build, install, security (ACL / NetworkPolicy), and ABI
69
+ stability guide lives in [documentation/python.md](../../documentation/python.md).
@@ -0,0 +1,42 @@
1
+ # gowkhtmltopdf (Python)
2
+
3
+ In-process Python bindings for the gowkhtmltopdf HTML-to-PDF engine. The
4
+ package loads `libgowkhtmltopdf` (a Go `-buildmode=c-shared` library) with
5
+ stdlib `ctypes`; there is no subprocess and no compiled Python extension.
6
+
7
+ Requires Python 3.8+. Linux is the first-supported platform; macOS and
8
+ Windows builds follow the wheel matrix.
9
+
10
+ ## Document style
11
+
12
+ Mirrors the Go `Document` API:
13
+
14
+ ```python
15
+ from gowkhtmltopdf import Document, Page, Content
16
+
17
+ doc = Document(
18
+ pages=[Page(source=Content(html=b"<html><body><h1>Invoice</h1></body></html>"))],
19
+ page_size="A4",
20
+ )
21
+ pdf_bytes: bytes = doc.pdf() # or doc.pdf(timeout=30)
22
+ ```
23
+
24
+ ## Helper style
25
+
26
+ ```python
27
+ from gowkhtmltopdf import convert_html_to_pdf, PDFOptions
28
+
29
+ pdf_bytes = convert_html_to_pdf(
30
+ html=b"<html><body><h1>Invoice #42</h1><p>Total: $19.00</p></body></html>",
31
+ options=PDFOptions(page_size="A4", orientation="portrait"),
32
+ )
33
+
34
+ with open("invoice.pdf", "wb") as f:
35
+ f.write(pdf_bytes)
36
+ ```
37
+
38
+ Images work the same way via `ImageDocument` or
39
+ `convert_html_to_image(html, options=ImageOptions(width=1024))`.
40
+
41
+ The full build, install, security (ACL / NetworkPolicy), and ABI
42
+ stability guide lives in [documentation/python.md](../../documentation/python.md).
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env python3
2
+ """Runnable example: both snippet styles produce an invoice PDF.
3
+
4
+ Run from anywhere with a built library on the search path:
5
+
6
+ cd bindings/python && python examples/invoice.py
7
+
8
+ Writes invoice.pdf (Document style) and invoice_high_level.pdf
9
+ (convert_html_to_pdf style) into the current directory.
10
+ """
11
+
12
+ import os
13
+ import sys
14
+
15
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
16
+
17
+ from gowkhtmltopdf import ( # noqa: E402
18
+ Content,
19
+ Document,
20
+ PDFOptions,
21
+ Page,
22
+ convert_html_to_pdf,
23
+ )
24
+
25
+ HTML = (
26
+ b"<html><body>"
27
+ b"<h1>Invoice</h1>"
28
+ b"<p>Invoice #42</p>"
29
+ b"<p>Total: $19.00</p>"
30
+ b"</body></html>"
31
+ )
32
+
33
+
34
+ def main():
35
+ doc = Document(
36
+ pages=[Page(source=Content(html=HTML))],
37
+ page_size="A4",
38
+ )
39
+ document_bytes = doc.pdf()
40
+ assert document_bytes.startswith(b"%PDF-"), "missing %PDF- header"
41
+
42
+ high_level_bytes = convert_html_to_pdf(
43
+ html=HTML,
44
+ options=PDFOptions(page_size="A4", orientation="portrait"),
45
+ )
46
+ assert high_level_bytes.startswith(b"%PDF-"), "missing %PDF- header"
47
+
48
+ with open("invoice.pdf", "wb") as sink:
49
+ sink.write(document_bytes)
50
+ with open("invoice_high_level.pdf", "wb") as sink:
51
+ sink.write(high_level_bytes)
52
+
53
+ print("invoice.pdf: {0} bytes".format(len(document_bytes)))
54
+ print("invoice_high_level.pdf: {0} bytes".format(len(high_level_bytes)))
55
+
56
+
57
+ if __name__ == "__main__":
58
+ main()
@@ -0,0 +1,95 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "gowkhtmltopdf"
7
+ version = "0.2.5"
8
+ description = "In-process Python bindings for the gowkhtmltopdf HTML-to-PDF engine via a ctypes-loaded c-shared library"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Chinmay Sawant" }]
13
+ keywords = ["html", "pdf", "wkhtmltopdf", "ctypes", "invoice"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: POSIX :: Linux",
19
+ "Operating System :: MacOS :: MacOS X",
20
+ "Operating System :: Microsoft :: Windows",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.8",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Topic :: Text Processing :: Markup :: HTML",
29
+ "Topic :: Printing",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/chinmay-sawant/gowkhtmltopdf"
34
+ Issues = "https://github.com/chinmay-sawant/gowkhtmltopdf/issues"
35
+
36
+ [tool.setuptools]
37
+ package-dir = { "" = "src" }
38
+ zip-safe = false
39
+
40
+ [tool.setuptools.packages.find]
41
+ where = ["src"]
42
+
43
+ [tool.setuptools.package-data]
44
+ gowkhtmltopdf = ["libgowkhtmltopdf.*", "py.typed"]
45
+
46
+ # cibuildwheel (Phase 43). Archs are per-platform: never set a global archs
47
+ # list (macOS rejects Linux's aarch64 name). Linux builds the c-shared library
48
+ # inside the manylinux container via before-build; macOS/Windows override
49
+ # CIBW_BEFORE_BUILD in publish-pypi.yml to scripts/build_cshared_for_wheel.sh.
50
+ [tool.cibuildwheel]
51
+ # Wheels are tagged py3-none-<plat> (ctypes-loaded native lib, not a CPython
52
+ # extension), so one CPython build per platform is enough for requires-python
53
+ # >=3.8. Building cp38..cp313 would only overwrite the same tag repeatedly.
54
+ build = "cp311-*"
55
+
56
+ [tool.cibuildwheel.linux]
57
+ # Per-job CIBW_ARCHS_LINUX in the workflow selects x86_64 or aarch64.
58
+ manylinux-x86_64-image = "manylinux_2_28"
59
+ manylinux-aarch64-image = "manylinux_2_28"
60
+ repair-wheel-command = "auditwheel repair --strip -w {dest_dir} {wheel}"
61
+ # {project} is the repo root (cwd where cibuildwheel was invoked). Relative
62
+ # ../.. from the package cwd is wrong and can resolve to /.
63
+ before-build = '''
64
+ set -eux
65
+ ARCH="$(uname -m)"
66
+ case "$ARCH" in
67
+ x86_64|amd64) GOPLAT=amd64 ;;
68
+ aarch64|arm64) GOPLAT=arm64 ;;
69
+ *) echo "unsupported architecture: $ARCH" >&2; exit 1 ;;
70
+ esac
71
+ curl -fsSL "https://go.dev/dl/go1.26.0.linux-${GOPLAT}.tar.gz" -o /tmp/gowk-go.tar.gz
72
+ rm -rf /usr/local/go
73
+ tar -C /usr/local -xzf /tmp/gowk-go.tar.gz
74
+ export PATH="/usr/local/go/bin:$PATH"
75
+ ROOT="{project}"
76
+ test -f "$ROOT/VERSION"
77
+ test -f "$ROOT/go.mod"
78
+ test -d "$ROOT/bindings/c"
79
+ OUT="$ROOT/bindings/python/src/gowkhtmltopdf/libgowkhtmltopdf.so"
80
+ mkdir -p "$(dirname "$OUT")"
81
+ (
82
+ cd "$ROOT" && CGO_ENABLED=1 go build -buildmode=c-shared \
83
+ -ldflags "-X main.libVersion=$(cat VERSION) -s -w" \
84
+ -o "$OUT" ./bindings/c
85
+ )
86
+ test -f "$OUT"
87
+ '''
88
+
89
+ [tool.cibuildwheel.macos]
90
+ # Native arch on macos-latest (Apple Silicon). Workflow sets
91
+ # CIBW_BEFORE_BUILD=bash scripts/build_cshared_for_wheel.sh.
92
+ archs = "arm64"
93
+
94
+ [tool.cibuildwheel.windows]
95
+ # Workflow sets CIBW_BEFORE_BUILD for the host Go + mingw build.
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,61 @@
1
+ """Build shim: VERSION stamp + platform/platlib wheel tags.
2
+
3
+ pyproject.toml carries a static version so the package builds standalone.
4
+ When the repo-root VERSION file exists (normal in-tree and sdist-from-repo
5
+ builds), setup.py overrides that static value so the wheel or sdist always
6
+ matches the release stamp in VERSION.
7
+
8
+ The package ships a prebuilt c-shared library as package data and loads it
9
+ with ctypes. That is not a Python C extension, so setuptools would:
10
+ 1. emit py3-none-any (cibuildwheel rejects pure-Python wheels)
11
+ 2. put .so/.dylib/.dll under purelib (auditwheel rejects that)
12
+
13
+ Force a platform tag (py3-none-<plat>) and a BinaryDistribution so the
14
+ native library lands in platlib and auditwheel can repair the wheel.
15
+ """
16
+
17
+ from pathlib import Path
18
+
19
+ from setuptools import setup
20
+ from setuptools.dist import Distribution
21
+
22
+ try:
23
+ from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
24
+ except ImportError: # pragma: no cover - wheel is listed in build-system.requires
25
+ _bdist_wheel = None
26
+
27
+
28
+ class BinaryDistribution(Distribution):
29
+ """Tell setuptools this package is platform-specific.
30
+
31
+ Without this, package-data shared libraries install into purelib and
32
+ auditwheel fails with "shared library in purelib folder".
33
+ """
34
+
35
+ def has_ext_modules(self):
36
+ return True
37
+
38
+
39
+ class bdist_wheel(_bdist_wheel): # type: ignore[misc,valid-type]
40
+ def finalize_options(self):
41
+ super().finalize_options()
42
+ self.root_is_pure = False
43
+
44
+ def get_tag(self):
45
+ _python, _abi, plat = super().get_tag()
46
+ # ctypes-loaded native lib: one wheel per OS/arch, any CPython 3.x.
47
+ return "py3", "none", plat
48
+
49
+
50
+ _ROOT_VERSION = Path(__file__).resolve().parent.parent.parent / "VERSION"
51
+
52
+ _kwargs = {
53
+ "distclass": BinaryDistribution,
54
+ }
55
+ if _bdist_wheel is not None:
56
+ _kwargs["cmdclass"] = {"bdist_wheel": bdist_wheel}
57
+
58
+ if _ROOT_VERSION.is_file():
59
+ _kwargs["version"] = _ROOT_VERSION.read_text(encoding="utf-8").strip()
60
+
61
+ setup(**_kwargs)
@@ -0,0 +1,134 @@
1
+ """gowkhtmltopdf: in-process Python bindings for the gowkhtmltopdf engine.
2
+
3
+ Two usage styles, both backed by a ctypes-loaded c-shared library:
4
+
5
+ from gowkhtmltopdf import Document, Page, Content
6
+
7
+ doc = Document(
8
+ pages=[Page(source=Content(html=b"<html><body><h1>Invoice</h1></body></html>"))],
9
+ page_size="A4",
10
+ )
11
+ pdf_bytes = doc.pdf()
12
+
13
+ Or the flat helper:
14
+
15
+ from gowkhtmltopdf import convert_html_to_pdf, PDFOptions
16
+
17
+ pdf_bytes = convert_html_to_pdf(
18
+ b"<html><body><h1>Invoice #42</h1></body></html>",
19
+ options=PDFOptions(page_size="A4"),
20
+ )
21
+
22
+ The shared library is located and loaded only when a conversion runs;
23
+ building model objects never touches it.
24
+ """
25
+
26
+ from .exceptions import (
27
+ ConversionError,
28
+ ConversionTimeoutError,
29
+ ErrEmptyContent,
30
+ ErrInvalidContent,
31
+ ErrInvalidOrientation,
32
+ ErrInvalidPDFProfile,
33
+ ErrInvalidPageSize,
34
+ ErrInvalidPDFVersion,
35
+ ErrMissingOutput,
36
+ ErrNoPageObjects,
37
+ GowkhtmltopdfError,
38
+ InternalEngineError,
39
+ InvalidArgumentError,
40
+ LoadDeniedError,
41
+ RenderError,
42
+ ResourceLimitError,
43
+ error_from_status,
44
+ sniff_sentinel,
45
+ )
46
+ from .document import (
47
+ Content,
48
+ Crop,
49
+ Document,
50
+ HeaderFooter,
51
+ ImageDocument,
52
+ ImageOptions,
53
+ Margin,
54
+ NetworkPolicy,
55
+ Page,
56
+ PDFOptions,
57
+ TOC,
58
+ compatible_network_policy,
59
+ restricted_network_policy,
60
+ )
61
+ from .api import (
62
+ convert_file_to_pdf,
63
+ convert_html_to_image,
64
+ convert_html_to_pdf,
65
+ convert_url_to_pdf,
66
+ )
67
+
68
+ __version__ = "0.2.5"
69
+
70
+ #: Upstream settings-surface identifier (api.go LibraryVersion), distinct
71
+ #: from the project release in __version__.
72
+ library_version = "0.12.7-dev"
73
+
74
+
75
+ def abi_version():
76
+ # type: () -> int
77
+ """Return the ABI revision of the loaded shared library (always 1 today).
78
+
79
+ Raises ImportError when the library is missing or built for another ABI.
80
+ """
81
+ from ._lib import abi_version as _abi_version
82
+
83
+ return _abi_version()
84
+
85
+
86
+ def library_version_string():
87
+ # type: () -> str
88
+ """Return the runtime version string reported by the shared library."""
89
+ from ._lib import library_version_string as _lvs
90
+
91
+ return _lvs()
92
+
93
+
94
+ __all__ = [
95
+ "GowkhtmltopdfError",
96
+ "ConversionError",
97
+ "InvalidArgumentError",
98
+ "LoadDeniedError",
99
+ "RenderError",
100
+ "ConversionTimeoutError",
101
+ "ResourceLimitError",
102
+ "InternalEngineError",
103
+ "ErrEmptyContent",
104
+ "ErrInvalidContent",
105
+ "ErrNoPageObjects",
106
+ "ErrInvalidPageSize",
107
+ "ErrInvalidOrientation",
108
+ "ErrInvalidPDFVersion",
109
+ "ErrInvalidPDFProfile",
110
+ "ErrMissingOutput",
111
+ "error_from_status",
112
+ "sniff_sentinel",
113
+ "Content",
114
+ "Page",
115
+ "Margin",
116
+ "HeaderFooter",
117
+ "TOC",
118
+ "Crop",
119
+ "NetworkPolicy",
120
+ "compatible_network_policy",
121
+ "restricted_network_policy",
122
+ "PDFOptions",
123
+ "ImageOptions",
124
+ "Document",
125
+ "ImageDocument",
126
+ "convert_html_to_pdf",
127
+ "convert_file_to_pdf",
128
+ "convert_url_to_pdf",
129
+ "convert_html_to_image",
130
+ "__version__",
131
+ "library_version",
132
+ "abi_version",
133
+ "library_version_string",
134
+ ]