brewdoc-linux-x64-glibc 0.0.0-stage → 0.3.2

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 (576) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -2
  3. package/binary/_internal/PIL/_avif.cpython-312-x86_64-linux-gnu.so +0 -0
  4. package/binary/_internal/PIL/_imaging.cpython-312-x86_64-linux-gnu.so +0 -0
  5. package/binary/_internal/PIL/_imagingcms.cpython-312-x86_64-linux-gnu.so +0 -0
  6. package/binary/_internal/PIL/_imagingft.cpython-312-x86_64-linux-gnu.so +0 -0
  7. package/binary/_internal/PIL/_imagingmath.cpython-312-x86_64-linux-gnu.so +0 -0
  8. package/binary/_internal/PIL/_imagingtk.cpython-312-x86_64-linux-gnu.so +0 -0
  9. package/binary/_internal/PIL/_webp.cpython-312-x86_64-linux-gnu.so +0 -0
  10. package/binary/_internal/_cffi_backend.cpython-312-x86_64-linux-gnu.so +0 -0
  11. package/binary/_internal/_quickjs.abi3.so +0 -0
  12. package/binary/_internal/base_library.zip +0 -0
  13. package/binary/_internal/brewdoc/_urljs/glue.js +858 -0
  14. package/binary/_internal/brewdoc/_vendor/THIRD_PARTY_NOTICES.txt +342 -0
  15. package/binary/_internal/brewdoc/_vendor/linkedom-worker.js +12650 -0
  16. package/binary/_internal/brewdoc-0.3.2.dist-info/INSTALLER +1 -0
  17. package/binary/_internal/brewdoc-0.3.2.dist-info/METADATA +157 -0
  18. package/binary/_internal/brewdoc-0.3.2.dist-info/RECORD +30 -0
  19. package/binary/_internal/brewdoc-0.3.2.dist-info/REQUESTED +0 -0
  20. package/binary/_internal/brewdoc-0.3.2.dist-info/WHEEL +4 -0
  21. package/binary/_internal/brewdoc-0.3.2.dist-info/direct_url.json +1 -0
  22. package/binary/_internal/brewdoc-0.3.2.dist-info/entry_points.txt +2 -0
  23. package/binary/_internal/brewdoc-0.3.2.dist-info/licenses/LICENSE +21 -0
  24. package/binary/_internal/brewdoc-0.3.2.dist-info/uv_cache.json +1 -0
  25. package/binary/_internal/cffi-2.1.1.dist-info/INSTALLER +1 -0
  26. package/binary/_internal/cffi-2.1.1.dist-info/METADATA +67 -0
  27. package/binary/_internal/cffi-2.1.1.dist-info/RECORD +34 -0
  28. package/binary/_internal/cffi-2.1.1.dist-info/REQUESTED +0 -0
  29. package/binary/_internal/cffi-2.1.1.dist-info/WHEEL +6 -0
  30. package/binary/_internal/cffi-2.1.1.dist-info/entry_points.txt +5 -0
  31. package/binary/_internal/cffi-2.1.1.dist-info/licenses/LICENSE +23 -0
  32. package/binary/_internal/cffi-2.1.1.dist-info/top_level.txt +2 -0
  33. package/binary/_internal/charset_normalizer/cd.cpython-312-x86_64-linux-gnu.so +0 -0
  34. package/binary/_internal/charset_normalizer/md.cpython-312-x86_64-linux-gnu.so +0 -0
  35. package/binary/_internal/charset_normalizer-3.5.2.dist-info/INSTALLER +1 -0
  36. package/binary/_internal/charset_normalizer-3.5.2.dist-info/METADATA +892 -0
  37. package/binary/_internal/charset_normalizer-3.5.2.dist-info/RECORD +24 -0
  38. package/binary/_internal/charset_normalizer-3.5.2.dist-info/REQUESTED +0 -0
  39. package/binary/_internal/charset_normalizer-3.5.2.dist-info/WHEEL +7 -0
  40. package/binary/_internal/charset_normalizer-3.5.2.dist-info/entry_points.txt +2 -0
  41. package/binary/_internal/charset_normalizer-3.5.2.dist-info/licenses/LICENSE +21 -0
  42. package/binary/_internal/charset_normalizer-3.5.2.dist-info/top_level.txt +1 -0
  43. package/binary/_internal/cryptography/hazmat/bindings/_rust.abi3.so +0 -0
  44. package/binary/_internal/cryptography-50.0.2.dist-info/INSTALLER +1 -0
  45. package/binary/_internal/cryptography-50.0.2.dist-info/METADATA +111 -0
  46. package/binary/_internal/cryptography-50.0.2.dist-info/RECORD +122 -0
  47. package/binary/_internal/cryptography-50.0.2.dist-info/REQUESTED +0 -0
  48. package/binary/_internal/cryptography-50.0.2.dist-info/WHEEL +5 -0
  49. package/binary/_internal/cryptography-50.0.2.dist-info/licenses/LICENSE +3 -0
  50. package/binary/_internal/cryptography-50.0.2.dist-info/licenses/LICENSE.APACHE +202 -0
  51. package/binary/_internal/cryptography-50.0.2.dist-info/licenses/LICENSE.BSD +27 -0
  52. package/binary/_internal/cryptography-50.0.2.dist-info/sboms/cryptography-rust.cyclonedx.json +1365 -0
  53. package/binary/_internal/cryptography-50.0.2.dist-info/sboms/sbom.json +43 -0
  54. package/binary/_internal/libXau-154567c4.so.6.0.0 +0 -0
  55. package/binary/_internal/libavif-8a7f9d56.so.16.4.2 +0 -0
  56. package/binary/_internal/libbrotlicommon-53534446.so.1.2.0 +0 -0
  57. package/binary/_internal/libbrotlidec-7e5462ba.so.1.2.0 +0 -0
  58. package/binary/_internal/libfreetype-9fc94c80.so.6.20.6 +0 -0
  59. package/binary/_internal/libgcc_s.so.1 +0 -0
  60. package/binary/_internal/libharfbuzz-172d1f63.so.0.61421.0 +0 -0
  61. package/binary/_internal/libjpeg-31e2ca52.so.62.4.0 +0 -0
  62. package/binary/_internal/liblcms2-dade1fbf.so.2.0.19 +0 -0
  63. package/binary/_internal/liblzma-2be87c3e.so.5.8.3 +0 -0
  64. package/binary/_internal/libopenjp2-b07f72ad.so.2.5.4 +0 -0
  65. package/binary/_internal/libpng16-abb096d5.so.16.58.0 +0 -0
  66. package/binary/_internal/libpython3.12.so.1.0 +0 -0
  67. package/binary/_internal/libsharpyuv-0066295b.so.0.1.2 +0 -0
  68. package/binary/_internal/libstdc++.so.6 +0 -0
  69. package/binary/_internal/libtiff-fc87e79d.so.6.2.0 +0 -0
  70. package/binary/_internal/libwebp-51b0b3f7.so.7.2.0 +0 -0
  71. package/binary/_internal/libwebpdemux-9fe2abcc.so.2.0.17 +0 -0
  72. package/binary/_internal/libwebpmux-8fb1c9f6.so.3.1.2 +0 -0
  73. package/binary/_internal/libxcb-ad31f5a3.so.1.1.0 +0 -0
  74. package/binary/_internal/libz.so.1 +0 -0
  75. package/binary/_internal/libzstd-44be1190.so.1.5.7 +0 -0
  76. package/binary/_internal/pdfminer/cmap/78-EUC-H.json.gz +0 -0
  77. package/binary/_internal/pdfminer/cmap/78-EUC-V.json.gz +0 -0
  78. package/binary/_internal/pdfminer/cmap/78-H.json.gz +0 -0
  79. package/binary/_internal/pdfminer/cmap/78-RKSJ-H.json.gz +0 -0
  80. package/binary/_internal/pdfminer/cmap/78-RKSJ-V.json.gz +0 -0
  81. package/binary/_internal/pdfminer/cmap/78-V.json.gz +0 -0
  82. package/binary/_internal/pdfminer/cmap/78ms-RKSJ-H.json.gz +0 -0
  83. package/binary/_internal/pdfminer/cmap/78ms-RKSJ-V.json.gz +0 -0
  84. package/binary/_internal/pdfminer/cmap/83pv-RKSJ-H.json.gz +0 -0
  85. package/binary/_internal/pdfminer/cmap/83pv-RKSJ-V.json.gz +0 -0
  86. package/binary/_internal/pdfminer/cmap/90ms-RKSJ-H.json.gz +0 -0
  87. package/binary/_internal/pdfminer/cmap/90ms-RKSJ-V.json.gz +0 -0
  88. package/binary/_internal/pdfminer/cmap/90msp-RKSJ-H.json.gz +0 -0
  89. package/binary/_internal/pdfminer/cmap/90msp-RKSJ-V.json.gz +0 -0
  90. package/binary/_internal/pdfminer/cmap/90pv-RKSJ-H.json.gz +0 -0
  91. package/binary/_internal/pdfminer/cmap/90pv-RKSJ-V.json.gz +0 -0
  92. package/binary/_internal/pdfminer/cmap/Add-H.json.gz +0 -0
  93. package/binary/_internal/pdfminer/cmap/Add-RKSJ-H.json.gz +0 -0
  94. package/binary/_internal/pdfminer/cmap/Add-RKSJ-V.json.gz +0 -0
  95. package/binary/_internal/pdfminer/cmap/Add-V.json.gz +0 -0
  96. package/binary/_internal/pdfminer/cmap/B5-H.json.gz +0 -0
  97. package/binary/_internal/pdfminer/cmap/B5-V.json.gz +0 -0
  98. package/binary/_internal/pdfminer/cmap/B5pc-H.json.gz +0 -0
  99. package/binary/_internal/pdfminer/cmap/B5pc-V.json.gz +0 -0
  100. package/binary/_internal/pdfminer/cmap/CNS-EUC-H.json.gz +0 -0
  101. package/binary/_internal/pdfminer/cmap/CNS-EUC-V.json.gz +0 -0
  102. package/binary/_internal/pdfminer/cmap/CNS1-H.json.gz +0 -0
  103. package/binary/_internal/pdfminer/cmap/CNS1-V.json.gz +0 -0
  104. package/binary/_internal/pdfminer/cmap/CNS2-H.json.gz +0 -0
  105. package/binary/_internal/pdfminer/cmap/CNS2-V.json.gz +0 -0
  106. package/binary/_internal/pdfminer/cmap/ETHK-B5-H.json.gz +0 -0
  107. package/binary/_internal/pdfminer/cmap/ETHK-B5-V.json.gz +0 -0
  108. package/binary/_internal/pdfminer/cmap/ETen-B5-H.json.gz +0 -0
  109. package/binary/_internal/pdfminer/cmap/ETen-B5-V.json.gz +0 -0
  110. package/binary/_internal/pdfminer/cmap/ETenms-B5-H.json.gz +0 -0
  111. package/binary/_internal/pdfminer/cmap/ETenms-B5-V.json.gz +0 -0
  112. package/binary/_internal/pdfminer/cmap/EUC-H.json.gz +0 -0
  113. package/binary/_internal/pdfminer/cmap/EUC-V.json.gz +0 -0
  114. package/binary/_internal/pdfminer/cmap/Ext-H.json.gz +0 -0
  115. package/binary/_internal/pdfminer/cmap/Ext-RKSJ-H.json.gz +0 -0
  116. package/binary/_internal/pdfminer/cmap/Ext-RKSJ-V.json.gz +0 -0
  117. package/binary/_internal/pdfminer/cmap/Ext-V.json.gz +0 -0
  118. package/binary/_internal/pdfminer/cmap/GB-EUC-H.json.gz +0 -0
  119. package/binary/_internal/pdfminer/cmap/GB-EUC-V.json.gz +0 -0
  120. package/binary/_internal/pdfminer/cmap/GB-H.json.gz +0 -0
  121. package/binary/_internal/pdfminer/cmap/GB-V.json.gz +0 -0
  122. package/binary/_internal/pdfminer/cmap/GBK-EUC-H.json.gz +0 -0
  123. package/binary/_internal/pdfminer/cmap/GBK-EUC-V.json.gz +0 -0
  124. package/binary/_internal/pdfminer/cmap/GBK2K-H.json.gz +0 -0
  125. package/binary/_internal/pdfminer/cmap/GBK2K-V.json.gz +0 -0
  126. package/binary/_internal/pdfminer/cmap/GBKp-EUC-H.json.gz +0 -0
  127. package/binary/_internal/pdfminer/cmap/GBKp-EUC-V.json.gz +0 -0
  128. package/binary/_internal/pdfminer/cmap/GBT-EUC-H.json.gz +0 -0
  129. package/binary/_internal/pdfminer/cmap/GBT-EUC-V.json.gz +0 -0
  130. package/binary/_internal/pdfminer/cmap/GBT-H.json.gz +0 -0
  131. package/binary/_internal/pdfminer/cmap/GBT-V.json.gz +0 -0
  132. package/binary/_internal/pdfminer/cmap/GBTpc-EUC-H.json.gz +0 -0
  133. package/binary/_internal/pdfminer/cmap/GBTpc-EUC-V.json.gz +0 -0
  134. package/binary/_internal/pdfminer/cmap/GBpc-EUC-H.json.gz +0 -0
  135. package/binary/_internal/pdfminer/cmap/GBpc-EUC-V.json.gz +0 -0
  136. package/binary/_internal/pdfminer/cmap/H.json.gz +0 -0
  137. package/binary/_internal/pdfminer/cmap/HKdla-B5-H.json.gz +0 -0
  138. package/binary/_internal/pdfminer/cmap/HKdla-B5-V.json.gz +0 -0
  139. package/binary/_internal/pdfminer/cmap/HKdlb-B5-H.json.gz +0 -0
  140. package/binary/_internal/pdfminer/cmap/HKdlb-B5-V.json.gz +0 -0
  141. package/binary/_internal/pdfminer/cmap/HKgccs-B5-H.json.gz +0 -0
  142. package/binary/_internal/pdfminer/cmap/HKgccs-B5-V.json.gz +0 -0
  143. package/binary/_internal/pdfminer/cmap/HKm314-B5-H.json.gz +0 -0
  144. package/binary/_internal/pdfminer/cmap/HKm314-B5-V.json.gz +0 -0
  145. package/binary/_internal/pdfminer/cmap/HKm471-B5-H.json.gz +0 -0
  146. package/binary/_internal/pdfminer/cmap/HKm471-B5-V.json.gz +0 -0
  147. package/binary/_internal/pdfminer/cmap/HKscs-B5-H.json.gz +0 -0
  148. package/binary/_internal/pdfminer/cmap/HKscs-B5-V.json.gz +0 -0
  149. package/binary/_internal/pdfminer/cmap/Hankaku-H.json.gz +0 -0
  150. package/binary/_internal/pdfminer/cmap/Hankaku-V.json.gz +0 -0
  151. package/binary/_internal/pdfminer/cmap/Hiragana-H.json.gz +0 -0
  152. package/binary/_internal/pdfminer/cmap/Hiragana-V.json.gz +0 -0
  153. package/binary/_internal/pdfminer/cmap/KSC-EUC-H.json.gz +0 -0
  154. package/binary/_internal/pdfminer/cmap/KSC-EUC-V.json.gz +0 -0
  155. package/binary/_internal/pdfminer/cmap/KSC-H.json.gz +0 -0
  156. package/binary/_internal/pdfminer/cmap/KSC-Johab-H.json.gz +0 -0
  157. package/binary/_internal/pdfminer/cmap/KSC-Johab-V.json.gz +0 -0
  158. package/binary/_internal/pdfminer/cmap/KSC-V.json.gz +0 -0
  159. package/binary/_internal/pdfminer/cmap/KSCms-UHC-H.json.gz +0 -0
  160. package/binary/_internal/pdfminer/cmap/KSCms-UHC-HW-H.json.gz +0 -0
  161. package/binary/_internal/pdfminer/cmap/KSCms-UHC-HW-V.json.gz +0 -0
  162. package/binary/_internal/pdfminer/cmap/KSCms-UHC-V.json.gz +0 -0
  163. package/binary/_internal/pdfminer/cmap/KSCpc-EUC-H.json.gz +0 -0
  164. package/binary/_internal/pdfminer/cmap/KSCpc-EUC-V.json.gz +0 -0
  165. package/binary/_internal/pdfminer/cmap/Katakana-H.json.gz +0 -0
  166. package/binary/_internal/pdfminer/cmap/Katakana-V.json.gz +0 -0
  167. package/binary/_internal/pdfminer/cmap/NWP-H.json.gz +0 -0
  168. package/binary/_internal/pdfminer/cmap/NWP-V.json.gz +0 -0
  169. package/binary/_internal/pdfminer/cmap/README.txt +79 -0
  170. package/binary/_internal/pdfminer/cmap/RKSJ-H.json.gz +0 -0
  171. package/binary/_internal/pdfminer/cmap/RKSJ-V.json.gz +0 -0
  172. package/binary/_internal/pdfminer/cmap/Roman-H.json.gz +0 -0
  173. package/binary/_internal/pdfminer/cmap/Roman-V.json.gz +0 -0
  174. package/binary/_internal/pdfminer/cmap/UniCNS-UCS2-H.json.gz +0 -0
  175. package/binary/_internal/pdfminer/cmap/UniCNS-UCS2-V.json.gz +0 -0
  176. package/binary/_internal/pdfminer/cmap/UniCNS-UTF16-H.json.gz +0 -0
  177. package/binary/_internal/pdfminer/cmap/UniCNS-UTF16-V.json.gz +0 -0
  178. package/binary/_internal/pdfminer/cmap/UniCNS-UTF32-H.json.gz +0 -0
  179. package/binary/_internal/pdfminer/cmap/UniCNS-UTF32-V.json.gz +0 -0
  180. package/binary/_internal/pdfminer/cmap/UniCNS-UTF8-H.json.gz +0 -0
  181. package/binary/_internal/pdfminer/cmap/UniCNS-UTF8-V.json.gz +0 -0
  182. package/binary/_internal/pdfminer/cmap/UniGB-UCS2-H.json.gz +0 -0
  183. package/binary/_internal/pdfminer/cmap/UniGB-UCS2-V.json.gz +0 -0
  184. package/binary/_internal/pdfminer/cmap/UniGB-UTF16-H.json.gz +0 -0
  185. package/binary/_internal/pdfminer/cmap/UniGB-UTF16-V.json.gz +0 -0
  186. package/binary/_internal/pdfminer/cmap/UniGB-UTF32-H.json.gz +0 -0
  187. package/binary/_internal/pdfminer/cmap/UniGB-UTF32-V.json.gz +0 -0
  188. package/binary/_internal/pdfminer/cmap/UniGB-UTF8-H.json.gz +0 -0
  189. package/binary/_internal/pdfminer/cmap/UniGB-UTF8-V.json.gz +0 -0
  190. package/binary/_internal/pdfminer/cmap/UniJIS-UCS2-H.json.gz +0 -0
  191. package/binary/_internal/pdfminer/cmap/UniJIS-UCS2-HW-H.json.gz +0 -0
  192. package/binary/_internal/pdfminer/cmap/UniJIS-UCS2-HW-V.json.gz +0 -0
  193. package/binary/_internal/pdfminer/cmap/UniJIS-UCS2-V.json.gz +0 -0
  194. package/binary/_internal/pdfminer/cmap/UniJIS-UTF16-H.json.gz +0 -0
  195. package/binary/_internal/pdfminer/cmap/UniJIS-UTF16-V.json.gz +0 -0
  196. package/binary/_internal/pdfminer/cmap/UniJIS-UTF32-H.json.gz +0 -0
  197. package/binary/_internal/pdfminer/cmap/UniJIS-UTF32-V.json.gz +0 -0
  198. package/binary/_internal/pdfminer/cmap/UniJIS-UTF8-H.json.gz +0 -0
  199. package/binary/_internal/pdfminer/cmap/UniJIS-UTF8-V.json.gz +0 -0
  200. package/binary/_internal/pdfminer/cmap/UniJIS2004-UTF16-H.json.gz +0 -0
  201. package/binary/_internal/pdfminer/cmap/UniJIS2004-UTF16-V.json.gz +0 -0
  202. package/binary/_internal/pdfminer/cmap/UniJIS2004-UTF32-H.json.gz +0 -0
  203. package/binary/_internal/pdfminer/cmap/UniJIS2004-UTF32-V.json.gz +0 -0
  204. package/binary/_internal/pdfminer/cmap/UniJIS2004-UTF8-H.json.gz +0 -0
  205. package/binary/_internal/pdfminer/cmap/UniJIS2004-UTF8-V.json.gz +0 -0
  206. package/binary/_internal/pdfminer/cmap/UniJISX0213-UTF32-H.json.gz +0 -0
  207. package/binary/_internal/pdfminer/cmap/UniJISX0213-UTF32-V.json.gz +0 -0
  208. package/binary/_internal/pdfminer/cmap/UniJISX02132004-UTF32-H.json.gz +0 -0
  209. package/binary/_internal/pdfminer/cmap/UniJISX02132004-UTF32-V.json.gz +0 -0
  210. package/binary/_internal/pdfminer/cmap/UniKS-UCS2-H.json.gz +0 -0
  211. package/binary/_internal/pdfminer/cmap/UniKS-UCS2-V.json.gz +0 -0
  212. package/binary/_internal/pdfminer/cmap/UniKS-UTF16-H.json.gz +0 -0
  213. package/binary/_internal/pdfminer/cmap/UniKS-UTF16-V.json.gz +0 -0
  214. package/binary/_internal/pdfminer/cmap/UniKS-UTF32-H.json.gz +0 -0
  215. package/binary/_internal/pdfminer/cmap/UniKS-UTF32-V.json.gz +0 -0
  216. package/binary/_internal/pdfminer/cmap/UniKS-UTF8-H.json.gz +0 -0
  217. package/binary/_internal/pdfminer/cmap/UniKS-UTF8-V.json.gz +0 -0
  218. package/binary/_internal/pdfminer/cmap/V.json.gz +0 -0
  219. package/binary/_internal/pdfminer/cmap/WP-Symbol-H.json.gz +0 -0
  220. package/binary/_internal/pdfminer/cmap/WP-Symbol-V.json.gz +0 -0
  221. package/binary/_internal/pdfminer/cmap/to-unicode-Adobe-CNS1.json.gz +0 -0
  222. package/binary/_internal/pdfminer/cmap/to-unicode-Adobe-GB1.json.gz +0 -0
  223. package/binary/_internal/pdfminer/cmap/to-unicode-Adobe-Japan1.json.gz +0 -0
  224. package/binary/_internal/pdfminer/cmap/to-unicode-Adobe-Korea1.json.gz +0 -0
  225. package/binary/_internal/pdfminer/py.typed +0 -0
  226. package/binary/_internal/pdfminer_six-20260107.dist-info/INSTALLER +1 -0
  227. package/binary/_internal/pdfminer_six-20260107.dist-info/METADATA +110 -0
  228. package/binary/_internal/pdfminer_six-20260107.dist-info/RECORD +191 -0
  229. package/binary/_internal/pdfminer_six-20260107.dist-info/REQUESTED +0 -0
  230. package/binary/_internal/pdfminer_six-20260107.dist-info/WHEEL +5 -0
  231. package/binary/_internal/pdfminer_six-20260107.dist-info/licenses/LICENSE +22 -0
  232. package/binary/_internal/pdfminer_six-20260107.dist-info/top_level.txt +1 -0
  233. package/binary/_internal/pdfplumber-0.11.10.dist-info/INSTALLER +1 -0
  234. package/binary/_internal/pdfplumber-0.11.10.dist-info/METADATA +617 -0
  235. package/binary/_internal/pdfplumber-0.11.10.dist-info/RECORD +30 -0
  236. package/binary/_internal/pdfplumber-0.11.10.dist-info/REQUESTED +0 -0
  237. package/binary/_internal/pdfplumber-0.11.10.dist-info/WHEEL +5 -0
  238. package/binary/_internal/pdfplumber-0.11.10.dist-info/entry_points.txt +2 -0
  239. package/binary/_internal/pdfplumber-0.11.10.dist-info/licenses/LICENSE.txt +21 -0
  240. package/binary/_internal/pdfplumber-0.11.10.dist-info/top_level.txt +1 -0
  241. package/binary/_internal/pillow-12.3.0.dist-info/INSTALLER +1 -0
  242. package/binary/_internal/pillow-12.3.0.dist-info/METADATA +180 -0
  243. package/binary/_internal/pillow-12.3.0.dist-info/RECORD +142 -0
  244. package/binary/_internal/pillow-12.3.0.dist-info/REQUESTED +0 -0
  245. package/binary/_internal/pillow-12.3.0.dist-info/WHEEL +6 -0
  246. package/binary/_internal/pillow-12.3.0.dist-info/licenses/LICENSE +1574 -0
  247. package/binary/_internal/pillow-12.3.0.dist-info/sboms/auditwheel.cdx.json +1 -0
  248. package/binary/_internal/pillow-12.3.0.dist-info/sboms/pillow-12.3.0.cdx.json +721 -0
  249. package/binary/_internal/pillow-12.3.0.dist-info/top_level.txt +1 -0
  250. package/binary/_internal/pillow-12.3.0.dist-info/zip-safe +1 -0
  251. package/binary/_internal/pillow.libs/libXau-154567c4.so.6.0.0 +0 -0
  252. package/binary/_internal/pillow.libs/libavif-8a7f9d56.so.16.4.2 +0 -0
  253. package/binary/_internal/pillow.libs/libbrotlicommon-53534446.so.1.2.0 +0 -0
  254. package/binary/_internal/pillow.libs/libbrotlidec-7e5462ba.so.1.2.0 +0 -0
  255. package/binary/_internal/pillow.libs/libfreetype-9fc94c80.so.6.20.6 +0 -0
  256. package/binary/_internal/pillow.libs/libharfbuzz-172d1f63.so.0.61421.0 +0 -0
  257. package/binary/_internal/pillow.libs/libjpeg-31e2ca52.so.62.4.0 +0 -0
  258. package/binary/_internal/pillow.libs/liblcms2-dade1fbf.so.2.0.19 +0 -0
  259. package/binary/_internal/pillow.libs/liblzma-2be87c3e.so.5.8.3 +0 -0
  260. package/binary/_internal/pillow.libs/libopenjp2-b07f72ad.so.2.5.4 +0 -0
  261. package/binary/_internal/pillow.libs/libpng16-abb096d5.so.16.58.0 +0 -0
  262. package/binary/_internal/pillow.libs/libsharpyuv-0066295b.so.0.1.2 +0 -0
  263. package/binary/_internal/pillow.libs/libtiff-fc87e79d.so.6.2.0 +0 -0
  264. package/binary/_internal/pillow.libs/libwebp-51b0b3f7.so.7.2.0 +0 -0
  265. package/binary/_internal/pillow.libs/libwebpdemux-9fe2abcc.so.2.0.17 +0 -0
  266. package/binary/_internal/pillow.libs/libwebpmux-8fb1c9f6.so.3.1.2 +0 -0
  267. package/binary/_internal/pillow.libs/libxcb-ad31f5a3.so.1.1.0 +0 -0
  268. package/binary/_internal/pillow.libs/libzstd-44be1190.so.1.5.7 +0 -0
  269. package/binary/_internal/pycparser-3.0.dist-info/INSTALLER +1 -0
  270. package/binary/_internal/pycparser-3.0.dist-info/METADATA +244 -0
  271. package/binary/_internal/pycparser-3.0.dist-info/RECORD +15 -0
  272. package/binary/_internal/pycparser-3.0.dist-info/REQUESTED +0 -0
  273. package/binary/_internal/pycparser-3.0.dist-info/WHEEL +5 -0
  274. package/binary/_internal/pycparser-3.0.dist-info/licenses/LICENSE +27 -0
  275. package/binary/_internal/pycparser-3.0.dist-info/top_level.txt +1 -0
  276. package/binary/_internal/pypdfium2/version.json +11 -0
  277. package/binary/_internal/pypdfium2-5.13.0.dist-info/INSTALLER +1 -0
  278. package/binary/_internal/pypdfium2-5.13.0.dist-info/METADATA +1139 -0
  279. package/binary/_internal/pypdfium2-5.13.0.dist-info/RECORD +75 -0
  280. package/binary/_internal/pypdfium2-5.13.0.dist-info/REQUESTED +0 -0
  281. package/binary/_internal/pypdfium2-5.13.0.dist-info/WHEEL +6 -0
  282. package/binary/_internal/pypdfium2-5.13.0.dist-info/entry_points.txt +2 -0
  283. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/LICENSES/Apache-2.0.txt +202 -0
  284. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/LICENSES/BSD-3-Clause.txt +26 -0
  285. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/LICENSES/CC-BY-4.0.txt +317 -0
  286. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/abseil.txt +203 -0
  287. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/agg23.txt +14 -0
  288. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/fast_float.txt +27 -0
  289. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/freetype.txt +169 -0
  290. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/icu.txt +568 -0
  291. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/lcms.txt +27 -0
  292. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libjpeg_turbo.ijg +260 -0
  293. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libjpeg_turbo.md +135 -0
  294. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libopenjpeg.txt +32 -0
  295. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libpng.txt +134 -0
  296. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libtiff.txt +21 -0
  297. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/llvm-libc.txt +278 -0
  298. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/pdfium-binaries.txt +9 -0
  299. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/pdfium.txt +230 -0
  300. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/simdutf.txt +18 -0
  301. package/binary/_internal/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/zlib.txt +29 -0
  302. package/binary/_internal/pypdfium2-5.13.0.dist-info/top_level.txt +4 -0
  303. package/binary/_internal/pypdfium2_raw/libpdfium.so +0 -0
  304. package/binary/_internal/pypdfium2_raw/version.json +10 -0
  305. package/binary/_internal/python_calamine/_python_calamine.cpython-312-x86_64-linux-gnu.so +0 -0
  306. package/binary/_internal/python_calamine-0.8.2.dist-info/INSTALLER +1 -0
  307. package/binary/_internal/python_calamine-0.8.2.dist-info/METADATA +94 -0
  308. package/binary/_internal/python_calamine-0.8.2.dist-info/RECORD +11 -0
  309. package/binary/_internal/python_calamine-0.8.2.dist-info/REQUESTED +0 -0
  310. package/binary/_internal/python_calamine-0.8.2.dist-info/WHEEL +5 -0
  311. package/binary/_internal/python_calamine-0.8.2.dist-info/licenses/LICENSE +21 -0
  312. package/binary/_internal/python_calamine-0.8.2.dist-info/sboms/python-calamine.cyclonedx.json +1615 -0
  313. package/binary/_internal/quickjs_ng-0.17.0.1.dist-info/INSTALLER +1 -0
  314. package/binary/_internal/quickjs_ng-0.17.0.1.dist-info/METADATA +161 -0
  315. package/binary/_internal/quickjs_ng-0.17.0.1.dist-info/RECORD +9 -0
  316. package/binary/_internal/quickjs_ng-0.17.0.1.dist-info/REQUESTED +0 -0
  317. package/binary/_internal/quickjs_ng-0.17.0.1.dist-info/WHEEL +7 -0
  318. package/binary/_internal/quickjs_ng-0.17.0.1.dist-info/licenses/LICENSE +21 -0
  319. package/binary/_internal/quickjs_ng-0.17.0.1.dist-info/top_level.txt +2 -0
  320. package/binary/_internal/selectolax/base.pxi +4 -0
  321. package/binary/_internal/selectolax/lexbor/attrs.pxi +123 -0
  322. package/binary/_internal/selectolax/lexbor/fragment_lookup.pxi +52 -0
  323. package/binary/_internal/selectolax/lexbor/node.pxi +1355 -0
  324. package/binary/_internal/selectolax/lexbor/node_remove.pxi +29 -0
  325. package/binary/_internal/selectolax/lexbor/selection.pxi +251 -0
  326. package/binary/_internal/selectolax/lexbor/util.pxi +114 -0
  327. package/binary/_internal/selectolax/lexbor.c +66981 -0
  328. package/binary/_internal/selectolax/lexbor.cpython-312-x86_64-linux-gnu.so +0 -0
  329. package/binary/_internal/selectolax/lexbor.pxd +682 -0
  330. package/binary/_internal/selectolax/lexbor.pyi +1534 -0
  331. package/binary/_internal/selectolax/lexbor.pyx +1046 -0
  332. package/binary/_internal/selectolax/modest/node.pxi +976 -0
  333. package/binary/_internal/selectolax/modest/selection.pxi +199 -0
  334. package/binary/_internal/selectolax/modest/util.pxi +20 -0
  335. package/binary/_internal/selectolax/py.typed +0 -0
  336. package/binary/_internal/selectolax/utils.pxi +117 -0
  337. package/binary/_internal/selectolax-0.4.13.dist-info/INSTALLER +1 -0
  338. package/binary/_internal/selectolax-0.4.13.dist-info/METADATA +222 -0
  339. package/binary/_internal/selectolax-0.4.13.dist-info/RECORD +30 -0
  340. package/binary/_internal/selectolax-0.4.13.dist-info/REQUESTED +0 -0
  341. package/binary/_internal/selectolax-0.4.13.dist-info/WHEEL +7 -0
  342. package/binary/_internal/selectolax-0.4.13.dist-info/licenses/LICENSE +10 -0
  343. package/binary/_internal/selectolax-0.4.13.dist-info/top_level.txt +1 -0
  344. package/binary/brewdoc +0 -0
  345. package/binary/licenses/installed/brewdoc/brewdoc/_vendor/THIRD_PARTY_NOTICES.txt +342 -0
  346. package/binary/licenses/installed/brewdoc/brewdoc-0.3.2.dist-info/licenses/LICENSE +21 -0
  347. package/binary/licenses/installed/cffi/cffi-2.1.1.dist-info/licenses/LICENSE +23 -0
  348. package/binary/licenses/installed/charset-normalizer/charset_normalizer-3.5.2.dist-info/licenses/LICENSE +21 -0
  349. package/binary/licenses/installed/cryptography/cryptography-50.0.2.dist-info/licenses/LICENSE +3 -0
  350. package/binary/licenses/installed/cryptography/cryptography-50.0.2.dist-info/licenses/LICENSE.APACHE +202 -0
  351. package/binary/licenses/installed/cryptography/cryptography-50.0.2.dist-info/licenses/LICENSE.BSD +27 -0
  352. package/binary/licenses/installed/interpreter/LICENSE.txt +279 -0
  353. package/binary/licenses/installed/native-runtime/GPL-3 +674 -0
  354. package/binary/licenses/installed/native-runtime/gcc-12-base-amd64-copyright +1512 -0
  355. package/binary/licenses/installed/pdfminer.six/pdfminer_six-20260107.dist-info/licenses/LICENSE +22 -0
  356. package/binary/licenses/installed/pdfplumber/pdfplumber-0.11.10.dist-info/licenses/LICENSE.txt +21 -0
  357. package/binary/licenses/installed/pillow/pillow-12.3.0.dist-info/licenses/LICENSE +1574 -0
  358. package/binary/licenses/installed/pycparser/pycparser-3.0.dist-info/licenses/LICENSE +27 -0
  359. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/LICENSES/Apache-2.0.txt +202 -0
  360. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/LICENSES/BSD-3-Clause.txt +26 -0
  361. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/LICENSES/CC-BY-4.0.txt +317 -0
  362. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/abseil.txt +203 -0
  363. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/agg23.txt +14 -0
  364. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/fast_float.txt +27 -0
  365. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/freetype.txt +169 -0
  366. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/icu.txt +568 -0
  367. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/lcms.txt +27 -0
  368. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libjpeg_turbo.ijg +260 -0
  369. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libjpeg_turbo.md +135 -0
  370. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libopenjpeg.txt +32 -0
  371. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libpng.txt +134 -0
  372. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/libtiff.txt +21 -0
  373. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/llvm-libc.txt +278 -0
  374. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/pdfium-binaries.txt +9 -0
  375. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/pdfium.txt +230 -0
  376. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/simdutf.txt +18 -0
  377. package/binary/licenses/installed/pypdfium2/pypdfium2-5.13.0.dist-info/licenses/data/linux_x64/BUILD_LICENSES/zlib.txt +29 -0
  378. package/binary/licenses/installed/python-calamine/python_calamine-0.8.2.dist-info/licenses/LICENSE +21 -0
  379. package/binary/licenses/installed/quickjs-ng/quickjs_ng-0.17.0.1.dist-info/licenses/LICENSE +21 -0
  380. package/binary/licenses/installed/runtime-hooks/pyi_rth_cryptography_openssl.py +20 -0
  381. package/binary/licenses/installed/runtime-hooks/pyi_rth_inspect.py +99 -0
  382. package/binary/licenses/installed/runtime-hooks/pyi_rth_multiprocessing.py +88 -0
  383. package/binary/licenses/installed/runtime-hooks/pyi_rth_pkgutil.py +64 -0
  384. package/binary/licenses/installed/selectolax/selectolax-0.4.13.dist-info/licenses/LICENSE +10 -0
  385. package/binary/licenses/installed-manifest.json +202 -0
  386. package/binary/licenses/supplemental/openssl/3.5.9/README-copyright.txt +9 -0
  387. package/binary/licenses/supplemental/openssl/4.0.3/README-copyright.txt +9 -0
  388. package/binary/licenses/supplemental/provenance.json +2347 -0
  389. package/binary/licenses/supplemental/pyinstaller-6.22.3/COPYING.txt +648 -0
  390. package/binary/licenses/supplemental/pyinstaller-6.22.3/bootloader/waflib/LICENSE +25 -0
  391. package/binary/licenses/supplemental/pyinstaller-6.22.3/bootloader/zlib/LICENSE +22 -0
  392. package/binary/licenses/supplemental/pyinstaller-6.22.3/doc/license.rst +24 -0
  393. package/binary/licenses/supplemental/pyinstaller-hooks-contrib-2026.8/LICENSE +521 -0
  394. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE +373 -0
  395. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.bdb.txt +126 -0
  396. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.bzip2.txt +37 -0
  397. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.cpython.txt +771 -0
  398. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.expat.txt +21 -0
  399. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.libX11.txt +942 -0
  400. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.libXau.txt +21 -0
  401. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.libedit.txt +29 -0
  402. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.libffi.txt +21 -0
  403. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.liblzma.txt +13 -0
  404. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.libuuid.txt +27 -0
  405. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.libxcb.txt +30 -0
  406. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.mpdecimal.txt +24 -0
  407. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.ncurses.txt +29 -0
  408. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.openssl-1.1.txt +124 -0
  409. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.openssl-3.txt +177 -0
  410. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.sqlite.txt +23 -0
  411. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.tcl.txt +40 -0
  412. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.tix.txt +54 -0
  413. package/binary/licenses/supplemental/python-build-standalone-20260929/LICENSE.zlib.txt +21 -0
  414. package/binary/licenses/supplemental/python-calamine-0.8.2/LICENSE +21 -0
  415. package/binary/licenses/supplemental/python-calamine-0.8.2/source-identity/Cargo.lock +620 -0
  416. package/binary/licenses/supplemental/python-calamine-0.8.2/source-identity/Cargo.toml +22 -0
  417. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/LICENSE +21 -0
  418. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/cutils.h.txt +24 -0
  419. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/dtoa.c.txt +23 -0
  420. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/dtoa.h.txt +23 -0
  421. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/libregexp-opcode.h.txt +23 -0
  422. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/libregexp.c.txt +23 -0
  423. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/libregexp.h.txt +23 -0
  424. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/libunicode.c.txt +23 -0
  425. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/libunicode.h.txt +23 -0
  426. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/list.h.txt +23 -0
  427. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/quickjs-atom.h.txt +24 -0
  428. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/quickjs-opcode.h.txt +24 -0
  429. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/quickjs.c.txt +26 -0
  430. package/binary/licenses/supplemental/quickjs-ng-0.17.0.1/engine-headers/upstream-quickjs/quickjs.h.txt +26 -0
  431. package/binary/licenses/supplemental/rust-adler2-2.0.1/LICENSE-0BSD +12 -0
  432. package/binary/licenses/supplemental/rust-adler2-2.0.1/LICENSE-APACHE +201 -0
  433. package/binary/licenses/supplemental/rust-adler2-2.0.1/LICENSE-MIT +23 -0
  434. package/binary/licenses/supplemental/rust-android_system_properties-0.1.5/LICENSE-APACHE +13 -0
  435. package/binary/licenses/supplemental/rust-android_system_properties-0.1.5/LICENSE-MIT +20 -0
  436. package/binary/licenses/supplemental/rust-atoi_simd-0.18.1/LICENSE-APACHE +201 -0
  437. package/binary/licenses/supplemental/rust-atoi_simd-0.18.1/LICENSE-MIT +25 -0
  438. package/binary/licenses/supplemental/rust-autocfg-1.5.1/LICENSE-APACHE +201 -0
  439. package/binary/licenses/supplemental/rust-autocfg-1.5.1/LICENSE-MIT +25 -0
  440. package/binary/licenses/supplemental/rust-bumpalo-3.20.3/LICENSE-APACHE +201 -0
  441. package/binary/licenses/supplemental/rust-bumpalo-3.20.3/LICENSE-MIT +25 -0
  442. package/binary/licenses/supplemental/rust-byteorder-1.5.0/COPYING +3 -0
  443. package/binary/licenses/supplemental/rust-byteorder-1.5.0/LICENSE-MIT +21 -0
  444. package/binary/licenses/supplemental/rust-calamine-0.36.0/LICENSE-MIT.md +23 -0
  445. package/binary/licenses/supplemental/rust-cc-1.2.64/LICENSE-APACHE +201 -0
  446. package/binary/licenses/supplemental/rust-cc-1.2.64/LICENSE-MIT +25 -0
  447. package/binary/licenses/supplemental/rust-cfg-if-1.0.4/LICENSE-APACHE +201 -0
  448. package/binary/licenses/supplemental/rust-cfg-if-1.0.4/LICENSE-MIT +25 -0
  449. package/binary/licenses/supplemental/rust-chrono-0.4.45/LICENSE.txt +240 -0
  450. package/binary/licenses/supplemental/rust-codepage-0.1.2/COPYRIGHT +9 -0
  451. package/binary/licenses/supplemental/rust-codepage-0.1.2/LICENSE-APACHE +202 -0
  452. package/binary/licenses/supplemental/rust-codepage-0.1.2/LICENSE-MIT +25 -0
  453. package/binary/licenses/supplemental/rust-core-foundation-sys-0.8.7/LICENSE-APACHE +201 -0
  454. package/binary/licenses/supplemental/rust-core-foundation-sys-0.8.7/LICENSE-MIT +25 -0
  455. package/binary/licenses/supplemental/rust-crc32fast-1.5.0/LICENSE-APACHE +202 -0
  456. package/binary/licenses/supplemental/rust-crc32fast-1.5.0/LICENSE-MIT +21 -0
  457. package/binary/licenses/supplemental/rust-debug_unsafe-0.1.4/LICENSE-APACHE +201 -0
  458. package/binary/licenses/supplemental/rust-debug_unsafe-0.1.4/LICENSE-MIT +25 -0
  459. package/binary/licenses/supplemental/rust-encoding_rs-0.8.35/COPYRIGHT +17 -0
  460. package/binary/licenses/supplemental/rust-encoding_rs-0.8.35/LICENSE-APACHE +202 -0
  461. package/binary/licenses/supplemental/rust-encoding_rs-0.8.35/LICENSE-MIT +25 -0
  462. package/binary/licenses/supplemental/rust-encoding_rs-0.8.35/LICENSE-WHATWG +26 -0
  463. package/binary/licenses/supplemental/rust-equivalent-1.0.2/LICENSE-APACHE +201 -0
  464. package/binary/licenses/supplemental/rust-equivalent-1.0.2/LICENSE-MIT +25 -0
  465. package/binary/licenses/supplemental/rust-fast-float2-0.2.3/LICENSE-APACHE +201 -0
  466. package/binary/licenses/supplemental/rust-fast-float2-0.2.3/LICENSE-MIT +23 -0
  467. package/binary/licenses/supplemental/rust-find-msvc-tools-0.1.9/LICENSE-APACHE +201 -0
  468. package/binary/licenses/supplemental/rust-find-msvc-tools-0.1.9/LICENSE-MIT +25 -0
  469. package/binary/licenses/supplemental/rust-flate2-1.1.9/LICENSE-APACHE +201 -0
  470. package/binary/licenses/supplemental/rust-flate2-1.1.9/LICENSE-MIT +25 -0
  471. package/binary/licenses/supplemental/rust-futures-core-0.3.32/LICENSE-APACHE +202 -0
  472. package/binary/licenses/supplemental/rust-futures-core-0.3.32/LICENSE-MIT +26 -0
  473. package/binary/licenses/supplemental/rust-futures-task-0.3.32/LICENSE-APACHE +202 -0
  474. package/binary/licenses/supplemental/rust-futures-task-0.3.32/LICENSE-MIT +26 -0
  475. package/binary/licenses/supplemental/rust-futures-util-0.3.32/LICENSE-APACHE +202 -0
  476. package/binary/licenses/supplemental/rust-futures-util-0.3.32/LICENSE-MIT +26 -0
  477. package/binary/licenses/supplemental/rust-hashbrown-0.17.1/LICENSE-APACHE +201 -0
  478. package/binary/licenses/supplemental/rust-hashbrown-0.17.1/LICENSE-MIT +25 -0
  479. package/binary/licenses/supplemental/rust-heck-0.5.0/LICENSE-APACHE +201 -0
  480. package/binary/licenses/supplemental/rust-heck-0.5.0/LICENSE-MIT +25 -0
  481. package/binary/licenses/supplemental/rust-iana-time-zone-0.1.65/LICENSE-APACHE +201 -0
  482. package/binary/licenses/supplemental/rust-iana-time-zone-0.1.65/LICENSE-MIT +25 -0
  483. package/binary/licenses/supplemental/rust-iana-time-zone-haiku-0.1.2/LICENSE-APACHE +201 -0
  484. package/binary/licenses/supplemental/rust-iana-time-zone-haiku-0.1.2/LICENSE-MIT +25 -0
  485. package/binary/licenses/supplemental/rust-indexmap-2.14.0/LICENSE-APACHE +201 -0
  486. package/binary/licenses/supplemental/rust-indexmap-2.14.0/LICENSE-MIT +25 -0
  487. package/binary/licenses/supplemental/rust-js-sys-0.3.102/LICENSE-APACHE +201 -0
  488. package/binary/licenses/supplemental/rust-js-sys-0.3.102/LICENSE-MIT +25 -0
  489. package/binary/licenses/supplemental/rust-libc-0.2.186/LICENSE-APACHE +176 -0
  490. package/binary/licenses/supplemental/rust-libc-0.2.186/LICENSE-MIT +25 -0
  491. package/binary/licenses/supplemental/rust-log-0.4.32/LICENSE-APACHE +201 -0
  492. package/binary/licenses/supplemental/rust-log-0.4.32/LICENSE-MIT +25 -0
  493. package/binary/licenses/supplemental/rust-memchr-2.8.2/COPYING +3 -0
  494. package/binary/licenses/supplemental/rust-memchr-2.8.2/LICENSE-MIT +21 -0
  495. package/binary/licenses/supplemental/rust-miniz_oxide-0.8.9/LICENSE +25 -0
  496. package/binary/licenses/supplemental/rust-miniz_oxide-0.8.9/LICENSE-APACHE.md +177 -0
  497. package/binary/licenses/supplemental/rust-miniz_oxide-0.8.9/LICENSE-MIT.md +24 -0
  498. package/binary/licenses/supplemental/rust-miniz_oxide-0.8.9/LICENSE-ZLIB.md +14 -0
  499. package/binary/licenses/supplemental/rust-num-traits-0.2.19/LICENSE-APACHE +201 -0
  500. package/binary/licenses/supplemental/rust-num-traits-0.2.19/LICENSE-MIT +25 -0
  501. package/binary/licenses/supplemental/rust-once_cell-1.21.4/LICENSE-APACHE +201 -0
  502. package/binary/licenses/supplemental/rust-once_cell-1.21.4/LICENSE-MIT +23 -0
  503. package/binary/licenses/supplemental/rust-pin-project-lite-0.2.17/LICENSE-APACHE +177 -0
  504. package/binary/licenses/supplemental/rust-pin-project-lite-0.2.17/LICENSE-MIT +23 -0
  505. package/binary/licenses/supplemental/rust-portable-atomic-1.13.1/LICENSE-APACHE +177 -0
  506. package/binary/licenses/supplemental/rust-portable-atomic-1.13.1/LICENSE-MIT +23 -0
  507. package/binary/licenses/supplemental/rust-proc-macro2-1.0.106/LICENSE-APACHE +176 -0
  508. package/binary/licenses/supplemental/rust-proc-macro2-1.0.106/LICENSE-MIT +23 -0
  509. package/binary/licenses/supplemental/rust-pyo3-0.29.0/LICENSE-APACHE +178 -0
  510. package/binary/licenses/supplemental/rust-pyo3-0.29.0/LICENSE-MIT +25 -0
  511. package/binary/licenses/supplemental/rust-pyo3-0.29.0/pyo3-runtime/LICENSE-APACHE +178 -0
  512. package/binary/licenses/supplemental/rust-pyo3-0.29.0/pyo3-runtime/LICENSE-MIT +25 -0
  513. package/binary/licenses/supplemental/rust-pyo3-build-config-0.29.0/LICENSE-APACHE +178 -0
  514. package/binary/licenses/supplemental/rust-pyo3-build-config-0.29.0/LICENSE-MIT +25 -0
  515. package/binary/licenses/supplemental/rust-pyo3-ffi-0.29.0/LICENSE-APACHE +178 -0
  516. package/binary/licenses/supplemental/rust-pyo3-ffi-0.29.0/LICENSE-MIT +25 -0
  517. package/binary/licenses/supplemental/rust-pyo3-file-0.16.0/Cargo.toml +14 -0
  518. package/binary/licenses/supplemental/rust-pyo3-file-0.16.0/README.md +90 -0
  519. package/binary/licenses/supplemental/rust-pyo3-file-0.16.0/declared-license/Apache-2.0.txt +73 -0
  520. package/binary/licenses/supplemental/rust-pyo3-macros-0.29.0/LICENSE-APACHE +178 -0
  521. package/binary/licenses/supplemental/rust-pyo3-macros-0.29.0/LICENSE-MIT +25 -0
  522. package/binary/licenses/supplemental/rust-pyo3-macros-backend-0.29.0/LICENSE-APACHE +178 -0
  523. package/binary/licenses/supplemental/rust-pyo3-macros-backend-0.29.0/LICENSE-MIT +25 -0
  524. package/binary/licenses/supplemental/rust-quick-xml-0.41.0/LICENSE-MIT.md +23 -0
  525. package/binary/licenses/supplemental/rust-quote-1.0.45/LICENSE-APACHE +176 -0
  526. package/binary/licenses/supplemental/rust-quote-1.0.45/LICENSE-MIT +23 -0
  527. package/binary/licenses/supplemental/rust-rustversion-1.0.22/LICENSE-APACHE +176 -0
  528. package/binary/licenses/supplemental/rust-rustversion-1.0.22/LICENSE-MIT +23 -0
  529. package/binary/licenses/supplemental/rust-serde-1.0.228/LICENSE-APACHE +176 -0
  530. package/binary/licenses/supplemental/rust-serde-1.0.228/LICENSE-MIT +23 -0
  531. package/binary/licenses/supplemental/rust-serde_core-1.0.228/LICENSE-APACHE +176 -0
  532. package/binary/licenses/supplemental/rust-serde_core-1.0.228/LICENSE-MIT +23 -0
  533. package/binary/licenses/supplemental/rust-serde_derive-1.0.228/LICENSE-APACHE +176 -0
  534. package/binary/licenses/supplemental/rust-serde_derive-1.0.228/LICENSE-MIT +23 -0
  535. package/binary/licenses/supplemental/rust-shlex-2.0.1/LICENSE-APACHE +13 -0
  536. package/binary/licenses/supplemental/rust-shlex-2.0.1/LICENSE-MIT +21 -0
  537. package/binary/licenses/supplemental/rust-simd-adler32-0.3.9/LICENSE.md +21 -0
  538. package/binary/licenses/supplemental/rust-slab-0.4.12/LICENSE +25 -0
  539. package/binary/licenses/supplemental/rust-syn-2.0.118/LICENSE-APACHE +176 -0
  540. package/binary/licenses/supplemental/rust-syn-2.0.118/LICENSE-MIT +23 -0
  541. package/binary/licenses/supplemental/rust-target-lexicon-0.13.5/LICENSE +220 -0
  542. package/binary/licenses/supplemental/rust-typed-path-0.12.3/LICENSE-APACHE +176 -0
  543. package/binary/licenses/supplemental/rust-typed-path-0.12.3/LICENSE-MIT +23 -0
  544. package/binary/licenses/supplemental/rust-unicode-ident-1.0.24/LICENSE-APACHE +176 -0
  545. package/binary/licenses/supplemental/rust-unicode-ident-1.0.24/LICENSE-MIT +23 -0
  546. package/binary/licenses/supplemental/rust-unicode-ident-1.0.24/LICENSE-UNICODE +39 -0
  547. package/binary/licenses/supplemental/rust-wasm-bindgen-0.2.125/LICENSE-APACHE +201 -0
  548. package/binary/licenses/supplemental/rust-wasm-bindgen-0.2.125/LICENSE-MIT +25 -0
  549. package/binary/licenses/supplemental/rust-wasm-bindgen-macro-0.2.125/LICENSE-APACHE +201 -0
  550. package/binary/licenses/supplemental/rust-wasm-bindgen-macro-0.2.125/LICENSE-MIT +25 -0
  551. package/binary/licenses/supplemental/rust-wasm-bindgen-macro-support-0.2.125/LICENSE-APACHE +201 -0
  552. package/binary/licenses/supplemental/rust-wasm-bindgen-macro-support-0.2.125/LICENSE-MIT +25 -0
  553. package/binary/licenses/supplemental/rust-wasm-bindgen-shared-0.2.125/LICENSE-APACHE +201 -0
  554. package/binary/licenses/supplemental/rust-wasm-bindgen-shared-0.2.125/LICENSE-MIT +25 -0
  555. package/binary/licenses/supplemental/rust-windows-core-0.62.2/license-apache-2.0 +201 -0
  556. package/binary/licenses/supplemental/rust-windows-core-0.62.2/license-mit +21 -0
  557. package/binary/licenses/supplemental/rust-windows-implement-0.60.2/license-apache-2.0 +201 -0
  558. package/binary/licenses/supplemental/rust-windows-implement-0.60.2/license-mit +21 -0
  559. package/binary/licenses/supplemental/rust-windows-interface-0.59.3/license-apache-2.0 +201 -0
  560. package/binary/licenses/supplemental/rust-windows-interface-0.59.3/license-mit +21 -0
  561. package/binary/licenses/supplemental/rust-windows-link-0.2.1/license-apache-2.0 +201 -0
  562. package/binary/licenses/supplemental/rust-windows-link-0.2.1/license-mit +21 -0
  563. package/binary/licenses/supplemental/rust-windows-result-0.4.1/license-apache-2.0 +201 -0
  564. package/binary/licenses/supplemental/rust-windows-result-0.4.1/license-mit +21 -0
  565. package/binary/licenses/supplemental/rust-windows-strings-0.5.1/license-apache-2.0 +201 -0
  566. package/binary/licenses/supplemental/rust-windows-strings-0.5.1/license-mit +21 -0
  567. package/binary/licenses/supplemental/rust-zip-8.6.0/LICENSE +21 -0
  568. package/binary/licenses/supplemental/rust-zlib-rs-0.6.3/LICENSE +19 -0
  569. package/binary/licenses/supplemental/rust-zopfli-0.8.3/COPYING +201 -0
  570. package/binary/licenses/supplemental/selectolax-0.4.13/LICENSE +10 -0
  571. package/binary/licenses/supplemental/selectolax-0.4.13/lexbor/LICENSE +223 -0
  572. package/binary/licenses/supplemental/selectolax-0.4.13/lexbor/NOTICE +16 -0
  573. package/binary/version.json +6 -0
  574. package/native-manifest.json +4474 -0
  575. package/native-verification.json +338 -0
  576. package/package.json +27 -4
@@ -0,0 +1,1139 @@
1
+ Metadata-Version: 2.4
2
+ Name: pypdfium2
3
+ Version: 5.13.0
4
+ Summary: Python bindings to PDFium
5
+ Home-page: https://github.com/pypdfium2-team/pypdfium2
6
+ Author: pypdfium2-team
7
+ Author-email: geisserml@gmail.com
8
+ License: BSD-3-Clause, Apache-2.0, dependency licenses
9
+ Project-URL: Source, https://github.com/pypdfium2-team/pypdfium2
10
+ Project-URL: Tracker, https://github.com/pypdfium2-team/pypdfium2/issues
11
+ Project-URL: Documentation, https://pypdfium2.readthedocs.io
12
+ Project-URL: Changelog, https://pypdfium2.readthedocs.io/en/stable/changelog.html
13
+ Keywords: pdf,pdfium
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Information Technology
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: Implementation :: CPython
20
+ Classifier: Topic :: Multimedia :: Graphics
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Requires-Python: >= 3.6
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSES/Apache-2.0.txt
25
+ License-File: LICENSES/BSD-3-Clause.txt
26
+ License-File: LICENSES/CC-BY-4.0.txt
27
+ License-File: data/linux_x64/BUILD_LICENSES/abseil.txt
28
+ License-File: data/linux_x64/BUILD_LICENSES/agg23.txt
29
+ License-File: data/linux_x64/BUILD_LICENSES/fast_float.txt
30
+ License-File: data/linux_x64/BUILD_LICENSES/freetype.txt
31
+ License-File: data/linux_x64/BUILD_LICENSES/icu.txt
32
+ License-File: data/linux_x64/BUILD_LICENSES/lcms.txt
33
+ License-File: data/linux_x64/BUILD_LICENSES/libjpeg_turbo.ijg
34
+ License-File: data/linux_x64/BUILD_LICENSES/libjpeg_turbo.md
35
+ License-File: data/linux_x64/BUILD_LICENSES/libopenjpeg.txt
36
+ License-File: data/linux_x64/BUILD_LICENSES/libpng.txt
37
+ License-File: data/linux_x64/BUILD_LICENSES/libtiff.txt
38
+ License-File: data/linux_x64/BUILD_LICENSES/llvm-libc.txt
39
+ License-File: data/linux_x64/BUILD_LICENSES/pdfium-binaries.txt
40
+ License-File: data/linux_x64/BUILD_LICENSES/pdfium.txt
41
+ License-File: data/linux_x64/BUILD_LICENSES/simdutf.txt
42
+ License-File: data/linux_x64/BUILD_LICENSES/zlib.txt
43
+ Dynamic: license
44
+ Dynamic: license-file
45
+ Dynamic: requires-python
46
+ Dynamic: summary
47
+
48
+ <!-- SPDX-FileCopyrightText: 2026 geisserml <geisserml@gmail.com> -->
49
+ <!-- SPDX-License-Identifier: CC-BY-4.0 -->
50
+
51
+ # pypdfium2
52
+
53
+ <!-- [![Downloads](https://pepy.tech/badge/pypdfium2/month)](https://pepy.tech/project/pypdfium2) -->
54
+
55
+ pypdfium2 is an ABI-level Python 3 binding to [PDFium](https://pdfium.googlesource.com/pdfium/+/refs/heads/main), a powerful and liberal-licensed library for PDF rendering, inspection, manipulation and creation.
56
+
57
+ It is built with [ctypesgen](https://github.com/pypdfium2-team/ctypesgen) and external [PDFium binaries](https://github.com/bblanchon/pdfium-binaries/).
58
+ The custom setup infrastructure provides a seamless packaging and installation process.
59
+ A wide range of platforms is covered with pre-built packages. Check out our [platform support page](https://pypdfium2-team.github.io/pypdfium2/platforms.html).
60
+
61
+ pypdfium2 includes [helpers](#support-model) to simplify common use cases, while the [raw PDFium API](#raw-pdfium-api) (ctypes) remains accessible as well.
62
+
63
+
64
+ ## Installation
65
+
66
+ ### From PyPI (recommended)
67
+ ```bash
68
+ python -m pip install -U pypdfium2
69
+ ```
70
+ If available for your platform, this will use a pre-built wheel package, which is the easiest way of installing pypdfium2.
71
+ Otherwise, [setup code](#from-the-repository--with-setup) will run.
72
+ If your platform is not covered with pre-built binaries, this will look for system pdfium, or attempt to build pdfium from source.
73
+
74
+ #### JavaScript/XFA builds
75
+
76
+ pdfium-binaries also offer V8 (JavaScript) / XFA enabled builds.
77
+ If you need them, do e.g.:
78
+ ```bash
79
+ PDFIUM_PLATFORM=auto-v8 pip install -v pypdfium2 --no-binary pypdfium2
80
+ ```
81
+ This will bypass wheels and run setup, while requesting use of V8 builds through the `PDFIUM_PLATFORM=auto-v8` environment setting. See below for more info.
82
+
83
+ #### Optional runtime dependencies
84
+
85
+ As of this writing, pypdfium2 does not require any mandatory runtime dependencies, apart from Python and PDFium itself (which is commonly bundled).
86
+
87
+ However, some optional support model / CLI features need additional packages:
88
+ * [`Pillow`](https://pillow.readthedocs.io/en/stable/) (module `PIL`) is a popular imaging library for Python.
89
+ pypdfium2 provides convenience adapters to translate between raw bitmap buffers and PIL images.
90
+ It also uses PIL for some command-line functionality (e.g. image saving).
91
+ * [`NumPy`](https://numpy.org/doc/stable/index.html) is a library for scientific computing.
92
+ As with `Pillow`, pypdfium2 provides helpers to get a numpy array view of a raw bitmap.
93
+ * [`opencv-python`](https://github.com/opencv/opencv-python) (module `cv2`) is an imaging library built around numpy arrays.
94
+ It can be used in the rendering CLI to save with pypdfium2's numpy adapter.
95
+ * If [`tabulate`](https://github.com/astanin/python-tabulate) is installed, the CLI will give prettier output where tables are involved.
96
+
97
+ pypdfium2 tries to defer imports of optional dependencies until they are actually needed, so there should be no startup overhead if you don't use them.
98
+
99
+
100
+ ### From the repository / With setup
101
+
102
+ _Note, unlike helpers, pypdfium2's setup is not bound by API stability promises, so it may change any time._
103
+
104
+ #### Setup Dependencies
105
+
106
+ *System*
107
+ + `gcc` or `clang` as C pre-processor (or set `$CPP` to whatever pre-processor command you want to use)
108
+ + `git` (Used e.g. to determine the latest pdfium-binaries version, to get `git describe` info, or to check out pdfium on sourcebuild. Might be optional on default setup.)
109
+ + [`gh >= 2.47.0`](https://github.com/cli/cli/) (optional; used to verify pdfium-binaries build attestations)
110
+
111
+ *Python*
112
+ + [`ctypesgen` (pypdfium2-team fork)](https://github.com/pypdfium2-team/ctypesgen)
113
+ + `setuptools`
114
+ + `wheel`, if setuptools is `< v70.1.0`
115
+
116
+ Python dependencies should be automatically installed, unless `--no-build-isolation` is passed to pip.
117
+
118
+ > [!NOTE]
119
+ > pypdfium2 and its ctypesgen fork are developed in sync, i.e. each pypdfium2 commit ought to be coupled with the then `HEAD` of pypdfium2-ctypesgen.<br>
120
+ > Our release sdists, and latest pypdfium2 from git, will automatically use matching ctypesgen.<br>
121
+ > However, when using a non-latest commit, you'll have to set up the right ctypesgen version on your own, and install pypdfium2 without build isolation.
122
+
123
+ #### Get the code
124
+
125
+ ```bash
126
+ git clone "https://github.com/pypdfium2-team/pypdfium2.git"
127
+ cd pypdfium2/
128
+ ```
129
+
130
+ #### Default setup
131
+
132
+ ```bash
133
+ # In the pypdfium2/ directory
134
+ python -m pip install -v .
135
+ ```
136
+
137
+ This will invoke pypdfium2's `setup.py`. Typically, this means a binary will be downloaded from `pdfium-binaries` and bundled into pypdfium2, and ctypesgen will be called on pdfium headers to produce the bindings interface.
138
+
139
+ `pdfium-binaries` offer GitHub build provenance [attestations](https://github.com/bblanchon/pdfium-binaries/attestations), so it is highly recommended that you install the `gh` CLI for our setup to verify authenticity of the binaries.
140
+
141
+ If no pre-built binaries are available for your platform, setup will [look for system pdfium](#with-system-pdfium), or attempt to [build pdfium from source](#with-self-built-pdfium).
142
+
143
+ ##### `pip` options of interest
144
+
145
+ - `-v`: Verbose logging output. Useful for debugging.
146
+ - `-e`: Install in editable mode, so the installation points to the source tree. This way, changes directly take effect without needing to re-install. Recommended for development.
147
+ - `--no-build-isolation`: Do not isolate setup in a virtual env; use the main env instead. This renders `pyproject.toml [build-system]` inactive, so setup deps must be prepared by caller. Useful to install custom versions of setup deps, or as speedup when installing repeatedly.
148
+ - `--no-binary pypdfium2`: Do not use binary *wheels* when installing from PyPI – instead, use the sdist and run setup. Note, this option is improperly named, as pypdfium2's setup will attempt to use binaries all the same. If you want to prevent that, set e.g. `PDFIUM_PLATFORM=fallback` to achieve the same behavior as if there were no pdfium-binaries for the host. Or if you just want to package a source distribution, set `PDFIUM_PLATFORM=sdist`.
149
+ - `--pre` to install a beta release, if available.
150
+
151
+
152
+ #### With system pdfium
153
+
154
+ ```bash
155
+ PDFIUM_PLATFORM="system-search" python -m pip install -v .
156
+ ```
157
+
158
+ Look for a system-provided pdfium shared library, and bind against it.
159
+
160
+ Standard, portable [`ctypes.util.find_library()`](https://docs.python.org/3/library/ctypes.html#finding-shared-libraries) means will be used to probe for system pdfium at setup time, and the result will be hardcoded into the bindings. Alternatively, set `$PDFIUM_BINARY` to the path of the out-of-tree DLL to use.
161
+
162
+ Assuming system pdfium was found, we will look for pdfium headers from which to generate the bindings (e.g. in `/usr/include`). If the headers are in a location not recognized by our code, set `$PDFIUM_HEADERS` to the directory in question.
163
+
164
+ Also, we try to determine the pdfium version, either from the library filename itself, or via `pkg-config`.[^full_ver]
165
+ Where this does not work, you can pass the version alongside the setup target, e.g. `PDFIUM_PLATFORM=system-search:XXXX`, where `XXXX` is the pdfium build version.
166
+ If the version is not known in the end, `NaN` placeholders will be set.
167
+
168
+ If the version is known but no headers were found, they will be downloaded from upstream.
169
+ If neither headers nor version are known (or ctypesgen is not installed), the reference bindings will be used as a last resort. This is ABI-unsafe and thus discouraged.
170
+
171
+ In case `find_library()` failed to find pdfium, we *may* do additional, custom search, such as checking for a pdfium shared library included with LibreOffice, and – if available – determining its version.<br>
172
+ Our search heuristics currently expect a Linux-like filesystem hierarchy (e.g. `/usr`), but contributions for other systems are welcome.
173
+
174
+ > [!CAUTION]
175
+ > When pypdfium2 is installed with system pdfium, bindings ought to be re-generated with the new headers whenever the out-of-tree pdfium DLL is updated, for ABI safety reasons.[^upstream_abi_policy]<br>
176
+ > For distributors, we suggest that you use versioned libraries (e.g. `libpdfium.so.140.0.7269.0`) or similar concepts that enforce binary/bindings version match, so outdated bindings will safely stop working with a meaningful error, rather than silently continue unsafely, at risk of hard crashes.
177
+
178
+ [^full_ver]: If this did not reveal the full version, setup will try to resolve it with a git web request. Set `GIVEN_FULLVER=$major.$minor.$build.$patch` or `IGNORE_FULLVER=1` to override that behavior.
179
+
180
+ [^upstream_abi_policy]: Luckily, upstream tend to be careful not to change the ABI of existing stable APIs, but they don't mind ABI-breaking changes to APIs that have not been promoted to stable tier yet, and pypdfium2 uses many of them, so it is still prudent to care about downstream ABI safety as well (it always is). You can read more about upstream's policy [here](https://pdfium.googlesource.com/pdfium/+/refs/heads/main/CONTRIBUTING.md#stability).
181
+
182
+ ##### Related targets
183
+
184
+ There is also a `system-generate:$VERSION` target, to produce system pdfium bindings in a host-independent fashion. This will call `find_library()` at runtime, and may be useful for packaging.
185
+
186
+ Further, you can set just `system` to consume pre-generated files from the `data/system` staging directory. See the section on [caller-provided data files](#with-caller-provided-data-files) for more info.
187
+
188
+
189
+ #### With self-built pdfium
190
+
191
+ You can also install pypdfium2 with a self-compiled pdfium shared library, by placing it in `data/sourcebuild/` along with a bindings interface and version info, and setting the `PDFIUM_PLATFORM="sourcebuild"` directive to use these files on setup.
192
+
193
+ This project comes with two scripts to automate the build process: `build_toolchained.py` and `build_native.py` (in `setupsrc/`).
194
+ - `build_toolchained` is based on the build instructions in pdfium's Readme, and uses Google's toolchain (this means foreign binaries and sysroots). This results in a heavy checkout process that may take a lot of time and space. Dependency libraries are vendored. An advantage of the toolchain is its powerful cross-compilation support (including symbol reversioning).
195
+ - `build_native` is an attempt to address some shortcomings of the toolchained build. It performs a lean, self-managed checkout, and is tailored towards native compilation. It uses system dependencies (compiler/gn/ninja), which must be installed by the caller beforehand. This script should theoretically work on arbitrary Linux architectures. As a drawback, this process is not supported or even documented upstream, so it might be hard to maintain.
196
+
197
+ The native sourcebuild can either use system libraries, or pdfium's vendored libraries.
198
+ When invoked directly, by default, system libraries will be used. However, when invoked through fallback setup, vendored libraries are used instead.
199
+ Use the `--vendor ...` and `--no-vendor ...` options to control vendoring on a per-library basis. See `build_native.py --help` for details.
200
+
201
+ You can also set `PDFIUM_PLATFORM` to `sourcebuild-native` or `sourcebuild-toolchained` to trigger either build script through setup, and pass command-line flags with `$BUILD_PARAMS`.
202
+ However, for simplicity, both scripts/subtargets share just `sourcebuild` as staging directory.
203
+
204
+ Dependencies:
205
+ - When building with system libraries, the following packages need to be installed (including development headers): `freetype, icu-uc, lcms2, libjpeg, libopenjp2, libpng, libtiff, zlib, harfbuzz` (and maybe `glib` to satisfy the build system).
206
+ - You might also want to know that pdfium bundles `agg, abseil, fast_float, simdutf`.
207
+ - When building with system tools, `gn (generate-ninja)`, `ninja`, and a compiler are needed. If available, the compiler defaults to GCC, but Clang should also work if you set up some symlinks, and make sure you have the `libclang_rt` builtins or pass `--no-libclang-rt`.
208
+
209
+ > [!IMPORTANT]
210
+ > PDFium requires recent GN. Outdated GN may fail with the most obscure errors.<br>
211
+ > With `build_native.py`, we recommend that you install [`gn-dist`](https://github.com/pypdfium2-team/gn-dist/) from PyPI, which is also maintained by pypdfium2-team:
212
+ > ```bash
213
+ > python3 -m pip install --group gn
214
+ > ```
215
+ > Using the dependency group from our `pyproject.toml` will ensure you install a GN version appropriate to the PDFium version pinned by pypdfium2's build scripts.
216
+ >
217
+ > GN packages provided by stable distributions are typically too old for PDFium, so we do not recommend installing GN with a system package manager like `apt`.
218
+ >
219
+ > With `build_toolchained.py`, `gclient`-orchestrated checkout should automatically provide you with a GN build from Google's CIPD. If it does not (e.g. because you are on an unhandled platform), also use `gn-dist`. If there are no wheels for your platform, sourcebuild fallback will step in.
220
+
221
+ To do the toolchained build, you'd run something like:
222
+ ```bash
223
+ # call build script with --help to list options
224
+ python ./setupsrc/build_toolchained.py
225
+ PDFIUM_PLATFORM="sourcebuild" python -m pip install -v .
226
+ ```
227
+
228
+ Or for the native build, on Ubuntu 24.04, you could do e.g.:
229
+ ```bash
230
+ # Install dependencies
231
+ python -m pip install --group gn # see above
232
+ sudo apt-get install ninja-build libfreetype-dev liblcms2-dev libjpeg-dev libopenjp2-7-dev libpng-dev libtiff-dev zlib1g-dev libicu-dev libglib2.0-dev libharfbuzz-dev # generate-ninja
233
+ ```
234
+ ```bash
235
+ # Build with GCC
236
+ python ./setupsrc/build_native.py --compiler gcc
237
+ ```
238
+ ```bash
239
+ # Alternatively, build with Clang
240
+ sudo apt-get install llvm lld
241
+ VERSION=18
242
+ ARCH=$(uname -m)
243
+ sudo ln -s "/usr/lib/clang/$VERSION/lib/linux" "/usr/lib/clang/$VERSION/lib/$ARCH-unknown-linux-gnu"
244
+ sudo ln -s "/usr/lib/clang/$VERSION/lib/linux/libclang_rt.builtins-$ARCH.a" "/usr/lib/clang/$VERSION/lib/linux/libclang_rt.builtins.a"
245
+ python ./setupsrc/build_native.py --compiler clang
246
+ ```
247
+ ```bash
248
+ # Install
249
+ PDFIUM_PLATFORM="sourcebuild" python -m pip install -v .
250
+ ```
251
+
252
+ The native sourcebuild currently supports Linux (or similar environments).
253
+ macOS and Windows are not handled, as we do not have access to these systems, and working over CI did not turn out feasible – use the toolchain-based build for now.
254
+ Community help / pull requests to extend platform support would be welcome.
255
+
256
+
257
+ #### cibuildwheel
258
+
259
+ Sourcebuild can be run through cibuildwheel. For targets configured in our [`pyproject.toml`](./pyproject.toml), the basic invocation is as simple as p.ex.
260
+ ```bash
261
+ CIBW_BUILD="cp314-manylinux_x86_64" cibuildwheel
262
+ ```
263
+ A more involved use case could look like this:
264
+ ```bash
265
+ CIBW_BUILD="cp314-musllinux_s390x" CIBW_ARCHS=s390x CIBW_CONTAINER_ENGINE=podman TEST_PDFIUM=1 cibuildwheel
266
+ ```
267
+ See also our [cibuildwheel workflow](.github/workflows/cibw_one.yaml).
268
+ For more options, consult the comprehensive [upstream documentation](https://cibuildwheel.pypa.io/en/stable/options).
269
+
270
+ On Linux, this will use the native sourcebuild with vendored dependency libraries.
271
+ On Windows and macOS, the toolchained sourcebuild is used.
272
+
273
+ Bear in mind that cibuildwheel copies the project directory into a container, not taking `.gitignore` rules into account.
274
+ Thus, it is advisable to make a fresh checkout of pypdfium2 before running cibuildwheel.
275
+ In particular, a toolchained checkout of pdfium within pypdfium2 is problematic, and will cause a halt on the `Copying project into container...` step.
276
+ For development, make sure the fresh checkout is in sync with the working copy.
277
+
278
+ Concerning Linux, cibuildwheel requires either Docker or Podman.
279
+ On the author's version of Fedora, Docker can be installed as follows:
280
+ ```bash
281
+ sudo dnf in moby-engine # this provides the docker command
282
+ sudo systemctl start docker
283
+ sudo systemctl enable docker
284
+ sudo usermod -aG docker $USER
285
+ # then reboot (re-login might also suffice)
286
+ ```
287
+ For other ways of installing Docker, refer to the cibuildwheel docs ([Setup](https://cibuildwheel.pypa.io/en/stable/setup/), [Platforms](https://cibuildwheel.pypa.io/en/stable/platforms/)) and the links therein.
288
+
289
+ <!-- TODO this tip might be a better fit in the build section above, which does not point out cross-compilation yet -->
290
+
291
+ > [!TIP]
292
+ > Note that pdfium itself has first-class cross-compilation support.
293
+ > For platforms covered upstream, we tend to sidestep cibuildwheel and cross-compile pdfium using its own toolchain instead, e.g.:
294
+ > ```bash
295
+ > # assuming cross-compilation dependencies are installed
296
+ > python setupsrc/build_toolchained.py --target-cpu arm
297
+ > PDFIUM_PLATFORM=sourcebuild CROSS_TAG="manylinux_2_17_armv7l" python -m build -wxn
298
+ > ```
299
+ > This typically achieves a lower glibc requirement than we can with cibuildwheel, and is especially useful for platforms that are not available natively on CI.
300
+
301
+
302
+ #### With caller-provided data files
303
+
304
+ pypdfium2 is like any other Python project in essentials, except that it needs some data files: a pdfium DLL (either bundled or out-of-tree), a bindings interface (generated via ctypesgen), and pdfium version info (JSON).
305
+
306
+ The main point of pypdfium2's custom setup is to automate deployment of these files, in a way that suits end users/contributors as well as our PyPI packaging.
307
+
308
+ However, if you want to (or have to) forego this automation, you can also *just supply these files yourself*, as shown below. This allows to largely sidestep pypdfium2's own setup code.<br>
309
+ The idea is basically to put your data files in a staging directory, `data/sourcebuild` or `data/system` (depending on whether you want to bundle or use system pdfium), and set the matching `$PDFIUM_PLATFORM` target to consume from that directory on setup.
310
+
311
+ This setup strategy should be inherently free of web requests.
312
+ Please don't expect us to support the result, though. If you bring your own files, that's your own responsibility, and it is quite possible your version of pypdfium2 may turn out subtly different than ours.
313
+
314
+ ```bash
315
+ # First, ask yourself: Do you want to bundle pdfium (in-tree), or use system
316
+ # pdfium (out-of-tree)? For bundling, set "sourcebuild", else set "system".
317
+ TARGET="sourcebuild" # or "system"
318
+ STAGING_DIR="data/$TARGET"
319
+
320
+ # If you have decided for bundling, copy over the pdfium DLL in question.
321
+ # Otherwise, skip this step.
322
+ cp "$MY_BINARY_PATH" "$STAGING_DIR/libpdfium.so"
323
+
324
+ # Now, we will call ctypesgen to generate the bindings interface.
325
+ # Reminder: You'll want to use the pypdfium2-team fork of ctypesgen.
326
+ # It generates much cleaner bindings, and it's what our source expects
327
+ # (there may be subtle API differences in terms of output).
328
+ # How exactly you do this is down to you.
329
+ # See ctypesgen --help or base.py::run_ctypesgen() for further options.
330
+ ctypesgen --library pdfium --rt-libpaths $MY_RT_LIBPATHS --ct-libpaths $MY_CT_LIBPATHS \
331
+ --headers $MY_INCLUDE_DIR/fpdf*.h -o $STAGING_DIR/bindings.py [-D $MY_RAW_FLAGS]
332
+
333
+ # Then write the version file (fill the placeholders).
334
+ # Note, this is not a mature interface yet and might change any time!
335
+ # See also https://pypdfium2.readthedocs.io/en/stable/python_api.html#pypdfium2.version.PDFIUM_INFO
336
+ # major/minor/build/patch: integers forming the pdfium version being packaged
337
+ # n_commits/hash: git describe like post-tag info (0/null for release commit)
338
+ # origin: a string to identify the build
339
+ # flags: a comma-delimited list of pdfium feature flag strings
340
+ # (e.g. "V8", "XFA") - may be empty for default build
341
+ cat > "$STAGING_DIR/version.json" <<END
342
+ {
343
+ "major": $PDFIUM_MAJOR,
344
+ "minor": $PDFIUM_MINOR,
345
+ "build": $PDFIUM_BUILD,
346
+ "patch": $PDFIUM_PATCH,
347
+ "n_commits": $POST_TAG_COMMIT_COUNT,
348
+ "hash": $POST_TAG_HASH,
349
+ "origin": "$TARGET-$MY_ORIGIN",
350
+ "flags": [$MY_SHORT_FLAGS]
351
+ }
352
+ END
353
+
354
+ # Finally, run setup (through pip, pyproject-build or whatever).
355
+ # The PDFIUM_PLATFORM value will instruct pypdfium2's setup to use the files
356
+ # we supplied, rather than to generate its own.
357
+ PDFIUM_PLATFORM=$TARGET python -m pip install --no-build-isolation -v .
358
+ ```
359
+
360
+
361
+ #### Further setup info (formal summary)
362
+
363
+ This is a somewhat formal description of pypdfium2's setup capabilities.
364
+ It is meant to sum up and complement the above documentation on specific sub-targets.
365
+
366
+ As it is hard to keep up with constantly evolving setup code, it is possible this documentation may be outdated/incomplete. Also keep in mind that these APIs could change any time, and are mainly of internal interest.
367
+
368
+ * Binaries are stored in platform-specific sub-directories of `data/`, along with bindings and version information.
369
+
370
+ * `$PDFIUM_PLATFORM` defines which binary to include on setup.
371
+ - Format spec: `[$PLATFORM][-v8][:$VERSION]` (`[]` = segments, `$CAPS` = variables).
372
+ - Examples: `auto`, `auto:7269` `auto-v8:7269` (`auto` may be substituted by an explicit platform name, e.g. `linux_x64`).
373
+ - V8: If given, use the V8 (JavaScript) and XFA enabled pdfium binaries. Otherwise, use the regular (non-V8) binaries.
374
+ - Version: If given, use the specified pdfium-binaries release. Otherwise, use the default version currently set in the codebase. Set `pinned` to request that behavior explicitly. Or set `latest` to use the newest pdfium-binaries release instead.
375
+ - Platform:
376
+ + If unset or `auto`, the host platform is detected and a corresponding binary will be selected.
377
+ + If an explicit platform identifier (e.g. `linux_x64`, `darwin_arm64`, ...), binaries for the requested platform will be used.[^platform_ids]
378
+ + If `system-search`, look for and bind against system-provided pdfium instead of embedding a binary. If just `system`, consume existing bindings from `data/system/`.
379
+ + If `sourcebuild`, binary and bindings will be taken from `data/sourcebuild/`, assuming a prior run of the native or toolchained build scripts. `sourcebuild-native` or `sourcebuild-toolchained` can also be used to trigger either build through setup (use `$BUILD_PARAMS` to pass custom options).
380
+ + If `sdist`, no platform-specific files will be included, so as to create a source distribution.
381
+
382
+ * `$PYPDFIUM_MODULES=[raw,helpers]` defines the modules to include. Metadata adapts dynamically.
383
+ - May be used by packagers to decouple raw bindings and helpers, which may be relevant if packaging against system pdfium.
384
+ - Would also allow to install only the raw module without helpers, or only helpers with a custom raw module.
385
+ - Be careful, `PYPDFIUM_MODULES=raw` requires a pre-generated version file to infer the package version.
386
+
387
+ * `$PDFIUM_BINDINGS=reference` allows to override ctypesgen and use the reference bindings file `autorelease/bindings.py` instead.
388
+ - This is a convenience option to get pypdfium2 installed from source even if a working ctypesgen / C pre-processor is not available in the install env. *May be automatically enabled under given circumstances.*
389
+ - Warning: This may not be ABI-safe. Please make sure binary/bindings build headers match to avoid ABI issues.
390
+
391
+ [^platform_ids]: Intended for packaging, so that wheels can be crafted for any platform without access to a native host.
392
+
393
+
394
+ ### From Conda
395
+
396
+ > [!WARNING]
397
+ > **Beware:** Any conda packages/recipes of pypdfium2 or pdfium-binaries that might be provided by other distributors, including `anaconda/main` or `conda-forge` default channels, are [unofficial](#unofficial-packages).
398
+
399
+ > [!NOTE]
400
+ > **Wait a moment:** Do you really need this?
401
+ > pypdfium2 is best installed from `PyPI` (e.g. via `pip`),[^pypi_reasons] which you can also do in a conda env. Rather than asking your users to add custom channels, consider making pypdfium2 optional at install time, and ask them to install it via pip instead.<br>
402
+ > This library has no hard runtime dependencies, so you don't need to worry about breaking the conda env.
403
+ >
404
+ > As of mid 2026, conda finally seems to get better integration with the PyPI world thanks to the [`conda‑pypi`](https://conda.github.io/conda-pypi/) bridge, so we might eventually want to deprecate pypdfium2's conda packaging.
405
+
406
+ [^pypi_reasons]: To name some reasons:
407
+ + pypdfium2 from PyPI covers platforms that we cannot cover on conda.
408
+ + pypdfium2 from PyPI has extensive fallback setup, while conda does not provide an opportunity to run custom setup code.
409
+ + With conda, in-project publishing / custom channels are second class.
410
+ + With conda, it seems there is no way to create platform-specific but interpreter-independent python packages, so we cannot reasonably bundle pdfium. Thus, we have to use external pdfium, which is more complex and has some pitfalls.
411
+
412
+ + To install
413
+
414
+ With permanent channel config (encouraged):
415
+ ```bash
416
+ conda config --add channels bblanchon
417
+ conda config --add channels pypdfium2-team
418
+ conda config --set channel_priority strict
419
+ conda install pypdfium2-team::pypdfium2_helpers
420
+ ```
421
+
422
+ Alternatively, with temporary channel config:
423
+ ```bash
424
+ conda install pypdfium2-team::pypdfium2_helpers --override-channels -c pypdfium2-team -c bblanchon -c defaults
425
+ ```
426
+
427
+ If desired, you may limit the channel config to the current environment by adding `--env`.
428
+ Adding the channels permanently and tightening priority is encouraged to include pypdfium2 in `conda update` by default, and to avoid accidentally replacing the install with a different channel.
429
+ Otherwise, you should be cautious when making changes to the environment.
430
+
431
+ + To depend on pypdfium2 in a `conda-build` recipe
432
+ ```yaml
433
+ requirements:
434
+ run:
435
+ - pypdfium2-team::pypdfium2_helpers
436
+ ```
437
+ You'll want to have downstream callers handle the custom channels as shown above, otherwise conda will not be able to satisfy requirements.
438
+
439
+ + To set up channels in a GH workflow
440
+ ```yaml
441
+ - name: ...
442
+ uses: conda-incubator/setup-miniconda@v4 # or pin to hash
443
+ with:
444
+ # ... your options
445
+ channels: pypdfium2-team,bblanchon
446
+ channel-priority: strict
447
+ ```
448
+ This is just a suggestion, you can also call `conda config` manually, or pass channels on command basis using `-c`, as discussed above.
449
+
450
+ + To verify the sources
451
+ ```bash
452
+ conda list --show-channel-urls "pypdfium2|pdfium-binaries"
453
+ conda config --show-sources
454
+ ```
455
+ The table should show `pypdfium2-team` and `bblanchon` in the channels column.
456
+ If added permanently, the config should also include these channels, ideally with top priority.
457
+ Please check this before reporting any issue with a conda install of pypdfium2.
458
+
459
+ _**Note:** Conda packages are normally managed using recipe feedstocks driven by third parties, in a Linux repository like fashion. However, with some quirks it is also possible to do conda packaging within the original project and publish to a custom channel, which is what pypdfium2-team does, and the above instructions are referring to._
460
+
461
+
462
+ ### Unofficial packages
463
+
464
+ The authors of this project have no control over and are not responsible for possible third-party builds of pypdfium2, and we do not support them. Please use our official packages where possible.
465
+ If you have an issue with a third-party build, either contact your distributor, or try to reproduce with our official builds.
466
+
467
+ Do not expect us to add/change code for downstream-specific setup tasks.
468
+ Related issues or PRs may be closed without further notice if we don't see fit for upstream.
469
+ Enhancements of general value that are maintainable and align well with the idea of our setup code are welcome, though.
470
+
471
+ > [!IMPORTANT]
472
+ > If you are a third-party distributor, please point out in the description that your package is unofficial, i.e. not affiliated with or endorsed by the pypdfium2 authors.<br>
473
+ > In particular, if you feel like you need patches to package pypdfium2, please submit them on the Discussions page so we can figure out if there isn't a better way (there usually is).
474
+
475
+
476
+ ## Usage
477
+
478
+ ### [Support model](https://pypdfium2.readthedocs.io/en/stable/python_api.html)
479
+
480
+ <!-- TODO demonstrate more APIs (e. g. XObject placement, transform matrices, image extraction, ...) -->
481
+
482
+ Here are some examples of using the support model API.
483
+
484
+ * Import the library
485
+ ```python
486
+ import pypdfium2 as pdfium
487
+ import pypdfium2.raw as pdfium_c
488
+ ```
489
+
490
+ * Open a PDF using the helper class `PdfDocument` (supports file paths as string or `pathlib.Path`, or file content as bytes or byte stream)
491
+ ```python
492
+ pdf = pdfium.PdfDocument("./path/to/document.pdf")
493
+ version = pdf.get_version() # get the PDF standard version
494
+ n_pages = len(pdf) # get the number of pages in the document
495
+ page = pdf[0] # load a page
496
+ ```
497
+
498
+ * Render the page
499
+ ```python
500
+ bitmap = page.render(
501
+ scale = 1, # 72dpi resolution
502
+ rotation = 0, # no additional rotation
503
+ # ... further rendering options
504
+ )
505
+ pil_image = bitmap.to_pil()
506
+ pil_image.show()
507
+ ```
508
+
509
+ Note, with the PIL adapter, it might be advantageous to use `force_bitmap_format=pdfium_c.FPDFBitmap_BGRA, rev_byteorder=True` or perhaps `prefer_bgrx=True, maybe_alpha=True, rev_byteorder=True`, to achieve a pixel format supported natively by PIL, and avoid rendering with transparency to a non-alpha bitmap, which can slow down pdfium.
510
+
511
+ With `.to_numpy()`, all formats are zero-copy, but passing either `maybe_alpha=True` (if dynamic pixel format is acceptable) or `force_bitmap_format=pdfium_c.FPDFBitmap_BGRA` is also recommended for the transparency problem.
512
+
513
+ * Try some page methods
514
+ ```python
515
+ # Get page dimensions in PDF canvas units (1pt->1/72in by default)
516
+ width, height = page.get_size()
517
+ # Set the absolute page rotation to 90° clockwise
518
+ page.set_rotation(90)
519
+
520
+ # Locate objects on the page
521
+ for obj in page.get_objects():
522
+ print(obj.level, obj.type, obj.get_bounds())
523
+ ```
524
+
525
+ * Extract and search text
526
+ ```python
527
+ # Load a text page helper
528
+ textpage = page.get_textpage()
529
+
530
+ # Extract text from the whole page
531
+ text_all = textpage.get_text_bounded()
532
+ # Extract text from a specific rectangular area
533
+ text_rect = textpage.get_text_bounded(left=50, bottom=100, right=width-50, top=height-100)
534
+ # Extract text from a specific char range
535
+ text_span = textpage.get_text_range(index=10, count=15)
536
+
537
+ # Locate text on the page
538
+ searcher = textpage.search("something", match_case=False, match_whole_word=False)
539
+ # This returns the next occurrence as (char_index, char_count), or None if not found
540
+ match = searcher.get_next()
541
+ ```
542
+
543
+ * Read the table of contents
544
+ ```python
545
+ import pypdfium2.internal as pdfium_i
546
+
547
+ for bm in pdf.get_toc(max_depth=15):
548
+ count, dest = bm.get_count(), bm.get_dest()
549
+ out = " " * bm.level
550
+ out += "[%s] %s -> " % (
551
+ f"{count:+}" if count != 0 else "*",
552
+ bm.get_title(),
553
+ )
554
+ if dest:
555
+ index, (view_mode, view_pos) = dest.get_index(), dest.get_view()
556
+ out += "%s # %s %s" % (
557
+ index+1 if index != None else "?",
558
+ pdfium_i.ViewmodeToStr.get(view_mode),
559
+ round(view_pos, 3),
560
+ )
561
+ else:
562
+ out += "_"
563
+ print(out)
564
+ ```
565
+
566
+ * Create a new PDF with an empty A4 sized page
567
+ ```python
568
+ pdf = pdfium.PdfDocument.new()
569
+ width, height = (595, 842)
570
+ page_a = pdf.new_page(width, height)
571
+ ```
572
+
573
+ * Include a JPEG image in a PDF
574
+ ```python
575
+ pdf = pdfium.PdfDocument.new()
576
+
577
+ image = pdfium.PdfImage.new(pdf)
578
+ image.load_jpeg("./tests/resources/mona_lisa.jpg")
579
+ width, height = image.get_px_size()
580
+
581
+ matrix = pdfium.PdfMatrix().scale(width, height)
582
+ image.set_matrix(matrix)
583
+
584
+ page = pdf.new_page(width, height)
585
+ page.insert_obj(image)
586
+ page.gen_content()
587
+ ```
588
+
589
+ * Save the document
590
+ ```python
591
+ # PDF 1.7 standard
592
+ pdf.save("output.pdf", version=17)
593
+ ```
594
+
595
+ ### Raw PDFium API
596
+
597
+ While helper classes conveniently wrap the raw PDFium API, it may still be accessed directly and is available in the namespace `pypdfium2.raw`. Lower-level utilities that may aid with using the raw API are provided in `pypdfium2.internal`.
598
+
599
+ ```python
600
+ import pypdfium2.raw as pdfium_c
601
+ import pypdfium2.internal as pdfium_i
602
+ ```
603
+
604
+ Since PDFium is a large library, many components are not covered by helpers yet. However, as helpers expose their underlying raw objects, you may seamlessly integrate raw APIs while using helpers as available. When passed as ctypes function parameter, helpers automatically resolve to the raw object handle (but you may still access it explicitly if desired):
605
+ ```python
606
+ permission_flags = pdfium_c.FPDF_GetDocPermission(pdf.raw) # explicit
607
+ permission_flags = pdfium_c.FPDF_GetDocPermission(pdf) # implicit
608
+ ```
609
+
610
+ For PDFium docs, please look at the comments in its [public header files](https://pdfium.googlesource.com/pdfium/+/refs/heads/main/public/).[^pdfium_docs]
611
+ A variety of examples on how to interface with the raw API using [`ctypes`](https://docs.python.org/3/library/ctypes.html) is already provided with [support model source code](src/pypdfium2/_helpers).
612
+ Nonetheless, the following guide may be helpful to get started with the raw API, if you are not familiar with `ctypes` yet.
613
+
614
+ [^pdfium_docs]: Unfortunately, no recent HTML-rendered docs are available for PDFium at the moment.
615
+
616
+ <!-- TODO write something about weakref.finalize(); add example on creating a C page array -->
617
+ <!-- TODO doctests? -->
618
+
619
+ * In general, PDFium functions can be called just like normal Python functions.
620
+ However, parameters may only be passed positionally, i.e. it is not possible to use keyword arguments.
621
+ There are no defaults, so you always need to provide a value for each argument.
622
+ ```python
623
+ # arguments: filepath (bytes), password (bytes|None)
624
+ # NUL-terminate filepath and encode as UTF-8
625
+ pdf = pdfium_c.FPDF_LoadDocument((filepath+"\x00").encode("utf-8"), None)
626
+ ```
627
+ This is the underlying bindings declaration,[^bindings_decl] which loads the function from the binary and
628
+ contains the information required to convert Python types to their C equivalents.
629
+ ```python
630
+ if hasattr(_libs['pdfium'], 'FPDF_LoadDocument'):
631
+ FPDF_LoadDocument = _libs['pdfium']['FPDF_LoadDocument']
632
+ FPDF_LoadDocument.argtypes = (FPDF_STRING, FPDF_BYTESTRING)
633
+ FPDF_LoadDocument.restype = FPDF_DOCUMENT
634
+ ```
635
+ Python `bytes` are converted to `FPDF_STRING` by ctypes autoconversion. This works because `FPDF_STRING` is actually an alias to `POINTER(c_char)` (i.e. `char*`), which is a primitive pointer type.
636
+ When passing a string to a C function, it must always be NUL-terminated, as the function merely receives a pointer to the first item and then continues to read memory until it finds a NUL terminator.
637
+
638
+ [^bindings_decl]: From the auto-generated bindings file. We maintain a reference copy at `autorelease/bindings.py`. Or if you have an editable install, there will also be `src/pypdfium2_raw/bindings.py`.
639
+
640
+ * First of all, function parameters are not only used for input, but also for output:
641
+ ```python
642
+ # Initialise an integer object (defaults to 0)
643
+ c_version = ctypes.c_int()
644
+ # Let the function assign a value to the c_int object, and capture its return code (True for success, False for failure)
645
+ ok = pdfium_c.FPDF_GetFileVersion(pdf, c_version)
646
+ # If successful, get the Python int by accessing the `value` attribute of the c_int object
647
+ # Otherwise, set the variable to None (in other cases, it may be desired to raise an exception instead)
648
+ version = c_version.value if ok else None
649
+ ```
650
+
651
+ * If an array is required as output parameter, you can initialise one like this (in general terms):
652
+ ```python
653
+ # long form
654
+ array_type = (c_type * array_length)
655
+ array_object = array_type()
656
+ # short form
657
+ array_object = (c_type * array_length)()
658
+ ```
659
+ Example: Getting view mode and target position from a destination object returned by some other function.
660
+ ```python
661
+ # (Assuming `dest` is an FPDF_DEST)
662
+ n_params = ctypes.c_ulong()
663
+ # Create a C array to store up to four coordinates
664
+ view_pos = (pdfium_c.FS_FLOAT * 4)()
665
+ view_mode = pdfium_c.FPDFDest_GetView(dest, n_params, view_pos)
666
+ # Slice the array to the actual number of coordinates. This implicitly converts the C array to a Python list.
667
+ view_pos = view_pos[:n_params.value]
668
+ ```
669
+
670
+ * For string output parameters, callers needs to provide a sufficiently long, pre-allocated buffer.
671
+ This may work differently depending on what type the function requires, which encoding is used, whether the number of bytes or units is returned, and whether space for a NUL terminator is included or not. Carefully review the documentation of the function in question to fulfill its requirements.
672
+
673
+ There are many different ways of handling output strings; this section describes the strategy used by pypdfium2's helpers.
674
+
675
+ We will first import the `codecs.decode()` function which can be used on generic memory (whereas the `.decode()` method is only available on bytes or bytearrays):
676
+ ```python
677
+ from codecs import decode
678
+ ```
679
+
680
+ Example A: Getting the title string of a bookmark.
681
+ ```python
682
+ # (Assuming `bookmark` is an FPDF_BOOKMARK)
683
+ # First call to get the required number of bytes (not units!), including space for a NUL terminator
684
+ n_bytes = pdfium_c.FPDFBookmark_GetTitle(bookmark, None, 0)
685
+ # Initialise the output buffer
686
+ buffer = ctypes.create_string_buffer(n_bytes)
687
+ # Second call with the actual buffer
688
+ pdfium_c.FPDFBookmark_GetTitle(bookmark, buffer, n_bytes)
689
+ # Decode to string, cutting off the NUL terminator (encoding: UTF-16LE)
690
+ title = decode(memoryview(buffer)[:n_bytes-2], "utf-16-le")
691
+ ```
692
+
693
+ Example B: Extracting text in given boundaries.
694
+ ```python
695
+ # (Assuming `textpage` is an FPDF_TEXTPAGE and the boundary variables are set)
696
+ # Store common arguments for the two calls
697
+ args = (textpage, left, top, right, bottom)
698
+ # First call to get the required number of units (not bytes!).
699
+ # A possible NUL terminator is not included.
700
+ n_units = pdfium_c.FPDFText_GetBoundedText(*args, None, 0)
701
+ # If no characters were found, return an empty string
702
+ if n_units <= 0:
703
+ return ""
704
+ # Create the buffer. This particular API does not insist on space for a NUL terminator.
705
+ # Skip so we don't need to cut it off later.
706
+ buffer = (ctypes.c_ushort * n_units)()
707
+ # Second call with the actual buffer
708
+ pdfium_c.FPDFText_GetBoundedText(*args, buffer, n_units)
709
+ # Decode to string (You may want to pass errors="ignore" to skip possible errors in the PDF's encoding)
710
+ text = decode(buffer, "utf-16-le")
711
+ ```
712
+
713
+ There are also APIs that return the number of bytes but expect a multi-byte type, e.g. `FPDF_WCHAR`.
714
+ In that case, you can calculate the number of units via `-(n_bytes // -ctypes.sizeof(pdfium_c.FPDF_WCHAR))` (this does a ceil division).
715
+ <!-- TODO add actual example -->
716
+
717
+ * Not only are there different ways of string output that need to be handled according to the requirements of the function in question.
718
+ String input, too, can work differently depending on encoding and type.
719
+ We have already discussed `FPDF_LoadDocument()`, which takes a UTF-8 encoded string as `char*`.
720
+ A different examples is `FPDFText_FindStart()`, which needs a UTF-16LE encoded string, given as `unsigned short*`:
721
+ ```python
722
+ # (Assuming `text` is a str and `textpage` an FPDF_TEXTPAGE)
723
+ # Add the NUL terminator and encode as UTF-16LE
724
+ enc_text = (text + "\x00").encode("utf-16-le")
725
+ # cast `enc_text` to a c_ushort pointer
726
+ text_ptr = ctypes.cast(enc_text, ctypes.POINTER(ctypes.c_ushort))
727
+ search = pdfium_c.FPDFText_FindStart(textpage, text_ptr, 0, 0)
728
+ ```
729
+
730
+ * Leaving strings, let's suppose you have a C memory buffer allocated by PDFium and wish to read its data.
731
+ PDFium will provide you with a pointer to the first item of the byte array.
732
+ To access the data, you'll want to re-interpret the pointer as an array view with `.from_address()`:
733
+ ```python
734
+ # (Assuming `bitmap` is an FPDF_BITMAP and `size` is the expected number of bytes in the buffer)
735
+ # FPDFBitmap_GetBuffer() has c_void_p as restype, which ctypes will auto-resolve to int or None
736
+ buffer_ptrval = pdfium_c.FPDFBitmap_GetBuffer(bitmap)
737
+ assert buffer_ptrval # make sure it's non-null
738
+ # Get an actual pointer object so we can access .contents
739
+ buffer_ptr = ctypes.cast(buffer_ptrval, ctypes.POINTER(ctypes.c_ubyte))
740
+ # Buffer as ctypes array (a view of the original buffer, will be unavailable as soon as the bitmap is destroyed)
741
+ c_buffer = (ctypes.c_ubyte * size).from_address( ctypes.addressof(buffer_ptr.contents) )
742
+ # Buffer as Python bytes (independent copy)
743
+ py_buffer = bytes(c_buffer)
744
+ ```
745
+ Note that you can achieve the same result with `ctypes.cast(ptr, POINTER(type * size)).contents`, but this is somewhat problematic since ctypes used to cache pointer types eternally with Python < 3.14 (as `size` may vary, this can lead to memory leak like scenarios with long-running applications).
746
+
747
+ * Writing data from Python into a C buffer works in a similar fashion:
748
+ ```python
749
+ # (Assuming `buffer_ptr` is a pointer to the first item of a C buffer to write into,
750
+ # `size` the number of bytes it can store, and `py_buffer` a Python byte buffer)
751
+ buffer = (ctypes.c_ubyte * size).from_address( ctypes.addressof(buffer_ptr.contents) )
752
+ # Read from the Python buffer, starting at its current position, directly into the C buffer
753
+ # (until the target is full or the end of the source is reached)
754
+ n_bytes = py_buffer.readinto(buffer) # returns the number of bytes read
755
+ ```
756
+
757
+ * If you wish to check whether two objects returned by PDFium are the same, the `is` operator won't help because `ctypes` does not have original object return (OOR), i.e. new, equivalent Python objects are created each time, although they might represent one and the same C object.[^ctypes_no_oor]
758
+ That's why you'll want to use `ctypes.addressof()` to get the memory addresses of the underlying C object.
759
+ For instance, this is used to avoid infinite loops on circular bookmark references when iterating through the document outline:
760
+ ```python
761
+ # (Assuming `pdf` is an FPDF_DOCUMENT)
762
+ seen = set()
763
+ bookmark = pdfium_c.FPDFBookmark_GetFirstChild(pdf, None)
764
+ while bookmark:
765
+ # bookmark is a pointer, so we need to use its `contents` attribute to get the object the pointer refers to
766
+ # (otherwise we'd only get the memory address of the pointer itself, which would result in random behaviour)
767
+ address = ctypes.addressof(bookmark.contents)
768
+ if address in seen:
769
+ break # circular reference detected
770
+ else:
771
+ seen.add(address)
772
+ bookmark = pdfium_c.FPDFBookmark_GetNextSibling(pdf, bookmark)
773
+ ```
774
+
775
+ [^ctypes_no_oor]: Confer the [ctypes documentation on Pointers](https://docs.python.org/3/library/ctypes.html#pointers).
776
+
777
+ * In many situations, callback functions come in handy.[^callback_usecases] Thanks to `ctypes`, it is seamlessly possible to use callbacks across Python/C language boundaries.
778
+
779
+ [^callback_usecases]: e. g. incremental read/write, management of progressive tasks, ...
780
+
781
+ Example: Loading a document from a Python buffer. This way, file access can be controlled in Python while the data does not need to be in memory at once.
782
+ ```python
783
+ import os
784
+
785
+ # Factory class to create callable objects holding a reference to a Python buffer
786
+ class _reader_class:
787
+
788
+ def __init__(self, py_buffer):
789
+ self.py_buffer = py_buffer
790
+
791
+ def __call__(self, _, position, buffer_ptr, size):
792
+ # Write data from Python buffer into C buffer, as explained before
793
+ c_buffer = (ctypes.c_ubyte * size).from_address( ctypes.addressof(buffer_ptr.contents) )
794
+ self.py_buffer.seek(position)
795
+ self.py_buffer.readinto(c_buffer)
796
+ return 1 # non-zero return code for success
797
+
798
+ # (Assuming py_buffer is a Python file buffer, e. g. io.BufferedReader)
799
+ # Get the length of the buffer
800
+ py_buffer.seek(0, os.SEEK_END)
801
+ file_len = py_buffer.tell()
802
+ py_buffer.seek(0)
803
+
804
+ # Set up an interface structure for custom file access
805
+ fileaccess = pdfium_c.FPDF_FILEACCESS()
806
+ fileaccess.m_FileLen = file_len
807
+
808
+ # Assign the callback, wrapped in its CFUNCTYPE
809
+ fileaccess.m_GetBlock = type(fileaccess.m_GetBlock)( _reader_class(py_buffer) )
810
+
811
+ # Finally, load the document
812
+ pdf = pdfium_c.FPDF_LoadCustomDocument(fileaccess, None)
813
+ ```
814
+
815
+ <!-- TODO mention pdfium_i.get_bufreader() as a shortcut to set up an FPDF_FILEACCESS interface -->
816
+ <!-- FIXME The data holder strategy shown below is wonky. Should use Py_IncRef() / Py_DecRef() C APIs instead. -->
817
+
818
+ * When using the raw API, special care needs to be taken regarding object lifetime, considering that Python may garbage collect objects as soon as their reference count reaches zero. However, the interpreter has no way of magically knowing how long the underlying resources of a Python object might still be needed on the C side, so measures need to be taken to keep such objects referenced until PDFium does not depend on them anymore.
819
+
820
+ If resources need to remain valid after the time of a function call, PDFium docs usually indicate this clearly. Ignoring requirements on object lifetime will lead to memory corruption (commonly resulting in a segfault sooner or later).
821
+
822
+ For instance, the docs on `FPDF_LoadCustomDocument()` state that
823
+ > The application must keep the file resources |pFileAccess| points to valid until the returned FPDF_DOCUMENT is closed. |pFileAccess| itself does not need to outlive the FPDF_DOCUMENT.
824
+
825
+ This means that the callback function and the Python buffer need to be kept alive as long as the `FPDF_DOCUMENT` is used.
826
+ This can be achieved by referencing these objects in an accompanying class, e. g.
827
+
828
+ ```python
829
+ class PdfDataHolder:
830
+
831
+ def __init__(self, buffer, function):
832
+ self.buffer = buffer
833
+ self.function = function
834
+
835
+ def close(self):
836
+ # Make sure both objects remain available until this function is called
837
+ # No-op id() call to denote that the object needs to stay in memory up to this point
838
+ id(self.function)
839
+ self.buffer.close()
840
+
841
+ # ... set up an FPDF_FILEACCESS structure
842
+
843
+ # (Assuming `py_buffer` is the buffer and `fileaccess` the FPDF_FILEACCESS interface)
844
+ data_holder = PdfDataHolder(py_buffer, fileaccess.m_GetBlock)
845
+ pdf = pdfium_c.FPDF_LoadCustomDocument(fileaccess, None)
846
+
847
+ # ... work with the pdf
848
+
849
+ # Close the PDF to free resources
850
+ pdfium_c.FPDF_CloseDocument(pdf)
851
+ # Close the data holder, to keep the object itself and thereby the objects it
852
+ # references alive up to this point, as well as to release the buffer
853
+ data_holder.close()
854
+ ```
855
+
856
+ * Finally, let's finish this guide with an example how to render the first page of a document to a `PIL` image in `RGBA` color format.
857
+ ```python
858
+ import math
859
+ import ctypes
860
+ import os.path
861
+ import PIL.Image
862
+ import pypdfium2.raw as pdfium_c
863
+
864
+ # Load the document
865
+ filepath = os.path.abspath("tests/resources/render.pdf")
866
+ pdf = pdfium_c.FPDF_LoadDocument((filepath+"\x00").encode("utf-8"), None)
867
+
868
+ # Check page count to make sure it was loaded correctly
869
+ page_count = pdfium_c.FPDF_GetPageCount(pdf)
870
+ assert page_count >= 1
871
+
872
+ # Load the first page and get its dimensions
873
+ page = pdfium_c.FPDF_LoadPage(pdf, 0)
874
+ width = math.ceil(pdfium_c.FPDF_GetPageWidthF(page))
875
+ height = math.ceil(pdfium_c.FPDF_GetPageHeightF(page))
876
+
877
+ # Create a bitmap
878
+ # (Note, pdfium is faster at rendering transparency if we use BGRA rather than BGRx)
879
+ use_alpha = pdfium_c.FPDFPage_HasTransparency(page)
880
+ bitmap = pdfium_c.FPDFBitmap_Create(width, height, int(use_alpha))
881
+ # Fill the whole bitmap with a white background
882
+ # The color is given as a 32-bit integer in ARGB format (8 bits per channel)
883
+ pdfium_c.FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF)
884
+
885
+ # Store common rendering arguments
886
+ render_args = (
887
+ bitmap, # the bitmap
888
+ page, # the page
889
+ # positions and sizes are to be given in pixels and may exceed the bitmap
890
+ 0, # left start position
891
+ 0, # top start position
892
+ width, # horizontal size
893
+ height, # vertical size
894
+ 0, # rotation (as constant, not in degrees!)
895
+ pdfium_c.FPDF_LCD_TEXT | pdfium_c.FPDF_ANNOT, # rendering flags, combined with binary or
896
+ )
897
+
898
+ # Render the page
899
+ pdfium_c.FPDF_RenderPageBitmap(*render_args)
900
+
901
+ # Get the value of a pointer to the first item of the buffer
902
+ buffer_ptrval = pdfium_c.FPDFBitmap_GetBuffer(bitmap)
903
+ assert buffer_ptrval, "buffer pointer value must be non-null"
904
+ # Cast the pointer value to an actual pointer object so we can access .contents
905
+ buffer_ptr = ctypes.cast(buffer_ptrval, ctypes.POINTER(ctypes.c_ubyte))
906
+ # Re-interpret as array
907
+ buffer = (ctypes.c_ubyte * (width * height * 4)).from_address(ctypes.addressof(buffer_ptr.contents))
908
+
909
+ # Create a PIL image from the buffer contents
910
+ img = PIL.Image.frombuffer("RGBA", (width, height), buffer, "raw", "BGRA", 0, 1)
911
+ # Save it as file
912
+ img.save("out.png")
913
+
914
+ # Free resources
915
+ pdfium_c.FPDFBitmap_Destroy(bitmap)
916
+ pdfium_c.FPDF_ClosePage(page)
917
+ pdfium_c.FPDF_CloseDocument(pdf)
918
+ ```
919
+
920
+ ### [Command-line Interface](https://pypdfium2.readthedocs.io/en/stable/shell_api.html)
921
+
922
+ pypdfium2 also ships with a simple command-line interface, providing access to key features of the support model in a shell environment (e. g. rendering, content extraction, document inspection, page rearranging, ...).
923
+
924
+ The primary motivation behind this is to have a nice testing interface, but it may be helpful in a variety of other situations as well.
925
+ Usage should be largely self-explanatory, assuming some familiarity with the command-line.
926
+ See `pypdfium2 --help` or `pypdfium2 $SUBCOMMAND --help` for available commands and options.
927
+
928
+ If you wish to call pypdfium2's CLI through `python -m`, note that the module name is `pypdfium2_cli` (not just `pypdfium2`), unlike the entrypoint script.
929
+
930
+ ## Licensing
931
+
932
+ > [!NOTE]
933
+ > __Disclaimer:__ *This project is provided on an "as-is" basis. This is not legal advice, and there is absolutely no warranty. Please check relevant licenses on your own.*
934
+ > *See also [GitHub's disclaimer](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository#disclaimer).*
935
+
936
+ pypdfium2 itself is available by the terms and conditions of [`Apache-2.0`](LICENSES/Apache-2.0.txt) / [`BSD-3-Clause`](LICENSES/BSD-3-Clause.txt).
937
+ Documentation and examples of pypdfium2 are licensed under [`CC-BY-4.0`](LICENSES/CC-BY-4.0.txt).
938
+ pypdfium2 includes [SPDX](https://spdx.org/licenses/) headers in source files.
939
+ License information for data files is provided in [`REUSE.toml`](REUSE.toml) as per the [`reuse` standard](https://reuse.software/spec/).
940
+
941
+ PDFium is available under "a BSD-style license that can be found in \[its\] [`LICENSE`](https://pdfium.googlesource.com/pdfium/+/refs/heads/main/LICENSE) file".<br>
942
+ Various other open-source licenses apply to dependencies included with PDFium.
943
+ PDFium's license as well as dependency licenses have to be shipped with binary distributions.<br>
944
+ See the [`BUILD_LICENSES/`](BUILD_LICENSES/) directory, or the licenses shipped with our wheel builds.
945
+
946
+ PDFium's dependencies might change over time. Please notify us if you think a relevant license is missing.
947
+
948
+ To the author's knowledge, pypdfium2 is one of the rare Python libraries capable of PDF rendering while not being covered by strong-copyleft licenses.[^liberal_pdf_renderlibs]
949
+
950
+ Note that the exact licensing situation depends on the build config/environment used.<br>
951
+ In particular, a subset of pypdfium2 builds may link with the `libgcc` runtime library. Check the builds you use and, if affected, libgcc's license [to evaluate if that's OK for your use](https://wiki.osdev.org/Libgcc#What_is_the_libgcc_license?).
952
+
953
+ [^liberal_pdf_renderlibs]: Other mature, liberal-licensed PDF rendering libraries known to the author are [`pdf.js`](https://github.com/mozilla/pdf.js/) (JavaScript) and [`Apache PDFBox`](https://github.com/apache/pdfbox) (Java). While they can be accessed from Python in principle, as shown in the author's gists ([pdfbox](https://gist.github.com/mara004/51c3216a9eabd3dcbc78a86d877a61dc), [pdfjs](https://gist.github.com/mara004/87276da4f8be31c80c38036c6ab667d7)), there don't seem to be proper python bindings projects to these libraries yet. These days, novel options have surfaced, including `docling-parse` and `pdf_oxide`, but the author is not familiar with them yet.
954
+
955
+
956
+ ## Issues / Contributions
957
+
958
+ While using pypdfium2, you might encounter bugs or missing features.
959
+ In this case, feel free to open an issue or discussion thread. If applicable, include details such as tracebacks, OS and CPU type, as well as the versions of pypdfium2 and used dependencies.
960
+
961
+ Roadmap:
962
+ * pypdfium2
963
+ - [Issues panel](https://github.com/pypdfium2-team/pypdfium2/issues): Initial bug reports and feature requests. May need to be transferred to dependencies.
964
+ - [Discussions page](https://github.com/pypdfium2-team/pypdfium2/discussions): General questions and suggestions.
965
+ * PDFium
966
+ - [Bug tracker](https://crbug.com/pdfium/): Issues in PDFium.
967
+ Beware: The bridge between Python and C increases the probability of integration issues or API misuse. The symptoms can often make it look like a PDFium bug while it is not.
968
+ - [Mailing list](https://groups.google.com/g/pdfium/): Questions regarding PDFium usage.
969
+ * [pdfium-binaries](https://github.com/bblanchon/pdfium-binaries/issues): Binary builder.
970
+ * [ctypesgen](https://github.com/pypdfium2-team/ctypesgen/issues): Bindings generator (fork). See also [upstream](https://github.com/ctypesgen/ctypesgen/issues).
971
+
972
+ ### Policy
973
+ <!-- Inspired by bluesky's contributions policy: https://github.com/bluesky-social/indigo -->
974
+
975
+ Given this is a volunteer open-source project, it is possible you may not get a response to your issue, or it may be closed without much feedback. Conversations may be locked if we feel like our attention is getting DDOSed. We may not have time to provide much usage support.
976
+
977
+ The same applies to Pull Requests. We will accept contributions only if we find them suitable. Do not reach out with a strong expectation to get your change merged; it is solely up to the repository owner to decide if and when a PR will be merged, and PRs that we consider unsuitable will be rejected without further ado.
978
+ If the code owner decides a change is inappropriate, that's it, and further discussion will not be accepted.
979
+ Any attempts to pressure us to merge a PR will not be tolerated, and may result in the offender being blocked.
980
+
981
+ ### No AI issues and PRs
982
+
983
+ <!-- Due to an extreme influx of AI slop on GitHub, nearly all major projects have added some kind of AI policy. This is ours. Perhaps, GitHub banning AI issues/PRs in the first place (similar to Stackoverflow) might have been the better approach. -->
984
+
985
+ AI issues and PRs are banned from this project.
986
+
987
+ Any issues or PRs that exhibit the typical characteristics of low-quality generative AI will be labelled as `spam / ai` and closed/locked immediately, no matter how important they may claim to be.
988
+
989
+ Our issue and PR templates make it quite plain that AI is not allowed, so users who violate this policy should not be surprised to find themselves blocked.
990
+
991
+ [This announcement](https://github.com/pypdfium2-team/pypdfium2/discussions/449) offers some more background as to why this decision was reached.
992
+
993
+ ### Known limitations
994
+
995
+ #### Incompatibility with Threading
996
+
997
+ PDFium is inherently not thread-safe. See the [API docs](https://pypdfium2.readthedocs.io/en/stable/python_api.html#incompatibility-with-threading) for more information.
998
+
999
+ #### Risk of unknown object lifetime violations
1000
+
1001
+ As outlined in the raw API section, it is essential that Python-managed resources remain available as long as they are needed by PDFium.
1002
+
1003
+ The problem is that the Python interpreter may garbage collect objects with reference count zero at any time, so it can happen that an unreferenced but still required object by chance stays around long enough before it is garbage collected. However, it could also disappear too soon and cause breakage. Such dangling objects result in non-deterministic memory issues that are hard to debug.
1004
+ If the timeframe between reaching reference count zero and removal is sufficiently large and roughly consistent across different runs, it is even possible that mistakes regarding object lifetime remain unnoticed for a long time.
1005
+
1006
+ Although we intend to develop helpers carefully, it cannot be fully excluded that unknown object lifetime violations might still be lurking around somewhere, especially if unexpected requirements were not documented by the time the code was written.
1007
+
1008
+ #### Missing raw PDF access
1009
+
1010
+ As of this writing, PDFium's public interface does not provide access to the raw PDF data structure (see [issue 1694](https://crbug.com/pdfium/1694)). It does not expose APIs to read/write PDF dictionaries, streams, name/number trees, etc. Instead, it merely offers a predefined set of abstracted functions. This considerably limits the library's potential, compared to other products such as `pikepdf`.
1011
+
1012
+ #### Limitations of ABI bindings
1013
+
1014
+ PDFium's non-public backend would provide extended capabilities, including [raw access](#missing-raw-pdf-access), but it is written in C++, which (unlike pure C) does not result in a stable ABI, so we cannot use it with `ctypes`. This means it's out of scope for this project.
1015
+
1016
+ Also, while ABI bindings tend to be more convenient, they have some technical drawbacks compared to API bindings (see e.g. [1](https://cffi.readthedocs.io/en/latest/overview.html#abi-versus-api), [2](https://github.com/ocrmypdf/OCRmyPDF/issues/541#issuecomment-1834684532))
1017
+
1018
+
1019
+ ## Development
1020
+ <!-- TODO wheel tags, maintainer access, GitHub peculiarities -->
1021
+
1022
+ ### Long lines
1023
+
1024
+ We do not hard wrap long lines.
1025
+ It is recommended to set up automatic word wrap in your text editor, e.g. VS Code:
1026
+ ```
1027
+ editor.wordWrap = bounded
1028
+ editor.wordWrapColumn = 100
1029
+ ```
1030
+
1031
+ ### Command recipes
1032
+
1033
+ We use the [`just` command runner](https://github.com/casey/just), which can be seen as a modern, flexible alternative to `make`. In particular, there's no good way to pass through positional arguments with `make`.
1034
+
1035
+ Run `just -l` (or open the `justfile`) to view the available commands.
1036
+
1037
+ ### Docs
1038
+
1039
+ pypdfium2 has API documentation built with [Sphinx](https://github.com/sphinx-doc/sphinx/), which can be rendered to various formats, including HTML:
1040
+ ```bash
1041
+ sphinx-build -b html ./docs/source ./docs/build/html/
1042
+ just docs-build # short alias
1043
+ ```
1044
+ <!-- there's also a Makefile in docs/ as generated by sphinx-quickstart (cd docs/; make build) -->
1045
+
1046
+ Docs are primarily hosted on [`readthedocs.org`](https://readthedocs.org/projects/pypdfium2/).
1047
+ It may be configured using a [`.readthedocs.yaml`](.readthedocs.yaml) file (see [instructions](https://docs.readthedocs.io/en/stable/config-file/v2.html)), and the administration page on the web interface.
1048
+ RTD theoretically supports hosting multiple versions, but currently, we only host one build for the latest release through the `stable` branch.
1049
+ New builds are automatically triggered by a webhook whenever a linked branch is pushed.
1050
+
1051
+ Additionally, one doc build can also be hosted on [GitHub Pages](https://pypdfium2-team.github.io/pypdfium2/index.html).
1052
+ It is implemented with a CI workflow, which is supposed to be triggered automatically on release.
1053
+ This provides us with full control over build env and used commands, whereas RTD may be less liberal in this regard.
1054
+
1055
+ ### Testing
1056
+
1057
+ pypdfium2 contains a small test suite to verify the library's functionality. It is written with [pytest](https://github.com/pytest-dev/pytest/):
1058
+ ```bash
1059
+ python -m pytest tests/ # or `just test`
1060
+ ```
1061
+
1062
+ Pass `-sv` to get more detailed output.
1063
+ Environment variables used by the CLI are also honored in the test suite: `PYPDFIUM_LOGLEVEL`, `DEBUG_AUTOCLOSE`, `DEBUG_SYSFONTS`, `DEBUG_UNSUPPORTED`.
1064
+ See [`pypdfium2 --help`](https://pypdfium2.readthedocs.io/en/stable/shell_api.html#main-help) for description.
1065
+
1066
+ To get code coverage statistics, you may call
1067
+ ```bash
1068
+ just coverage
1069
+ ```
1070
+
1071
+ Sometimes, it can also be helpful to test code on many PDFs.[^testing_corpora]
1072
+ In this case, the command-line interface and `find` come in handy:
1073
+ ```bash
1074
+ # Example A: Analyse PDF images (in the current working directory)
1075
+ find . -name '*.pdf' -exec bash -c "echo \"{}\" && pypdfium2 pageobjects \"{}\" --filter image" \;
1076
+ # Example B: Parse PDF table of contents
1077
+ find . -name '*.pdf' -exec bash -c "echo \"{}\" && pypdfium2 toc \"{}\"" \;
1078
+ ```
1079
+
1080
+ [^testing_corpora]: For instance, one could use the testing corpora of open-source PDF libraries (pdfium, pikepdf/ocrmypdf, mupdf/ghostscript, tika/pdfbox, pdfjs, ...)
1081
+
1082
+ <!-- TODO document release workflow -->
1083
+
1084
+
1085
+ ## Popular dependents
1086
+
1087
+ pypdfium2 is used by popular packages such as
1088
+ [langchain](https://github.com/langchain-ai/langchain),
1089
+ [dify](https://github.com/langgenius/dify),
1090
+ [docling](https://github.com/DS4SD/docling),
1091
+ [nougat](https://github.com/facebookresearch/nougat),
1092
+ [pdfplumber](https://github.com/jsvine/pdfplumber),
1093
+ [doctr](https://github.com/mindee/doctr/),
1094
+ and [nv-ingest](https://github.com/NVIDIA/nv-ingest).
1095
+
1096
+ This results in pypdfium2 being part of a large dependency tree.
1097
+
1098
+
1099
+ ## Thanks to[^thanks_to]
1100
+
1101
+ * [Benoît Blanchon](https://github.com/bblanchon): Author/Maintainer of [PDFium binaries](https://github.com/bblanchon/pdfium-binaries/) and [patches](https://github.com/bblanchon/pdfium-binaries/tree/master/patches).
1102
+ * [Yinlin Hu](https://github.com/YinlinHu): `pypdfium` prototype and `kuafu` PDF viewer.
1103
+ * [Mike Kroutikov](https://github.com/mkroutikov): Examples on how to use PDFium from Python in `redstork`, `redstork-ui` and `pdfbrain`.
1104
+ * [Matthieu Darbois](http://github.com/mayeut): Provider of static clang images – native performance builds in otherwise qemu-driven containers. Help with bypassing `libclang_rt` dependency.
1105
+ * [wojiushixiaobai](https://github.com/wojiushixiaobai): Helpful pointers and draft workflow for cibuildwheel. Supporting extra Linux architectures via emulated containers.
1106
+ * [Christian Heimes](https://github.com/tiran): RPM packaging for pdfium. Showing how to build pdfium natively without Google's toolchain. Big-endian fixes.
1107
+ * [Marvin Gießing](https://github.com/mgiessing): Investigation on building PDFium for a then unhandled Linux architecture (ppc64le).
1108
+ * [Adam Huganir](https://github.com/adam-huganir): Help with maintenance and development decisions since the beginning of the project.
1109
+ * [Tim Head](https://github.com/betatim): Original idea for Python bindings to PDFium with ctypesgen in `wowpng`.
1110
+ * [kobaltcore](https://github.com/kobaltcore): Bug fix for `PdfDocument.save()`.
1111
+ * [Anderson Bravalheri](https://github.com/abravalheri): Help with PEP 517/518 compliance. Hint to use an environment variable rather than separate setup files.
1112
+ * [Bastian Germann](https://github.com/bgermann): Help with inclusion of licenses for third-party components of PDFium.
1113
+
1114
+ ... and further [code contributors](https://github.com/pypdfium2-team/pypdfium2/graphs/contributors) (GitHub stats).
1115
+
1116
+ *If you have contributed to this project but are not mentioned here yet, please let us know.*
1117
+
1118
+ [^thanks_to]: People listed in this section may not necessarily have contributed any copyrightable code to the repository. Many have rather helped with ideas, or contributions to dependencies of pypdfium2.
1119
+
1120
+
1121
+ ## History
1122
+
1123
+ ### PDFium
1124
+
1125
+ The PDFium code base was originally developed as part of the commercial Foxit SDK, before being acquired and open-sourced by Google, who maintain PDFium independently ever since, while Foxit continue to develop their SDK closed-source.
1126
+
1127
+ ### pypdfium2
1128
+
1129
+ pypdfium2 is the successor of *pypdfium* and *pypdfium-reboot*.
1130
+
1131
+ Inspired by *wowpng*, the first known proof of concept Python binding to PDFium using ctypesgen, the initial *pypdfium* package was created. It had to be updated manually, which did not happen frequently. There were no platform-specific wheels, but only a single wheel that contained binaries for 64-bit Linux, Windows and macOS.
1132
+
1133
+ *pypdfium-reboot* then added a script to automate binary deployment and bindings generation to simplify regular updates. However, it was still not platform specific.
1134
+
1135
+ pypdfium2 is a full rewrite of *pypdfium-reboot* to build platform-specific wheels and consolidate the setup scripts. Further additions include ...
1136
+ * A CI workflow to automatically release new wheels at a defined schedule
1137
+ * Convenience support models that wrap the raw PDFium/ctypes API
1138
+ * Test code
1139
+ * A script to build PDFium from source