PyMuPDF 1.24.13__tar.gz → 1.25.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/PKG-INFO +1 -1
  2. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/changes.txt +33 -0
  3. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/pipcl.py +29 -8
  4. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/scripts/gh_release.py +28 -51
  5. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/scripts/sysinstall.py +37 -36
  6. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/scripts/test.py +107 -27
  7. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/setup.py +27 -6
  8. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/__init__.py +124 -70
  9. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/extra.i +22 -5
  10. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/utils.py +6 -5
  11. pymupdf-1.25.0/tests/resources/test-E+A.pdf +0 -0
  12. pymupdf-1.25.0/tests/resources/test_3448.pdf +0 -0
  13. pymupdf-1.25.0/tests/resources/test_3448.pdf-expected.png +0 -0
  14. pymupdf-1.25.0/tests/resources/test_3725.pdf +0 -0
  15. pymupdf-1.25.0/tests/resources/test_3780.pdf +0 -0
  16. pymupdf-1.25.0/tests/resources/test_3842.pdf +0 -0
  17. pymupdf-1.25.0/tests/resources/test_3854.pdf +920 -2
  18. pymupdf-1.25.0/tests/resources/test_3854_expected.png +0 -0
  19. pymupdf-1.25.0/tests/resources/test_4004.pdf +0 -0
  20. pymupdf-1.25.0/tests/resources/test_4017.pdf +0 -0
  21. pymupdf-1.25.0/tests/resources/test_4026.pdf +0 -0
  22. pymupdf-1.25.0/tests/resources/test_4034.pdf +0 -0
  23. pymupdf-1.25.0/tests/resources/test_4043.pdf +77 -0
  24. pymupdf-1.25.0/tests/resources/test_4047.pdf +0 -0
  25. pymupdf-1.25.0/tests/resources/test_4079.pdf +0 -0
  26. pymupdf-1.25.0/tests/resources/test_4079_after.pdf +0 -0
  27. pymupdf-1.25.0/tests/resources/test_4090.pdf +0 -0
  28. pymupdf-1.25.0/tests/test-rtl.py +15 -0
  29. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_annots.py +68 -2
  30. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_embeddedfiles.py +20 -1
  31. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_font.py +26 -1
  32. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_general.py +50 -9
  33. PyMuPDF-1.24.13/tests/test_2791.py → pymupdf-1.25.0/tests/test_memory.py +30 -0
  34. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_pixmap.py +44 -0
  35. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_pylint.py +1 -0
  36. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_story.py +65 -0
  37. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_tables.py +43 -0
  38. pymupdf-1.25.0/tests/test_tesseract.py +156 -0
  39. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_textextract.py +22 -0
  40. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_widgets.py +46 -0
  41. PyMuPDF-1.24.13/tests/test_tesseract.py +0 -68
  42. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/COPYING +0 -0
  43. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/README.md +0 -0
  44. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/READMEb.md +0 -0
  45. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/READMEd.md +0 -0
  46. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/pyproject.toml +0 -0
  47. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/pytest.ini +0 -0
  48. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/__main__.py +0 -0
  49. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/_apply_pages.py +0 -0
  50. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/fitz___init__.py +0 -0
  51. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/fitz_table.py +0 -0
  52. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/fitz_utils.py +0 -0
  53. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/pymupdf.py +0 -0
  54. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src/table.py +0 -0
  55. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/__init__.py +0 -0
  56. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/__main__.py +0 -0
  57. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/_config.h +0 -0
  58. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/fitz_old.i +0 -0
  59. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-annot.i +0 -0
  60. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-convert.i +0 -0
  61. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-defines.i +0 -0
  62. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-devices.i +0 -0
  63. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-fields.i +0 -0
  64. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-fileobj.i +0 -0
  65. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-geo-c.i +0 -0
  66. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-geo-py.i +0 -0
  67. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-globals.i +0 -0
  68. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-other.i +0 -0
  69. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-pdfinfo.i +0 -0
  70. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-pixmap.i +0 -0
  71. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-portfolio.i +0 -0
  72. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-python.i +0 -0
  73. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-select.i +0 -0
  74. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-stext.i +0 -0
  75. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/helper-xobject.i +0 -0
  76. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/utils.py +0 -0
  77. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/src_classic/version.i +0 -0
  78. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/README.md +0 -0
  79. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/conftest.py +0 -0
  80. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/gentle_compare.py +0 -0
  81. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/001003ED.pdf +0 -0
  82. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/1.pdf +0 -0
  83. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/2.pdf +0 -0
  84. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/2201.00069.pdf +0 -0
  85. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/3.pdf +0 -0
  86. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/4.pdf +0 -0
  87. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/Bezier.epub +0 -0
  88. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/PragmaticaC.otf +0 -0
  89. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/battery-file-22.pdf +0 -0
  90. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/bug1945.pdf +0 -0
  91. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/bug1971.pdf +0 -0
  92. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/chinese-tables.pdf +0 -0
  93. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/chinese-tables.pickle +0 -0
  94. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/circular-toc.pdf +0 -0
  95. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/cython.pdf +0 -0
  96. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/cython.pickle +0 -0
  97. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/dotted-gridlines.pdf +0 -0
  98. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/full_toc.txt +0 -0
  99. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/github_sample.pdf +0 -0
  100. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/has-bad-fonts.pdf +0 -0
  101. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/image-file1.pdf +0 -0
  102. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/img-transparent.png +0 -0
  103. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/joined.pdf +0 -0
  104. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/metadata.txt +0 -0
  105. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/mupdf_explored.pdf +0 -0
  106. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/nur-ruhig.jpg +0 -0
  107. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/quad-calc-0.pdf +0 -0
  108. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/simple_toc.txt +0 -0
  109. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/small-table.pdf +0 -0
  110. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/strict-yes-no.pdf +0 -0
  111. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/symbol-list.pdf +0 -0
  112. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/symbols.txt +0 -0
  113. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-2333.pdf +0 -0
  114. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-2462.pdf +0 -0
  115. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-2812.pdf +0 -0
  116. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-3143.pdf +0 -0
  117. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-3150.pdf +0 -0
  118. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-3207.pdf +0 -0
  119. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-3591.pdf +0 -0
  120. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-3820.pdf +0 -0
  121. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-707448.pdf +0 -0
  122. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-707673.pdf +0 -0
  123. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test-linebreaks.pdf +0 -0
  124. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test2093.pdf +0 -0
  125. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test2182.pdf +0 -0
  126. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test2238.pdf +0 -0
  127. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_1645_expected_1.22.pdf +0 -0
  128. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_1645_expected_1.24.2.pdf +0 -0
  129. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_1645_expected_1.24.pdf +0 -0
  130. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_1645_expected_1.25.pdf +0 -0
  131. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_1824.pdf +0 -0
  132. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2108.pdf +0 -0
  133. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2270.pdf +0 -0
  134. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2533.pdf +0 -0
  135. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2548.pdf +0 -0
  136. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2553-2.pdf +0 -0
  137. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2553.pdf +0 -0
  138. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2596.pdf +0 -0
  139. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2608_expected +0 -0
  140. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2634.pdf +0 -0
  141. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2635.pdf +0 -0
  142. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2645_1.pdf +0 -0
  143. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2645_2.pdf +0 -0
  144. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2645_3.pdf +0 -0
  145. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2710.pdf +0 -0
  146. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2730.pdf +0 -0
  147. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2742.pdf +0 -0
  148. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2788.pdf +0 -0
  149. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2791_content.pdf +0 -0
  150. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2791_coverpage.pdf +0 -0
  151. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2861.pdf +0 -0
  152. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2871.pdf +0 -0
  153. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2885.pdf +0 -0
  154. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2904.pdf +0 -0
  155. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2907.pdf +0 -0
  156. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2954.pdf +0 -0
  157. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2957_1.pdf +0 -0
  158. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2957_2.pdf +0 -0
  159. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2969.pdf +0 -0
  160. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_2979.pdf +0 -0
  161. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3058.pdf +0 -0
  162. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3062.pdf +0 -0
  163. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3070.pdf +0 -0
  164. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3072.pdf +0 -0
  165. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3087.pdf +0 -0
  166. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3179.pdf +0 -0
  167. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3186.pdf +0 -0
  168. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3197.pdf +0 -0
  169. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3357.pdf +0 -0
  170. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3362.pdf +0 -0
  171. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3376.pdf +0 -0
  172. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3450.pdf +0 -0
  173. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3493.epub +0 -0
  174. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3569.pdf +0 -0
  175. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3594.pdf +0 -0
  176. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3615.epub +0 -0
  177. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3624.pdf +0 -0
  178. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3624_expected.png +0 -0
  179. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3650.pdf +0 -0
  180. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3654.docx +0 -0
  181. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3677.pdf +0 -0
  182. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3687-3.epub +0 -0
  183. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3687.epub +0 -0
  184. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3705.pdf +0 -0
  185. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3727.pdf +0 -0
  186. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3789.pdf +0 -0
  187. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3848.pdf +0 -0
  188. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3863.pdf +0 -0
  189. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3863.pdf.pdf.0.png +0 -0
  190. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3863.pdf.pdf.1.png +0 -0
  191. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3863.pdf.pdf.2.png +0 -0
  192. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3863.pdf.pdf.3.png +0 -0
  193. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3863.pdf.pdf.4.png +0 -0
  194. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3863.pdf.pdf.5.png +0 -0
  195. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3863.pdf.pdf.6.png +0 -0
  196. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3863.pdf.pdf.7.png +0 -0
  197. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3933.pdf +0 -0
  198. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3950.pdf +0 -0
  199. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_3994.pdf +0 -0
  200. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_annot_file_info.pdf +0 -0
  201. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_delete_image.pdf +0 -0
  202. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/test_toc_count.pdf +0 -0
  203. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/text-find-ligatures.pdf +0 -0
  204. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/type3font.pdf +0 -0
  205. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/v110-changes.pdf +0 -0
  206. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/resources/widgettest.pdf +0 -0
  207. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/run_compound.py +0 -0
  208. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_2548.py +0 -0
  209. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_2634.py +0 -0
  210. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_2904.py +0 -0
  211. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_2907.py +0 -0
  212. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_badfonts.py +0 -0
  213. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_balance_count.py +0 -0
  214. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_cluster_drawings.py +0 -0
  215. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_codespell.py +0 -0
  216. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_crypting.py +0 -0
  217. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_docs_samples.py +0 -0
  218. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_drawings.py +0 -0
  219. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_extractimage.py +0 -0
  220. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_flake8.py +0 -0
  221. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_geometry.py +0 -0
  222. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_imagebbox.py +0 -0
  223. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_import.py +0 -0
  224. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_insertimage.py +0 -0
  225. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_insertpdf.py +0 -0
  226. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_linebreaks.py +0 -0
  227. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_linequad.py +0 -0
  228. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_metadata.py +0 -0
  229. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_mupdf_regressions.py +0 -0
  230. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_named_links.py +0 -0
  231. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_nonpdf.py +0 -0
  232. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_object_manipulation.py +0 -0
  233. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_objectstreams.py +0 -0
  234. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_optional_content.py +0 -0
  235. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_page_links.py +0 -0
  236. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_pagedelete.py +0 -0
  237. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_pagelabels.py +0 -0
  238. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_remove-rotation.py +0 -0
  239. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_showpdfpage.py +0 -0
  240. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_textbox.py +0 -0
  241. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_textsearch.py +0 -0
  242. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_toc.py +0 -0
  243. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/tests/test_word_delimiters.py +0 -0
  244. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/valgrind.supp +0 -0
  245. {PyMuPDF-1.24.13 → pymupdf-1.25.0}/wdev.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyMuPDF
3
- Version: 1.24.13
3
+ Version: 1.25.0
4
4
  Summary: A high performance Python library for data extraction, analysis, conversion & manipulation of PDF (and other) documents.
5
5
  Description-Content-Type: text/markdown
6
6
  Author: Artifex
@@ -2,6 +2,39 @@ Change Log
2
2
  ==========
3
3
 
4
4
 
5
+ **Changes in version 1.25.0 (2024-12-05)**
6
+
7
+ * Use MuPDF-1.25.1.
8
+
9
+ * Fixed issues:
10
+
11
+ * **Fixed** `4026 <https://github.com/pymupdf/PyMuPDF/issues/4026>`_: page.get_text('blocks') output two piece of very similar text with different bbox
12
+ * **Fixed** `4004 <https://github.com/pymupdf/PyMuPDF/issues/4004>`_: Segmentation Fault When Updating PDF Form Field Value
13
+ * **Fixed** `3751 <https://github.com/pymupdf/PyMuPDF/issues/3751>`_: apply_redactions causes part of the page content to be hidden / transparent
14
+
15
+
16
+ **Changes in version 1.24.14 (2024-11-19)**
17
+
18
+ * Use MuPDF-1.24.11.
19
+
20
+ * Fixed issues:
21
+
22
+ * **Fixed** `3448 <https://github.com/pymupdf/PyMuPDF/issues/3448>`_: get_pixmap function removes the table and leaves just the content behind
23
+ * **Fixed** `3758 <https://github.com/pymupdf/PyMuPDF/issues/3758>`_: Got "malloc(): unaligned tcache chunk detected Aborted (core dumped)" while using add_redact_annot/apply_redactions
24
+ * **Fixed** `3813 <https://github.com/pymupdf/PyMuPDF/issues/3813>`_: Stories: Ordered list count broken with nested unordered list
25
+ * **Fixed** `3933 <https://github.com/pymupdf/PyMuPDF/issues/3933>`_: font.valid_codepoints() - malfunction
26
+ * **Fixed** `4018 <https://github.com/pymupdf/PyMuPDF/issues/4018>`_: PyMuPDF hangs when iterating over zero page PDF pages backwards
27
+ * **Fixed** `4043 <https://github.com/pymupdf/PyMuPDF/issues/4043>`_: fullcopypage bug
28
+ * **Fixed** `4047 <https://github.com/pymupdf/PyMuPDF/issues/4047>`_: Segmentation Fault in add_redact_annot
29
+ * **Fixed** `4050 <https://github.com/pymupdf/PyMuPDF/issues/4050>`_: Content of dict returned by doc.embfile_info() does not fit to documentation
30
+
31
+ * Other:
32
+
33
+ * Ensure that words from `Page.get_text()` never contain RTL/LTR char mixtures.
34
+ * Fix building with system MuPDF.
35
+ * Add dot product for points and vectors.
36
+
37
+
5
38
  **Changes in version 1.24.13 (2024-10-29)**
6
39
 
7
40
  * Fixed issues:
@@ -364,7 +364,7 @@ class Package:
364
364
  * https://pypi.org/classifiers/
365
365
 
366
366
  requires_dist:
367
- A string or list of strings. Also see PEP-508.
367
+ A string or list of strings. None items are ignored. Also see PEP-508.
368
368
  requires_python:
369
369
  A string or list of strings.
370
370
  requires_external:
@@ -489,6 +489,7 @@ class Package:
489
489
  Used as `zipfile.ZipFile()`'s `compresslevel` parameter when
490
490
  creating wheels.
491
491
 
492
+ Occurrences of `None` in lists are ignored.
492
493
  '''
493
494
  assert name
494
495
  assert version
@@ -689,7 +690,7 @@ class Package:
689
690
  else:
690
691
  items = self.fn_sdist()
691
692
 
692
- prefix = f'{self.name}-{self.version}'
693
+ prefix = f'{_normalise(self.name)}-{self.version}'
693
694
  os.makedirs(sdist_directory, exist_ok=True)
694
695
  tarpath = f'{sdist_directory}/{prefix}.tar.gz'
695
696
  log2(f'Creating sdist: {tarpath}')
@@ -822,7 +823,7 @@ class Package:
822
823
  return ret
823
824
 
824
825
  def wheel_name(self):
825
- return f'{self.name}-{self.version}-{self.tag_python()}-{self.tag_abi()}-{self.tag_platform()}.whl'
826
+ return f'{_normalise(self.name)}-{self.version}-{self.tag_python()}-{self.tag_abi()}-{self.tag_platform()}.whl'
826
827
 
827
828
  def wheel_name_match(self, wheel):
828
829
  '''
@@ -851,7 +852,7 @@ class Package:
851
852
  log2(f'py_limited_api; {tag_python=} compatible with {self.tag_python()=}.')
852
853
  py_limited_api_compatible = True
853
854
 
854
- log2(f'{self.name == name=}')
855
+ log2(f'{_normalise(self.name) == name=}')
855
856
  log2(f'{self.version == version=}')
856
857
  log2(f'{self.tag_python() == tag_python=} {self.tag_python()=} {tag_python=}')
857
858
  log2(f'{py_limited_api_compatible=}')
@@ -860,7 +861,7 @@ class Package:
860
861
  log2(f'{self.tag_platform()=}')
861
862
  log2(f'{tag_platform.split(".")=}')
862
863
  ret = (1
863
- and self.name == name
864
+ and _normalise(self.name) == name
864
865
  and self.version == version
865
866
  and (self.tag_python() == tag_python or py_limited_api_compatible)
866
867
  and self.tag_abi() == tag_abi
@@ -1244,7 +1245,7 @@ class Package:
1244
1245
  )
1245
1246
 
1246
1247
  def _dist_info_dir( self):
1247
- return f'{self.name}-{self.version}.dist-info'
1248
+ return f'{_normalise(self.name)}-{self.version}.dist-info'
1248
1249
 
1249
1250
  def _metainfo(self):
1250
1251
  '''
@@ -1261,7 +1262,8 @@ class Package:
1261
1262
  return
1262
1263
  if isinstance( value, (tuple, list)):
1263
1264
  for v in value:
1264
- add( key, v)
1265
+ if v is not None:
1266
+ add( key, v)
1265
1267
  return
1266
1268
  if key == 'License' and '\n' in value:
1267
1269
  # This is ok because we write `self.license` into
@@ -1899,7 +1901,16 @@ def git_items( directory, submodules=False):
1899
1901
  return ret
1900
1902
 
1901
1903
 
1902
- def run( command, capture=False, check=1, verbose=1, env_extra=None, caller=1):
1904
+ def run(
1905
+ command,
1906
+ *,
1907
+ capture=False,
1908
+ check=1,
1909
+ verbose=1,
1910
+ env_extra=None,
1911
+ timeout=None,
1912
+ caller=1,
1913
+ ):
1903
1914
  '''
1904
1915
  Runs a command using `subprocess.run()`.
1905
1916
 
@@ -1923,6 +1934,10 @@ def run( command, capture=False, check=1, verbose=1, env_extra=None, caller=1):
1923
1934
  If true we show the command.
1924
1935
  env_extra:
1925
1936
  None or dict to add to environ.
1937
+ timeout:
1938
+ If not None, timeout in seconds; passed directly to
1939
+ subprocess.run(). Note that on MacOS subprocess.run() seems to
1940
+ leave processes running if timeout expires.
1926
1941
  Returns:
1927
1942
  check capture Return
1928
1943
  --------------------------
@@ -1949,6 +1964,7 @@ def run( command, capture=False, check=1, verbose=1, env_extra=None, caller=1):
1949
1964
  check=check,
1950
1965
  encoding='utf8',
1951
1966
  env=env,
1967
+ timeout=timeout,
1952
1968
  )
1953
1969
  if check:
1954
1970
  return cp.stdout if capture else None
@@ -2357,6 +2373,11 @@ def _fs_mtime( filename, default=0):
2357
2373
  return default
2358
2374
 
2359
2375
 
2376
+ def _normalise(name):
2377
+ # https://packaging.python.org/en/latest/specifications/name-normalization/#name-normalization
2378
+ return re.sub(r"[-_.]+", "-", name).lower()
2379
+
2380
+
2360
2381
  def _assert_version_pep_440(version):
2361
2382
  assert re.match(
2362
2383
  r'^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$',
@@ -89,6 +89,14 @@ import test as test_py
89
89
 
90
90
  pymupdf_dir = os.path.abspath( f'{__file__}/../..')
91
91
 
92
+ sys.path.insert(0, pymupdf_dir)
93
+ import pipcl
94
+ del sys.path[0]
95
+
96
+ log = pipcl.log0
97
+ run = pipcl.run
98
+
99
+
92
100
  def main():
93
101
 
94
102
  log( '### main():')
@@ -223,7 +231,7 @@ def build( platform_=None, valgrind=False):
223
231
  if platform.system() == 'Linux' and inputs_wheels_linux_pyodide:
224
232
  # Pyodide wheels are built by running scripts/test.py, not
225
233
  # cibuildwheel.
226
- command = f'{sys.executable} scripts/test.py'
234
+ command = f'{sys.executable} scripts/test.py -P 1'
227
235
  if inputs_PYMUPDF_SETUP_MUPDF_BUILD:
228
236
  command += f' -m {shlex.quote(inputs_PYMUPDF_SETUP_MUPDF_BUILD)}'
229
237
  command += ' pyodide_wheel'
@@ -237,14 +245,14 @@ def build( platform_=None, valgrind=False):
237
245
  os.chdir( pymupdf_dir)
238
246
  # Create PyMuPDF sdist.
239
247
  run(f'{sys.executable} setup.py sdist')
240
- assert glob.glob('dist/PyMuPDF-*.tar.gz')
248
+ assert glob.glob('dist/pymupdf-*.tar.gz')
241
249
  if inputs_flavours:
242
250
  # Create PyMuPDFb sdist.
243
251
  run(
244
252
  f'{sys.executable} setup.py sdist',
245
253
  env_extra=dict(PYMUPDF_SETUP_FLAVOUR='b'),
246
254
  )
247
- assert glob.glob('dist/PyMuPDFb-*.tar.gz')
255
+ assert glob.glob('dist/pymupdfb-*.tar.gz')
248
256
 
249
257
  # Build wheels.
250
258
  #
@@ -284,11 +292,11 @@ def build( platform_=None, valgrind=False):
284
292
  ret.append(item)
285
293
  return ' '.join(ret)
286
294
 
287
- cps = inputs_wheels_cps if inputs_wheels_cps else 'cp39* cp310* cp311* cp312* cp313'
295
+ cps = inputs_wheels_cps if inputs_wheels_cps else 'cp39* cp310* cp311* cp312* cp313*'
288
296
  set_if_unset( 'CIBW_BUILD', cps)
289
297
  for cp in cps.split():
290
298
  m = re.match('cp([0-9]+)[*]', cp)
291
- assert m
299
+ assert m, f'{cps=} {cp=}'
292
300
  v = int(m.group(1))
293
301
  if v == 314:
294
302
  # Need to set CIBW_PRERELEASE_PYTHONS, otherwise cibuildwheel
@@ -351,6 +359,8 @@ def build( platform_=None, valgrind=False):
351
359
  if pass_:
352
360
  env_pass(name)
353
361
 
362
+ env_pass('PYMUPDF_SETUP_PY_LIMITED_API')
363
+
354
364
  if os.environ.get('PYMUPDF_SETUP_LIBCLANG'):
355
365
  env_pass('PYMUPDF_SETUP_LIBCLANG')
356
366
 
@@ -389,7 +399,8 @@ def build( platform_=None, valgrind=False):
389
399
  env_pass('PYMUPDF_SETUP_PY_LIMITED_API')
390
400
  CIBW_BUILD_old = env_extra.get('CIBW_BUILD')
391
401
  assert CIBW_BUILD_old is not None
392
- env_set('CIBW_BUILD', 'cp39*')
402
+ cp = cps.split()[0]
403
+ env_set('CIBW_BUILD', cp)
393
404
  log(f'Building single wheel.')
394
405
  run( f'cibuildwheel{platform_arg}', env_extra=env_extra)
395
406
 
@@ -413,7 +424,16 @@ def build( platform_=None, valgrind=False):
413
424
  #
414
425
  env_set('CIBW_REPAIR_WHEEL_COMMAND', '')
415
426
 
416
- log(f'Testing on all python versions using wheels in wheelhouse/.')
427
+ if platform.system() == 'Linux' and env_extra.get('CIBW_ARCHS_LINUX') == 'aarch64':
428
+ log(f'Testing all Python versions on linux-aarch64 is too slow and is killed by github after 6h.')
429
+ log(f'Testing on restricted python versions using wheels in wheelhouse/.')
430
+ # Testing only on first and last python versions.
431
+ cp1 = cps.split()[0]
432
+ cp2 = cps.split()[-1]
433
+ cp = cp1 if cp1 == cp2 else f'{cp1} {cp2}'
434
+ env_set('CIBW_BUILD', cp)
435
+ else:
436
+ log(f'Testing on all python versions using wheels in wheelhouse/.')
417
437
  run( f'cibuildwheel{platform_arg}', env_extra=env_extra)
418
438
 
419
439
  elif inputs_flavours:
@@ -455,7 +475,7 @@ def build( platform_=None, valgrind=False):
455
475
  # careful to avoid incompatible wheels, e.g. 32 vs 64-bit wheels
456
476
  # coexist during Windows builds.
457
477
  #
458
- env_set('CIBW_BEFORE_TEST', f'python scripts/gh_release.py pip_install wheelhouse/PyMuPDFb')
478
+ env_set('CIBW_BEFORE_TEST', f'python scripts/gh_release.py pip_install wheelhouse/pymupdfb')
459
479
 
460
480
  set_cibuild_test()
461
481
 
@@ -576,49 +596,6 @@ else:
576
596
  return os.path.relpath(path, start)
577
597
 
578
598
 
579
- def log(text, caller=0):
580
- '''
581
- Writes `text` to stdout with prefix showing caller path relative to
582
- pymupdf_dir and fn name.
583
- '''
584
- frame_record = inspect.stack( context=0)[ caller+1]
585
- filename = frame_record.filename
586
- line = frame_record.lineno
587
- function = frame_record.function
588
- prefix = f'{relpath(filename, pymupdf_dir)}:{line}:{function}(): '
589
- print(textwrap.indent(text, prefix), flush=1)
590
-
591
-
592
- def run(command, env_extra=None, check=1, timeout=None):
593
- '''
594
- Runs a command using subprocess.run().
595
- Args:
596
- command:
597
- The command to run.
598
- env_extra:
599
- None or dict containing extra environment variable settings to add
600
- to os.environ.
601
- check:
602
- Whether to raise exception if command fails.
603
- timeout:
604
- If not None, timeout in seconds; passed directory to
605
- subprocess.run(). Note that on MacOS subprocess.run() seems to
606
- leave processes running if timeout expires.
607
- '''
608
- env = None
609
- message = 'Running: '
610
- if env_extra:
611
- env = os.environ.copy()
612
- env.update(env_extra)
613
- message += '\n[environment:\n'
614
- for n, v in env_extra.items():
615
- message += f' {n}={shlex.quote(v)}\n'
616
- message += ']\n'
617
- message += f'{command}'
618
- log(message, caller=1)
619
- return subprocess.run(command, check=check, shell=1, env=env, timeout=timeout)
620
-
621
-
622
599
  def platform_tag():
623
600
  bits = cpu_bits()
624
601
  if platform.system() == 'Windows':
@@ -49,7 +49,7 @@ Args:
49
49
  --pymupdf-do 0|1
50
50
  Whether to build and install pymupdf.
51
51
  --root <root>
52
- Root of install directory; default is `/`.
52
+ Root of install directory; default is 'pymupdf-sysinstall-test-root'.
53
53
  --tesseract5 0|1
54
54
  If 1 (the default), we force installation of libtesseract-dev version
55
55
  5 (which is not available as a default package in Ubuntu-22.04) from
@@ -86,6 +86,14 @@ import sysconfig
86
86
 
87
87
  import test as test_py
88
88
 
89
+ pymupdf_dir = os.path.abspath( f'{__file__}/../..')
90
+
91
+ sys.path.insert(0, pymupdf_dir)
92
+ import pipcl
93
+ del sys.path[0]
94
+
95
+ log = pipcl.log0
96
+
89
97
  # Requirements for a system build and install:
90
98
  #
91
99
  # system packages (Debian names):
@@ -106,12 +114,12 @@ g_sys_packages = [
106
114
  def main():
107
115
 
108
116
  if 1:
109
- print(f'## {__file__}: Starting.')
110
- print(f'{sys.executable=}')
111
- print(f'{platform.python_version()=}')
112
- print(f'{__file__=}')
113
- print(f'{sys.argv=}')
114
- print(f'{sysconfig.get_path("platlib")=}')
117
+ log(f'## {__file__}: Starting.')
118
+ log(f'{sys.executable=}')
119
+ log(f'{platform.python_version()=}')
120
+ log(f'{__file__=}')
121
+ log(f'{sys.argv=}')
122
+ log(f'{sysconfig.get_path("platlib")=}')
115
123
  run_command(f'python -V', check=0)
116
124
  run_command(f'python3 -V', check=0)
117
125
  run_command(f'sudo python -V', check=0)
@@ -132,8 +140,7 @@ def main():
132
140
  packages = True
133
141
  prefix = '/usr/local'
134
142
  pymupdf_do = True
135
- pymupdf_dir = os.path.abspath( f'{__file__}/../..')
136
- root = 'sysinstall_test'
143
+ root = 'pymupdf-sysinstall-test-root'
137
144
  tesseract5 = True
138
145
  pytest_args = None
139
146
  pytest_do = True
@@ -152,7 +159,7 @@ def main():
152
159
  except StopIteration:
153
160
  break
154
161
  if arg in ('-h', '--help'):
155
- print(__doc__)
162
+ log(__doc__)
156
163
  return
157
164
  elif arg == '--mupdf-do': mupdf_do = int(next(args))
158
165
  elif arg == '--mupdf-dir': mupdf_dir = next(args)
@@ -161,7 +168,6 @@ def main():
161
168
  elif arg == '--packages': packages = int(next(args))
162
169
  elif arg == '--prefix': prefix = next(args)
163
170
  elif arg == '--pymupdf-do': pymupdf_do = int(next(args))
164
- elif arg == '--pymupdf-dir': pymupdf_dir = next(args)
165
171
  elif arg == '--root': root = next(args)
166
172
  elif arg == '--tesseract5': tesseract5 = int(next(args))
167
173
  elif arg == '--pytest-do': pytest_do = int(next(args))
@@ -184,30 +190,30 @@ def main():
184
190
  sudo = ''
185
191
  if root == '/':
186
192
  sudo = f'sudo PATH={os.environ["PATH"]} '
187
- def run(command):
188
- return run_command(command, doit=mupdf_do)
193
+ def run(command, env_extra=None):
194
+ return run_command(command, doit=mupdf_do, env_extra=env_extra)
189
195
  # Get MuPDF from git if specified.
190
196
  #
191
197
  if mupdf_git:
192
198
  # Update existing checkout or do `git clone`.
193
199
  if os.path.exists(mupdf_dir):
194
- print(f'## Update MuPDF checkout {mupdf_dir}.')
200
+ log(f'## Update MuPDF checkout {mupdf_dir}.')
195
201
  run(f'cd {mupdf_dir} && git pull && git submodule update --init')
196
202
  else:
197
203
  # No existing git checkout, so do a fresh clone.
198
- print(f'## Clone MuPDF into {mupdf_dir}.')
204
+ log(f'## Clone MuPDF into {mupdf_dir}.')
199
205
  run(f'git clone --recursive --depth 1 --shallow-submodules {mupdf_git} {mupdf_dir}')
200
206
 
201
207
  if packages:
202
208
  # Install required system packages. We assume a Debian package system.
203
209
  #
204
- print('## Install system packages required by MuPDF.')
210
+ log('## Install system packages required by MuPDF.')
205
211
  run(f'sudo apt update')
206
212
  run(f'sudo apt install {" ".join(g_sys_packages)}')
207
213
  # Ubuntu-22.04 has freeglut3-dev, not libglut-dev.
208
214
  run(f'sudo apt install libglut-dev | sudo apt install freeglut3-dev')
209
215
  if tesseract5:
210
- print(f'## Force installation of libtesseract-dev version 5.')
216
+ log(f'## Force installation of libtesseract-dev version 5.')
211
217
  # https://stackoverflow.com/questions/76834972/how-can-i-run-pytesseract-python-library-in-ubuntu-22-04
212
218
  #
213
219
  run('sudo apt install -y software-properties-common')
@@ -220,12 +226,12 @@ def main():
220
226
  # Build+install MuPDF. We use mupd:Makefile's install-shared-python target.
221
227
  #
222
228
  if pip == 'sudo':
223
- print('## Installing Python packages required for building MuPDF and PyMuPDF.')
229
+ log('## Installing Python packages required for building MuPDF and PyMuPDF.')
224
230
  run(f'sudo pip install --upgrade pip')
225
231
  names = test_py.wrap_get_requires_for_build_wheel(f'{__file__}/../..')
226
232
  run(f'sudo pip install {names}')
227
233
 
228
- print('## Build and install MuPDF.')
234
+ log('## Build and install MuPDF.')
229
235
  command = f'cd {mupdf_dir}'
230
236
  command += f' && {sudo}make'
231
237
  command += f' -j {multiprocessing.cpu_count()}'
@@ -246,10 +252,10 @@ def main():
246
252
 
247
253
  # Build+install PyMuPDF.
248
254
  #
249
- print('## Build and install PyMuPDF.')
255
+ log('## Build and install PyMuPDF.')
250
256
  def run(command):
251
257
  return run_command(command, doit=pymupdf_do)
252
- flags_freetype2 = run_command('pkg-config --cflags freetype2', capture_output=1).stdout.strip()
258
+ flags_freetype2 = run_command('pkg-config --cflags freetype2', capture=1)
253
259
  compile_flags = f'-I {root_prefix}/include {flags_freetype2}'
254
260
  link_flags = f'-L {root_prefix}/lib'
255
261
  env = ''
@@ -258,7 +264,7 @@ def main():
258
264
  env += f'LDFLAGS="-L {root}/{prefix}/lib" '
259
265
  env += f'PYMUPDF_SETUP_MUPDF_BUILD= ' # Use system MuPDF.
260
266
  if use_installer:
261
- print(f'## Building wheel.')
267
+ log(f'## Building wheel.')
262
268
  if pip == 'venv':
263
269
  venv_name = 'venv-pymupdf-sysinstall'
264
270
  run(f'pwd')
@@ -277,7 +283,7 @@ def main():
277
283
  wheel = glob.glob(f'dist/*')
278
284
  assert len(wheel) == 1, f'{wheel=}'
279
285
  wheel = wheel[0]
280
- print(f'## Installing wheel using `installer`.')
286
+ log(f'## Installing wheel using `installer`.')
281
287
  pv = '.'.join(platform.python_version_tuple()[:2])
282
288
  p = f'{root_prefix}/lib/python{pv}'
283
289
  # `python -m installer` fails to overwrite existing files.
@@ -315,13 +321,10 @@ def main():
315
321
  if leaf in dirnames:
316
322
  pythonpath.append(os.path.join(dirpath, leaf))
317
323
  pythonpath = ':'.join(pythonpath)
318
- print(f'{pythonpath=}')
324
+ log(f'{pythonpath=}')
319
325
  else:
320
326
  command = f'{env} pip install -vv --root {root} {os.path.abspath(pymupdf_dir)}'
321
327
  run( command)
322
- sys.path.insert(0, pymupdf_dir)
323
- import pipcl
324
- del sys.path[0]
325
328
  pythonpath = pipcl.install_dir(root)
326
329
 
327
330
  # Show contents of installation directory. This is very slow on github,
@@ -330,9 +333,9 @@ def main():
330
333
 
331
334
  # Run pytest tests.
332
335
  #
333
- print('## Run PyMuPDF pytest tests.')
334
- def run(command):
335
- return run_command(command, doit=pytest_do)
336
+ log('## Run PyMuPDF pytest tests.')
337
+ def run(command, env_extra=None):
338
+ return run_command(command, doit=pytest_do, env_extra=env_extra)
336
339
  import gh_release
337
340
  if pip == 'venv':
338
341
  # Create venv.
@@ -384,16 +387,14 @@ def main():
384
387
  command += f' -p {shlex.quote(pytest_args)}'
385
388
  if pytest_do:
386
389
  command += ' test'
387
- run(command)
390
+ run(command, env_extra=dict(PYMUPDF_SYSINSTALL_TEST='1'))
388
391
 
389
392
 
390
- def run_command(command, capture_output=False, check=True, doit=True):
393
+ def run_command(command, capture=False, check=True, doit=True, env_extra=None):
391
394
  if doit:
392
- print(f'## Running: {command}')
393
- sys.stdout.flush()
394
- return subprocess.run(command, shell=1, check=check, text=1, capture_output=capture_output)
395
+ return pipcl.run(command, capture=capture, check=check, caller=2, env_extra=env_extra)
395
396
  else:
396
- print(f'## Would have run: {command}')
397
+ log(f'## Would have run: {command}', caller=2)
397
398
 
398
399
 
399
400
  if __name__ == '__main__':