PyMuPDF 1.24.5__tar.gz → 1.24.7__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 (196) hide show
  1. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/PKG-INFO +1 -1
  2. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/READMErb.md +1 -1
  3. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/changes.txt +40 -0
  4. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/pipcl.py +28 -14
  5. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/scripts/gh_release.py +28 -6
  6. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/scripts/sysinstall.py +59 -23
  7. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/scripts/test.py +19 -1
  8. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/setup.py +38 -13
  9. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/__init__.py +122 -168
  10. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/extra.i +6 -2
  11. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/table.py +11 -7
  12. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/utils.py +57 -65
  13. PyMuPDF-1.24.7/tests/resources/dotted-gridlines.pdf +0 -0
  14. PyMuPDF-1.24.7/tests/resources/test-3591.pdf +0 -0
  15. PyMuPDF-1.24.7/tests/resources/test_3493.epub +0 -0
  16. PyMuPDF-1.24.7/tests/resources/test_3594.pdf +0 -0
  17. PyMuPDF-1.24.7/tests/resources/test_3615.epub +0 -0
  18. PyMuPDF-1.24.7/tests/resources/test_toc_count.pdf +0 -0
  19. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_2791.py +3 -2
  20. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_drawings.py +11 -1
  21. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_general.py +11 -0
  22. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_metadata.py +1 -1
  23. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_pixmap.py +94 -0
  24. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_tables.py +17 -1
  25. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_textbox.py +11 -0
  26. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_textextract.py +15 -0
  27. PyMuPDF-1.24.7/tests/test_toc.py +276 -0
  28. PyMuPDF-1.24.5/tests/test_toc.py +0 -137
  29. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/COPYING +0 -0
  30. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/README.md +0 -0
  31. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/pyproject.toml +0 -0
  32. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/pytest.ini +0 -0
  33. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/__main__.py +0 -0
  34. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/_apply_pages.py +0 -0
  35. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/fitz___init__.py +0 -0
  36. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/fitz_table.py +0 -0
  37. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/fitz_utils.py +0 -0
  38. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src/pymupdf.py +0 -0
  39. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/__init__.py +0 -0
  40. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/__main__.py +0 -0
  41. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/_config.h +0 -0
  42. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/fitz_old.i +0 -0
  43. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-annot.i +0 -0
  44. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-convert.i +0 -0
  45. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-defines.i +0 -0
  46. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-devices.i +0 -0
  47. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-fields.i +0 -0
  48. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-fileobj.i +0 -0
  49. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-geo-c.i +0 -0
  50. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-geo-py.i +0 -0
  51. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-globals.i +0 -0
  52. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-other.i +0 -0
  53. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-pdfinfo.i +0 -0
  54. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-pixmap.i +0 -0
  55. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-portfolio.i +0 -0
  56. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-python.i +0 -0
  57. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-select.i +0 -0
  58. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-stext.i +0 -0
  59. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/helper-xobject.i +0 -0
  60. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/utils.py +0 -0
  61. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/src_classic/version.i +0 -0
  62. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/README.md +0 -0
  63. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/conftest.py +0 -0
  64. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/gentle_compare.py +0 -0
  65. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/001003ED.pdf +0 -0
  66. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/1.pdf +0 -0
  67. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/2.pdf +0 -0
  68. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/2201.00069.pdf +0 -0
  69. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/3.pdf +0 -0
  70. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/4.pdf +0 -0
  71. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/Bezier.epub +0 -0
  72. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/PragmaticaC.otf +0 -0
  73. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/battery-file-22.pdf +0 -0
  74. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/bug1945.pdf +0 -0
  75. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/bug1971.pdf +0 -0
  76. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/chinese-tables.pdf +0 -0
  77. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/chinese-tables.pickle +0 -0
  78. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/circular-toc.pdf +0 -0
  79. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/cython.pdf +0 -0
  80. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/cython.pickle +0 -0
  81. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/full_toc.txt +0 -0
  82. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/github_sample.pdf +0 -0
  83. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/has-bad-fonts.pdf +0 -0
  84. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/image-file1.pdf +0 -0
  85. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/img-transparent.png +0 -0
  86. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/joined.pdf +0 -0
  87. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/metadata.txt +0 -0
  88. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/mupdf_explored.pdf +0 -0
  89. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/nur-ruhig.jpg +0 -0
  90. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/quad-calc-0.pdf +0 -0
  91. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/simple_toc.txt +0 -0
  92. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/small-table.pdf +0 -0
  93. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/strict-yes-no.pdf +0 -0
  94. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/symbol-list.pdf +0 -0
  95. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/symbols.txt +0 -0
  96. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test-2333.pdf +0 -0
  97. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test-2462.pdf +0 -0
  98. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test-2812.pdf +0 -0
  99. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test-3143.pdf +0 -0
  100. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test-3150.pdf +0 -0
  101. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test-3207.pdf +0 -0
  102. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test-707448.pdf +0 -0
  103. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test-707673.pdf +0 -0
  104. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test2093.pdf +0 -0
  105. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test2182.pdf +0 -0
  106. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test2238.pdf +0 -0
  107. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_1645_expected_1.22.pdf +0 -0
  108. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_1645_expected_1.24.2.pdf +0 -0
  109. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_1645_expected_1.24.pdf +0 -0
  110. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_1645_expected_1.25.pdf +0 -0
  111. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_1824.pdf +0 -0
  112. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2108.pdf +0 -0
  113. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2270.pdf +0 -0
  114. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2533.pdf +0 -0
  115. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2548.pdf +0 -0
  116. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2553-2.pdf +0 -0
  117. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2553.pdf +0 -0
  118. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2596.pdf +0 -0
  119. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2608_expected +0 -0
  120. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2634.pdf +0 -0
  121. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2635.pdf +0 -0
  122. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2645_1.pdf +0 -0
  123. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2645_2.pdf +0 -0
  124. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2645_3.pdf +0 -0
  125. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2710.pdf +0 -0
  126. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2730.pdf +0 -0
  127. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2742.pdf +0 -0
  128. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2788.pdf +0 -0
  129. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2791_content.pdf +0 -0
  130. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2791_coverpage.pdf +0 -0
  131. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2861.pdf +0 -0
  132. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2871.pdf +0 -0
  133. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2885.pdf +0 -0
  134. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2904.pdf +0 -0
  135. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2907.pdf +0 -0
  136. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2954.pdf +0 -0
  137. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2957_1.pdf +0 -0
  138. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2957_2.pdf +0 -0
  139. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2969.pdf +0 -0
  140. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_2979.pdf +0 -0
  141. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3058.pdf +0 -0
  142. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3062.pdf +0 -0
  143. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3070.pdf +0 -0
  144. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3072.pdf +0 -0
  145. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3087.pdf +0 -0
  146. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3179.pdf +0 -0
  147. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3186.pdf +0 -0
  148. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3197.pdf +0 -0
  149. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3357.pdf +0 -0
  150. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3362.pdf +0 -0
  151. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_3376.pdf +0 -0
  152. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_annot_file_info.pdf +0 -0
  153. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/test_delete_image.pdf +0 -0
  154. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/type3font.pdf +0 -0
  155. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/v110-changes.pdf +0 -0
  156. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/resources/widgettest.pdf +0 -0
  157. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/run_compound.py +0 -0
  158. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_2548.py +0 -0
  159. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_2634.py +0 -0
  160. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_2904.py +0 -0
  161. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_2907.py +0 -0
  162. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_annots.py +0 -0
  163. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_badfonts.py +0 -0
  164. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_balance_count.py +0 -0
  165. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_cluster_drawings.py +0 -0
  166. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_crypting.py +0 -0
  167. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_docs_samples.py +0 -0
  168. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_embeddedfiles.py +0 -0
  169. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_extractimage.py +0 -0
  170. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_flake8.py +0 -0
  171. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_font.py +0 -0
  172. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_geometry.py +0 -0
  173. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_imagebbox.py +0 -0
  174. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_import.py +0 -0
  175. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_insertimage.py +0 -0
  176. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_insertpdf.py +0 -0
  177. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_linequad.py +0 -0
  178. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_mupdf_regressions.py +0 -0
  179. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_named_links.py +0 -0
  180. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_nonpdf.py +0 -0
  181. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_object_manipulation.py +0 -0
  182. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_objectstreams.py +0 -0
  183. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_optional_content.py +0 -0
  184. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_page_links.py +0 -0
  185. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_pagedelete.py +0 -0
  186. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_pagelabels.py +0 -0
  187. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_pylint.py +0 -0
  188. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_remove-rotation.py +0 -0
  189. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_showpdfpage.py +0 -0
  190. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_story.py +0 -0
  191. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_tesseract.py +0 -0
  192. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_textsearch.py +0 -0
  193. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_widgets.py +0 -0
  194. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/tests/test_word_delimiters.py +0 -0
  195. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/valgrind.supp +0 -0
  196. {PyMuPDF-1.24.5 → PyMuPDF-1.24.7}/wdev.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyMuPDF
3
- Version: 1.24.5
3
+ Version: 1.24.7
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
@@ -1,4 +1,4 @@
1
- # PyMuPDF 1.24.3
1
+ # PyMuPDF 1.24.6
2
2
 
3
3
  This wheel contains [MuPDF](https://mupdf.readthedocs.io/) shared libraries for
4
4
  use by [PyMuPDF](https://pymupdf.readthedocs.io/).
@@ -2,6 +2,46 @@ Change Log
2
2
  ==========
3
3
 
4
4
 
5
+ **Changes in version 1.24.7 (2024-06-26)**
6
+
7
+ * Fixed issues:
8
+
9
+ * **Fixed** `3615 <https://github.com/pymupdf/PyMuPDF/issues/3615>`_: Document.pagemode or Document.pagelayout crashes for epub files
10
+ * **Fixed** `3616 <https://github.com/pymupdf/PyMuPDF/issues/3616>`_: not last version reported
11
+
12
+
13
+ **Changes in version 1.24.6 (2024-06-25)**
14
+
15
+ * Fixed issues:
16
+
17
+ * **Fixed** `3599 <https://github.com/pymupdf/PyMuPDF/issues/3599>`_: Story.fit_width() has a weird line
18
+ * **Fixed** `3594 <https://github.com/pymupdf/PyMuPDF/issues/3594>`_: Garbled extraction for Amazon Sustainability Report
19
+ * **Fixed** `3591 <https://github.com/pymupdf/PyMuPDF/issues/3591>`_: 'width' in Page.get_drawings() returns width equal as 0
20
+ * **Fixed** `3561 <https://github.com/pymupdf/PyMuPDF/issues/3561>`_: ZeroDivisionError: float division by zero with page.apply_redactions()
21
+ * **Fixed** `3559 <https://github.com/pymupdf/PyMuPDF/issues/3559>`_: SegFault 11 when empty H1 H2 H3 H4 etc element is used in insert_htmlbox
22
+ * **Fixed** `3539 <https://github.com/pymupdf/PyMuPDF/issues/3539>`_: Add dotted gridline detection to table recognition
23
+ * **Fixed** `3519 <https://github.com/pymupdf/PyMuPDF/issues/3519>`_: get_toc(simple=False) AttributeError: 'Outline' object has no attribute 'rect'
24
+ * **Fixed** `3510 <https://github.com/pymupdf/PyMuPDF/issues/3510>`_: page.get_label() gets wrong label on the first page of doc
25
+ * **Fixed** `3494 <https://github.com/pymupdf/PyMuPDF/issues/3494>`_: 1.24.2/1.24.3: spurious characters introduced when using subset_fonts and insert_pdf
26
+ * **Fixed** `3470 <https://github.com/pymupdf/PyMuPDF/issues/3470>`_: subset_fonts error exit without exception/warning
27
+ * **Fixed** `3400 <https://github.com/pymupdf/PyMuPDF/issues/3400>`_: set_toc alters link coordinates for some rotated pages on pymupdf 1.24.2
28
+ * **Fixed** `3347 <https://github.com/pymupdf/PyMuPDF/issues/3347>`_: Incorrect links to points on pages having different heights
29
+ * **Fixed** `3237 <https://github.com/pymupdf/PyMuPDF/issues/3237>`_: Set_metadata() does not work
30
+ * **Fixed** `3493 <https://github.com/pymupdf/PyMuPDF/discussions/3493>`_: Isolate PyMuPDF from other libraries; issues when PyMuPDF is loaded with other libraries like GdkPixbuf
31
+
32
+ * Other:
33
+
34
+ * Fixed concurrent use of PyMuPDF caused by use of constant temporary filenames.
35
+
36
+ * Add musllinux x86_64 wheels to release.
37
+
38
+ * Added clearer version information:
39
+
40
+ * `pymupdf.pymupdf_version`.
41
+ * `pymupdf.mupdf_version`.
42
+ * `pymupdf.pymupdf_date`.
43
+
44
+
5
45
  **Changes in version 1.24.5 (2024-05-30)**
6
46
 
7
47
  * Fixed issues:
@@ -2075,49 +2075,63 @@ def run_if( command, out, *prerequisites):
2075
2075
  >>> out = 'run_if_test_out'
2076
2076
  >>> if os.path.exists( out):
2077
2077
  ... os.remove( out)
2078
+ >>> if os.path.exists( f'{out}.cmd'):
2079
+ ... os.remove( f'{out}.cmd')
2078
2080
  >>> run_if( f'touch {out}', out)
2081
+ pipcl.py: run_if(): Running command because: File does not exist: 'run_if_test_out'
2082
+ pipcl.py: run(): Running: touch run_if_test_out
2079
2083
  True
2080
2084
 
2081
2085
  If we repeat, the output file will be up to date so the command is not run:
2082
2086
 
2083
2087
  >>> run_if( f'touch {out}', out)
2088
+ pipcl.py: run_if(): Not running command because up to date: 'run_if_test_out'
2084
2089
 
2085
2090
  If we change the command, the command is run:
2086
2091
 
2087
2092
  >>> run_if( f'touch {out}', out)
2093
+ pipcl.py: run_if(): Running command because: Command has changed
2094
+ pipcl.py: run(): Running: touch run_if_test_out
2088
2095
  True
2089
2096
 
2090
2097
  If we add a prerequisite that is newer than the output, the command is run:
2091
2098
 
2099
+ >>> time.sleep(1)
2092
2100
  >>> prerequisite = 'run_if_test_prerequisite'
2093
2101
  >>> run( f'touch {prerequisite}')
2094
- >>> run_if( f'touch {out}', out, prerequisite)
2102
+ pipcl.py: run(): Running: touch run_if_test_prerequisite
2103
+ >>> run_if( f'touch {out}', out, prerequisite)
2104
+ pipcl.py: run_if(): Running command because: Prerequisite is new: 'run_if_test_prerequisite'
2105
+ pipcl.py: run(): Running: touch run_if_test_out
2095
2106
  True
2096
2107
 
2097
2108
  If we repeat, the output will be newer than the prerequisite, so the
2098
2109
  command is not run:
2099
2110
 
2100
- >>> run_if( f'touch {out}', out, prerequisite)
2111
+ >>> run_if( f'touch {out}', out, prerequisite)
2112
+ pipcl.py: run_if(): Not running command because up to date: 'run_if_test_out'
2101
2113
  '''
2102
2114
  doit = False
2115
+ cmd_path = f'{out}.cmd'
2116
+
2103
2117
  if not doit:
2104
2118
  out_mtime = _fs_mtime( out)
2105
2119
  if out_mtime == 0:
2106
2120
  doit = f'File does not exist: {out!r}'
2107
2121
 
2108
- cmd_path = f'{out}.cmd'
2109
- if os.path.isfile( cmd_path):
2110
- with open( cmd_path) as f:
2111
- cmd = f.read()
2112
- else:
2113
- cmd = None
2114
- if command != cmd:
2115
- if cmd is None:
2116
- doit = 'No previous command stored'
2122
+ if not doit:
2123
+ if os.path.isfile( cmd_path):
2124
+ with open( cmd_path) as f:
2125
+ cmd = f.read()
2117
2126
  else:
2118
- doit = f'Command has changed'
2119
- if 0:
2120
- doit += f': {cmd!r} => {command!r}'
2127
+ cmd = None
2128
+ if command != cmd:
2129
+ if cmd is None:
2130
+ doit = 'No previous command stored'
2131
+ else:
2132
+ doit = f'Command has changed'
2133
+ if 0:
2134
+ doit += f': {cmd!r} => {command!r}'
2121
2135
 
2122
2136
  if not doit:
2123
2137
  # See whether any prerequisites are newer than target.
@@ -51,6 +51,8 @@ action inputs, which can't be easily translated into command-line arguments.
51
51
  inputs_PYMUPDF_SETUP_MUPDF_BUILD
52
52
  Used to directly set PYMUPDF_SETUP_MUPDF_BUILD.
53
53
  E.g. 'git:--recursive --depth 1 --shallow-submodules --branch master https://github.com/ArtifexSoftware/mupdf.git'
54
+ inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE
55
+ Used to directly set PYMUPDF_SETUP_MUPDF_BUILD_TYPE.
54
56
  inputs_wheels_implementations
55
57
  Used to directly set PYMUPDF_SETUP_IMPLEMENTATIONS.
56
58
  'a', 'b', 'ab'.
@@ -133,6 +135,12 @@ def main():
133
135
  pattern = f'{prefix}-*{platform_tag()}.whl'
134
136
  paths = glob.glob( pattern)
135
137
  log( f'{pattern=} {paths=}')
138
+ # Follow pipcl.py and look at AUDITWHEEL_PLAT. This allows us to
139
+ # cope if building for both musl and normal linux.
140
+ awp = os.environ.get('AUDITWHEEL_PLAT')
141
+ if awp:
142
+ paths = [i for i in paths if awp in i]
143
+ log(f'After selecting AUDITWHEEL_PLAT={awp!r}, {paths=}.')
136
144
  paths = ' '.join( paths)
137
145
  run( f'pip install {paths}')
138
146
  elif arg == 'venv':
@@ -180,6 +188,7 @@ def build( platform_=None, valgrind=False):
180
188
  inputs_wheels_windows_auto = get_bool('inputs_wheels_windows_auto', inputs_wheels_default)
181
189
  inputs_wheels_cps = os.environ.get('inputs_wheels_cps')
182
190
  inputs_PYMUPDF_SETUP_MUPDF_BUILD = os.environ.get('inputs_PYMUPDF_SETUP_MUPDF_BUILD')
191
+ inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE = os.environ.get('inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE')
183
192
  inputs_wheels_implementations = os.environ.get('inputs_wheels_implementations', 'b')
184
193
 
185
194
  log( f'{inputs_flavours=}')
@@ -194,6 +203,7 @@ def build( platform_=None, valgrind=False):
194
203
  log( f'{inputs_wheels_windows_auto=}')
195
204
  log( f'{inputs_wheels_cps=}')
196
205
  log( f'{inputs_PYMUPDF_SETUP_MUPDF_BUILD=}')
206
+ log( f'{inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE=}')
197
207
 
198
208
  # Build Pyodide wheel if specified.
199
209
  #
@@ -236,7 +246,11 @@ def build( platform_=None, valgrind=False):
236
246
  else:
237
247
  log( f'Not changing {name}={v!r} to {value!r}')
238
248
  set_if_unset( 'CIBW_BUILD_VERBOSITY', '3')
239
- set_if_unset( 'CIBW_SKIP', '"pp* *i686 *-musllinux_* cp36* cp37*"')
249
+ # We exclude pp* because of `fitz_wrap.obj : error LNK2001: unresolved
250
+ # external symbol PyUnicode_DecodeRawUnicodeEscape`.
251
+ # 2024-06-05: musllinux on aarch64 fails because libclang cannot find
252
+ # libclang.so.
253
+ set_if_unset( 'CIBW_SKIP', 'pp* *i686 cp36* cp37* *musllinux*aarch64*')
240
254
 
241
255
  def make_string(*items):
242
256
  ret = list()
@@ -315,6 +329,10 @@ def build( platform_=None, valgrind=False):
315
329
  env_set('PYMUPDF_SETUP_MUPDF_BUILD', inputs_PYMUPDF_SETUP_MUPDF_BUILD, pass_=True)
316
330
  env_set('PYMUPDF_SETUP_MUPDF_TGZ', '', pass_=True) # Don't put mupdf in sdist.
317
331
 
332
+ if inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE not in ('-', None):
333
+ log(f'Setting PYMUPDF_SETUP_MUPDF_BUILD_TYPE to {inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE!r}.')
334
+ env_set('PYMUPDF_SETUP_MUPDF_BUILD_TYPE', inputs_PYMUPDF_SETUP_MUPDF_BUILD_TYPE, pass_=True)
335
+
318
336
  def set_cibuild_test():
319
337
  log( f'set_cibuild_test(): {inputs_skeleton=}')
320
338
  valgrind_text = ''
@@ -440,7 +458,7 @@ def cpu_bits():
440
458
  #
441
459
  venv_name = f'venv-pymupdf-{platform.python_version()}-{cpu_bits()}'
442
460
 
443
- def venv( command=None, packages=None, quick=False):
461
+ def venv( command=None, packages=None, quick=False, system_site_packages=False):
444
462
  '''
445
463
  Runs remaining args, or the specified command if present, in a venv.
446
464
 
@@ -454,16 +472,17 @@ def venv( command=None, packages=None, quick=False):
454
472
  install Python packages in it.
455
473
  '''
456
474
  command2 = ''
457
- ssp = ''
458
475
  if platform.system() == 'OpenBSD':
459
476
  # libclang not available from pypi.org, but system py3-llvm package
460
477
  # works. `pip install` should be run with --no-build-isolation and
461
478
  # explicit `pip install swig setuptools psutil`.
462
- ssp = ' --system-site-packages'
479
+ system_site_packages = True
480
+ #ssp = ' --system-site-packages'
463
481
  log(f'OpenBSD: libclang not available from pypi.org.')
464
482
  log(f'OpenBSD: system package `py3-llvm` must be installed.')
465
483
  log(f'OpenBSD: creating venv with --system-site-packages.')
466
484
  log(f'OpenBSD: `pip install .../PyMuPDF` must be preceded by install of swig etc.')
485
+ ssp = ' --system-site-packages' if system_site_packages else ''
467
486
  if quick and os.path.isdir(venv_name):
468
487
  log(f'{quick=}: Not creating venv because directory already exists: {venv_name}')
469
488
  command2 += 'true'
@@ -544,8 +563,11 @@ def pyodide_setup(clean=False):
544
563
  # Clone emsdk.
545
564
  #
546
565
  dir_emsdk = 'emsdk'
547
- if clean and os.path.exists(dir_emsdk):
548
- shutil.rmtree( dir_emsdk, ignore_errors=1)
566
+ if clean:
567
+ shutil.rmtree(dir_emsdk, ignore_errors=1)
568
+ # 2024-06-25: old `.pyodide-xbuildenv` directory was breaking build, so
569
+ # important to remove it here.
570
+ shutil.rmtree('.pyodide-xbuildenv', ignore_errors=1)
549
571
  if not os.path.exists(dir_emsdk):
550
572
  command += f' && echo "### cloning emsdk.git"'
551
573
  command += f' && git clone https://github.com/emscripten-core/emsdk.git {dir_emsdk}'
@@ -3,8 +3,9 @@
3
3
  '''
4
4
  Test for Linux system install of MuPDF and PyMuPDF.
5
5
 
6
- We build and install MuPDF and PyMuPDF into a root directory, then run
7
- PyMuPDF's pytest tests with LD_PRELOAD_PATH and PYTHONPATH set.
6
+ We build and install MuPDF and PyMuPDF into a root directory, then use
7
+ scripts/test.py to run PyMuPDF's pytest tests with LD_PRELOAD_PATH and
8
+ PYTHONPATH set.
8
9
 
9
10
  PyMuPDF itself is installed using `python -m install` with a wheel created with
10
11
  `pip wheel`.
@@ -21,6 +22,8 @@ Args:
21
22
 
22
23
  --mupdf-dir <mupdf_dir>
23
24
  Path of MuPDF checkout; default is 'mupdf'.
25
+ --mupdf-do 0|1
26
+ Whether to build and install mupdf.
24
27
  --mupdf-git <git_args>
25
28
  Get or update `mupdf_dir` using git. If `mupdf_dir` already
26
29
  exists we run `git pull` in it; otherwise we run `git
@@ -43,6 +46,8 @@ Args:
43
46
  Directory within `root`; default is `/usr/local`. Must start with `/`.
44
47
  --pymupdf-dir <pymupdf_dir>
45
48
  Path of PyMuPDF checkout; default is 'PyMuPDF'.
49
+ --pymupdf-do 0|1
50
+ Whether to build and install pymupdf.
46
51
  --root <root>
47
52
  Root of install directory; default is `/`.
48
53
  --tesseract5 0|1
@@ -57,15 +62,14 @@ Args:
57
62
  If 1 (the default), we use `python -m installer` to install PyMuPDF
58
63
  from a generated wheel. [Otherwise we use `pip install`, which refuses
59
64
  to do a system install with `--root /`, referencing PEP-668.]
60
- -m 0|1
61
- If 1 (the default) we build and install MuPDF, otherwise we just show
62
- what command we would have run.
63
- -p 0|1
64
- If 1 (the default) we build and install PyMuPDF, otherwise we just show
65
- what command we would have run.
66
- -t 0|1
67
- If 1 (the default) we run PyMuPDF's pytest tests, otherwise we just
68
- show what command we would have run.
65
+ -i <implementations>
66
+ Passed through to scripts/test.py.
67
+ -f <test-fitz>
68
+ Passed through to scripts/test.py.
69
+ -p <pytest-options>
70
+ Passed through to scripts/test.py.
71
+ -t <names>
72
+ Passed through to scripts/test.py.
69
73
 
70
74
  To only show what commands would be run, but not actually run them, specify `-m
71
75
  0 -p 0 -t 0`.
@@ -75,6 +79,7 @@ import glob
75
79
  import multiprocessing
76
80
  import os
77
81
  import platform
82
+ import shlex
78
83
  import subprocess
79
84
  import sys
80
85
  import sysconfig
@@ -117,19 +122,23 @@ def main():
117
122
  # Set default behaviour.
118
123
  #
119
124
  use_installer = True
120
- mupdf = True
125
+ mupdf_do = True
121
126
  mupdf_dir = 'mupdf'
122
127
  mupdf_git = None
123
128
  mupdf_so_mode = None
124
129
  packages = True
125
130
  prefix = '/usr/local'
126
- pymupdf = True
131
+ pymupdf_do = True
127
132
  pymupdf_dir = os.path.abspath( f'{__file__}/../..')
128
133
  root = 'sysinstall_test'
129
134
  tesseract5 = True
130
- test = True
135
+ pytest_args = None
136
+ pytest_do = True
137
+ pytest_name = None
131
138
  test_venv = 'venv-pymupdf-sysinstall-test'
132
139
  pip = 'venv'
140
+ test_fitz = None
141
+ test_implementations = None
133
142
 
134
143
  # Parse command-line.
135
144
  #
@@ -142,20 +151,24 @@ def main():
142
151
  if arg in ('-h', '--help'):
143
152
  print(__doc__)
144
153
  return
154
+ elif arg == '--mupdf-do': mupdf_do = int(next(args))
145
155
  elif arg == '--mupdf-dir': mupdf_dir = next(args)
146
156
  elif arg == '--mupdf-git': mupdf_git = next(args)
147
157
  elif arg == '--mupdf-so-mode': mupdf_so_mode = next(args)
148
158
  elif arg == '--packages': packages = int(next(args))
149
159
  elif arg == '--prefix': prefix = next(args)
160
+ elif arg == '--pymupdf-do': pymupdf_do = int(next(args))
150
161
  elif arg == '--pymupdf-dir': pymupdf_dir = next(args)
151
162
  elif arg == '--root': root = next(args)
152
163
  elif arg == '--tesseract5': tesseract5 = int(next(args))
164
+ elif arg == '--pytest-do': pytest_do = int(next(args))
153
165
  elif arg == '--test-venv': test_venv = next(args)
154
166
  elif arg == '--use-installer': use_installer = int(next(args))
155
167
  elif arg == '--pip': pip = next(args)
156
- elif arg == '-m': mupdf = int(next(args))
157
- elif arg == '-p': pymupdf = int(next(args))
158
- elif arg == '-t': test = int(next(args))
168
+ elif arg == '-f': test_fitz = next(args)
169
+ elif arg == '-i': test_implementations = next(args)
170
+ elif arg == '-p': pytest_args = next(args)
171
+ elif arg == '-t': pytest_name = next(args)
159
172
  else:
160
173
  assert 0, f'Unrecognised arg: {arg!r}'
161
174
 
@@ -169,7 +182,7 @@ def main():
169
182
  if root == '/':
170
183
  sudo = f'sudo PATH={os.environ["PATH"]} '
171
184
  def run(command):
172
- return run_command(command, doit=mupdf)
185
+ return run_command(command, doit=mupdf_do)
173
186
  # Get MuPDF from git if specified.
174
187
  #
175
188
  if mupdf_git:
@@ -232,7 +245,7 @@ def main():
232
245
  #
233
246
  print('## Build and install PyMuPDF.')
234
247
  def run(command):
235
- return run_command(command, doit=pymupdf)
248
+ return run_command(command, doit=pymupdf_do)
236
249
  flags_freetype2 = run_command('pkg-config --cflags freetype2', capture_output=1).stdout.strip()
237
250
  compile_flags = f'-I {root_prefix}/include {flags_freetype2}'
238
251
  link_flags = f'-L {root_prefix}/lib'
@@ -316,7 +329,7 @@ def main():
316
329
  #
317
330
  print('## Run PyMuPDF pytest tests.')
318
331
  def run(command):
319
- return run_command(command, doit=test)
332
+ return run_command(command, doit=pytest_do)
320
333
  import gh_release
321
334
  if pip == 'venv':
322
335
  # Create venv.
@@ -342,9 +355,32 @@ def main():
342
355
  run(f'ls -l {root_prefix}/bin/')
343
356
  # 2024-03-20: Not sure whether/where `pymupdf` binary is installed, so we
344
357
  # disable the test_cli* tests.
345
- excluded_tests = 'test_color_count test_3050 test_cli test_cli_out test_pylint test_textbox3'.split()
346
- excluded_tests = ' and not '.join(excluded_tests)
347
- command += f' {pymupdf_dir}/scripts/test.py -p "-k \'not {excluded_tests}\'" -v 0 test'
358
+ command += f' {pymupdf_dir}/scripts/test.py'
359
+ command += f' -v 0'
360
+ if pytest_name is None:
361
+ excluded_tests = (
362
+ 'test_color_count',
363
+ 'test_3050',
364
+ 'test_cli',
365
+ 'test_cli_out',
366
+ 'test_pylint',
367
+ 'test_textbox3',
368
+ 'test_3493',
369
+ )
370
+ excluded_tests = ' and not '.join(excluded_tests)
371
+ if not pytest_args:
372
+ pytest_args = ''
373
+ pytest_args += f' -k \'not {excluded_tests}\''
374
+ else:
375
+ command += f' -t {pytest_name}'
376
+ if test_fitz:
377
+ command += f' -f {test_fitz}'
378
+ if test_implementations:
379
+ command += f' -i {test_implementations}'
380
+ if pytest_args:
381
+ command += f' -p {shlex.quote(pytest_args)}'
382
+ if pytest_do:
383
+ command += ' test'
348
384
  run(command)
349
385
 
350
386
 
@@ -54,6 +54,8 @@ Options:
54
54
  'r' - rebased.
55
55
  'R' - rebased without optimisations.
56
56
  Default is 'rR'. Also see `PyMuPDF:tests/run_compound.py`.
57
+ -k <expression>
58
+ Passed straight through to pytest's `-k`.
57
59
  -m <location> | --mupdf <location>
58
60
  Location of local mupdf/ directory or 'git:...' to be used
59
61
  when building PyMuPDF. [This sets environment variable
@@ -83,6 +85,8 @@ Options:
83
85
  Whether to rebuild mupdf when we build PyMuPDF. Default is 1.
84
86
  --gdb 0|1
85
87
  Run tests under gdb.
88
+ --system-site-packages 0|1
89
+ If 1, use `--system-site-packages` when creating venv.
86
90
  --timeout <seconds>
87
91
  Sets timeout when running tests.
88
92
  --valgrind 0|1
@@ -136,6 +140,8 @@ def main(argv):
136
140
  venv = 2
137
141
  pytest_options = None
138
142
  timeout = None
143
+ pytest_k = None
144
+ system_site_packages = False
139
145
 
140
146
  options = os.environ.get('PYMUDF_SCRIPTS_TEST_options', '')
141
147
  options = shlex.split(options)
@@ -169,8 +175,12 @@ def main(argv):
169
175
  assert os.path.isdir(mupdf), f'Not a directory: {mupdf=}.'
170
176
  mupdf = os.path.abspath(mupdf)
171
177
  os.environ['PYMUPDF_SETUP_MUPDF_BUILD'] = mupdf
178
+ elif arg == '-k':
179
+ pytest_k = next(args)
172
180
  elif arg == '-p':
173
181
  pytest_options = next(args)
182
+ elif arg == '--system-site-packages':
183
+ system_site_packages = int(next(args))
174
184
  elif arg == '-t':
175
185
  test_names += next(args).split(',')
176
186
  elif arg == '--timeout':
@@ -206,7 +216,11 @@ def main(argv):
206
216
  if venv and sys.prefix == sys.base_prefix:
207
217
  # We are not running in a venv.
208
218
  log(f'Re-running in venv {gh_release.venv_name!r}.')
209
- gh_release.venv( ['python'] + argv, quick=venv_quick)
219
+ gh_release.venv(
220
+ ['python'] + argv,
221
+ quick=venv_quick,
222
+ system_site_packages=system_site_packages,
223
+ )
210
224
  return
211
225
 
212
226
  def do_build():
@@ -227,6 +241,7 @@ def main(argv):
227
241
  timeout=timeout,
228
242
  gdb=gdb,
229
243
  test_fitz=test_fitz,
244
+ pytest_k=pytest_k,
230
245
  )
231
246
 
232
247
  for command in commands:
@@ -360,6 +375,7 @@ def test(
360
375
  timeout=None,
361
376
  gdb=False,
362
377
  test_fitz=True,
378
+ pytest_k=None
363
379
  ):
364
380
  '''
365
381
  Args:
@@ -384,6 +400,8 @@ def test(
384
400
  pytest_options = '-s -vv'
385
401
  else:
386
402
  pytest_options = ''
403
+ if pytest_k:
404
+ pytest_options += f' -k {shlex.quote(pytest_k)}'
387
405
  pytest_arg = ''
388
406
  if test_names:
389
407
  for test_name in test_names:
@@ -87,6 +87,9 @@ Environmental variables:
87
87
  Otherwise:
88
88
  Location of mupdf directory.
89
89
 
90
+ PYMUPDF_SETUP_MUPDF_BSYMBOLIC
91
+ If '0' we do not link libmupdf.so with -Bsymbolic.
92
+
90
93
  PYMUPDF_SETUP_MUPDF_TESSERACT
91
94
  If '0' we build MuPDF without Tesseract.
92
95
 
@@ -139,16 +142,6 @@ Environmental variables:
139
142
  WDEV_VS_GRADE
140
143
  If set, we use as Visual Studio grade, for example 'Community' or
141
144
  'Professional' or 'Enterprise'.
142
-
143
- Known build failures:
144
- Linux:
145
- *musllinux*.
146
- Windows:
147
- pp*:
148
- fitz_wrap.obj : error LNK2001: unresolved external symbol PyUnicode_DecodeRawUnicodeEscape
149
-
150
- When using cibuildwheel, one can avoid building these failing wheels with:
151
- CIBW_SKIP='*musllinux* pp*'
152
145
  '''
153
146
 
154
147
  import glob
@@ -157,6 +150,7 @@ import os
157
150
  import textwrap
158
151
  import time
159
152
  import platform
153
+ import re
160
154
  import shlex
161
155
  import shutil
162
156
  import stat
@@ -386,7 +380,7 @@ def get_mupdf_internal(out, location=None, sha=None, local_tgz=None):
386
380
  log(f'get_mupdf_internal(): {out=} {location=} {sha=}')
387
381
  assert out in ('dir', 'tgz')
388
382
  if location is None:
389
- location = 'https://mupdf.com/downloads/archive/mupdf-1.24.2-source.tar.gz'
383
+ location = 'https://mupdf.com/downloads/archive/mupdf-1.24.4-source.tar.gz'
390
384
  #location = 'git:--branch master https://github.com/ArtifexSoftware/mupdf.git'
391
385
 
392
386
  if location == '':
@@ -788,6 +782,14 @@ def build_mupdf_unix( mupdf_local, env, build_type):
788
782
  log(f'PYMUPDF_SETUP_MUPDF_TESSERACT=0 so building mupdf without tesseract.')
789
783
  else:
790
784
  build_prefix += 'tesseract-'
785
+ mupdf_version_tuple = get_mupdf_version(mupdf_local)
786
+ if (
787
+ linux
788
+ and os.environ.get('PYMUPDF_SETUP_MUPDF_BSYMBOLIC', '1') == '1'
789
+ and mupdf_version_tuple >= (1, 24, 3)
790
+ ):
791
+ log(f'Appending `bsymbolic-` to MuPDF build path.')
792
+ build_prefix += 'bsymbolic-'
791
793
  unix_build_dir = f'{mupdf_local}/build/{build_prefix}{build_type}'
792
794
  # We need MuPDF's Python bindings, so we build MuPDF with
793
795
  # `mupdf/scripts/mupdfwrap.py` instead of running `make`.
@@ -813,6 +815,19 @@ def build_mupdf_unix( mupdf_local, env, build_type):
813
815
  return unix_build_dir
814
816
 
815
817
 
818
+ def get_mupdf_version(mupdf_dir):
819
+ path = f'{mupdf_dir}/include/mupdf/fitz/version.h'
820
+ with open(path) as f:
821
+ text = f.read()
822
+ v0 = re.search('#define FZ_VERSION_MAJOR ([0-9]+)', text)
823
+ v1 = re.search('#define FZ_VERSION_MINOR ([0-9]+)', text)
824
+ v2 = re.search('#define FZ_VERSION_PATCH ([0-9]+)', text)
825
+ assert v0 and v1 and v2, f'Cannot find MuPDF version numers in {path=}.'
826
+ v0 = int(v0.group(1))
827
+ v1 = int(v1.group(1))
828
+ v2 = int(v2.group(1))
829
+ return v0, v1, v2
830
+
816
831
  def _fs_update(text, path):
817
832
  try:
818
833
  with open( path) as f:
@@ -1113,8 +1128,8 @@ classifier = [
1113
1128
  # We generate different wheels depending on g_flavour.
1114
1129
  #
1115
1130
 
1116
- version = '1.24.5'
1117
- version_b = '1.24.3'
1131
+ version = '1.24.7'
1132
+ version_b = '1.24.6'
1118
1133
 
1119
1134
  if os.path.exists(f'{g_root}/{g_pymupdfb_sdist_marker}'):
1120
1135
 
@@ -1211,6 +1226,13 @@ else:
1211
1226
  Adds to pyproject.toml:[build-system]:requires, allowing programmatic
1212
1227
  control over what packages we require.
1213
1228
  '''
1229
+ def platform_release_tuple():
1230
+ r = platform.release()
1231
+ r = r.split('.')
1232
+ r = tuple(int(i) for i in r)
1233
+ log(f'platform_release_tuple() returning {r=}.')
1234
+ return r
1235
+
1214
1236
  ret = list()
1215
1237
  ret.append('setuptools')
1216
1238
  libclang = os.environ.get('PYMUPDF_SETUP_LIBCLANG')
@@ -1222,6 +1244,9 @@ else:
1222
1244
  elif darwin and platform.machine() == 'arm64':
1223
1245
  print(f'MacOS/arm64: forcing use of libclang 16.0.6 because 18.1.1 known to fail with `clang.cindex.TranslationUnitLoadError: Error parsing translation unit.`')
1224
1246
  ret.append('libclang==16.0.6')
1247
+ elif darwin and platform_release_tuple() < (18,):
1248
+ # There are still of ptoblems when building on old macos.
1249
+ ret.append('libclang==14.0.6')
1225
1250
  else:
1226
1251
  ret.append('libclang')
1227
1252
  if msys2: