PyMuPDF 1.23.26__tar.gz → 1.24.1__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 (180) hide show
  1. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/PKG-INFO +1 -1
  2. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/READMErb.md +1 -1
  3. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/changes.txt +60 -0
  4. PyMuPDF-1.24.1/pyproject.toml +8 -0
  5. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/scripts/gh_release.py +25 -11
  6. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/scripts/sysinstall.py +9 -7
  7. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/scripts/test.py +33 -14
  8. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/setup.py +40 -11
  9. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src/__init__.py +272 -206
  10. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src/__main__.py +99 -95
  11. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src/extra.i +24 -413
  12. PyMuPDF-1.24.1/src/fitz.py +2 -0
  13. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src/table.py +58 -51
  14. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src/utils.py +52 -52
  15. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/__init__.py +3 -14
  16. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-devices.i +21 -1
  17. PyMuPDF-1.24.1/src_classic/version.i +7 -0
  18. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/full_toc.txt +11 -11
  19. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/symbols.txt +37 -22
  20. PyMuPDF-1.24.1/tests/resources/test-3207.pdf +0 -0
  21. PyMuPDF-1.24.1/tests/resources/test-707448.pdf +2837 -2
  22. PyMuPDF-1.24.1/tests/resources/test-707673.pdf +0 -0
  23. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_2548.py +1 -1
  24. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_2791.py +3 -0
  25. PyMuPDF-1.24.1/tests/test_707448.py +66 -0
  26. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_annots.py +16 -1
  27. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_drawings.py +79 -49
  28. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_general.py +256 -0
  29. PyMuPDF-1.24.1/tests/test_metadata.py +43 -0
  30. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_named_links.py +46 -0
  31. PyMuPDF-1.24.1/tests/test_objectstreams.py +83 -0
  32. PyMuPDF-1.24.1/tests/test_pylint.py +130 -0
  33. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_tables.py +34 -5
  34. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_toc.py +14 -9
  35. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_widgets.py +9 -5
  36. PyMuPDF-1.23.26/pyproject.toml +0 -7
  37. PyMuPDF-1.23.26/src/fitz.py +0 -1
  38. PyMuPDF-1.23.26/src_classic/version.i +0 -7
  39. PyMuPDF-1.23.26/tests/resources/full_toc2.txt +0 -48
  40. PyMuPDF-1.23.26/tests/test_metadata.py +0 -26
  41. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/COPYING +0 -0
  42. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/MANIFEST.in +0 -0
  43. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/README.md +0 -0
  44. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/pipcl.py +0 -0
  45. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/pytest.ini +0 -0
  46. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/__main__.py +0 -0
  47. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/_config.h +0 -0
  48. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/fitz_old.i +0 -0
  49. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-annot.i +0 -0
  50. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-convert.i +0 -0
  51. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-defines.i +0 -0
  52. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-fields.i +0 -0
  53. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-fileobj.i +0 -0
  54. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-geo-c.i +0 -0
  55. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-geo-py.i +0 -0
  56. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-globals.i +0 -0
  57. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-other.i +0 -0
  58. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-pdfinfo.i +0 -0
  59. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-pixmap.i +0 -0
  60. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-portfolio.i +0 -0
  61. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-python.i +0 -0
  62. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-select.i +0 -0
  63. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-stext.i +0 -0
  64. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/helper-xobject.i +0 -0
  65. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/src_classic/utils.py +0 -0
  66. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/README.md +0 -0
  67. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/001003ED.pdf +0 -0
  68. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/1.pdf +0 -0
  69. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/2.pdf +0 -0
  70. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/2201.00069.pdf +0 -0
  71. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/3.pdf +0 -0
  72. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/4.pdf +0 -0
  73. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/Bezier.epub +0 -0
  74. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/PragmaticaC.otf +0 -0
  75. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/battery-file-22.pdf +0 -0
  76. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/bug1945.pdf +0 -0
  77. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/bug1971.pdf +0 -0
  78. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/chinese-tables.pdf +0 -0
  79. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/chinese-tables.pickle +0 -0
  80. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/circular-toc.pdf +0 -0
  81. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/cython.pdf +0 -0
  82. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/cython.pickle +0 -0
  83. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/github_sample.pdf +0 -0
  84. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/has-bad-fonts.pdf +0 -0
  85. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/image-file1.pdf +0 -0
  86. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/img-transparent.png +0 -0
  87. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/joined.pdf +0 -0
  88. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/metadata.txt +0 -0
  89. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/mupdf_explored.pdf +0 -0
  90. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/nur-ruhig.jpg +0 -0
  91. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/quad-calc-0.pdf +0 -0
  92. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/simple_toc.txt +0 -0
  93. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/small-table.pdf +0 -0
  94. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/strict-yes-no.pdf +0 -0
  95. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/symbol-list.pdf +0 -0
  96. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test-2333.pdf +0 -0
  97. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test-2462.pdf +0 -0
  98. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test-3143.pdf +0 -0
  99. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test-3150.pdf +0 -0
  100. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test2093.pdf +0 -0
  101. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test2182.pdf +0 -0
  102. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test2238.pdf +0 -0
  103. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_1645_expected.pdf +0 -0
  104. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_1645_expected_1.22.pdf +0 -0
  105. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_1645_expected_1.24.pdf +0 -0
  106. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_1824.pdf +0 -0
  107. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2108.pdf +0 -0
  108. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2270.pdf +0 -0
  109. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2533.pdf +0 -0
  110. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2548.pdf +0 -0
  111. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2553-2.pdf +0 -0
  112. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2553.pdf +0 -0
  113. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2596.pdf +0 -0
  114. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2608_expected +0 -0
  115. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2634.pdf +0 -0
  116. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2635.pdf +0 -0
  117. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2645_1.pdf +0 -0
  118. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2645_2.pdf +0 -0
  119. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2645_3.pdf +0 -0
  120. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2710.pdf +0 -0
  121. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2730.pdf +0 -0
  122. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2742.pdf +0 -0
  123. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2788.pdf +0 -0
  124. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2791_content.pdf +0 -0
  125. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2791_coverpage.pdf +0 -0
  126. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2861.pdf +0 -0
  127. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2871.pdf +0 -0
  128. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2885.pdf +0 -0
  129. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2904.pdf +0 -0
  130. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2907.pdf +0 -0
  131. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2954.pdf +0 -0
  132. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2957_1.pdf +0 -0
  133. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2957_2.pdf +0 -0
  134. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2969.pdf +0 -0
  135. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_2979.pdf +0 -0
  136. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_3058.pdf +0 -0
  137. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_3062.pdf +0 -0
  138. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_3070.pdf +0 -0
  139. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_3072.pdf +0 -0
  140. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_3087.pdf +0 -0
  141. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_3179.pdf +0 -0
  142. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_3186.pdf +0 -0
  143. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_3197.pdf +0 -0
  144. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_annot_file_info.pdf +0 -0
  145. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/test_delete_image.pdf +0 -0
  146. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/type3font.pdf +0 -0
  147. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/v110-changes.pdf +0 -0
  148. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/resources/widgettest.pdf +0 -0
  149. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/run_compound.py +0 -0
  150. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_2634.py +0 -0
  151. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_2904.py +0 -0
  152. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_2907.py +0 -0
  153. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_badfonts.py +0 -0
  154. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_crypting.py +0 -0
  155. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_docs_samples.py +0 -0
  156. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_embeddedfiles.py +0 -0
  157. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_extractimage.py +0 -0
  158. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_flake8.py +0 -0
  159. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_font.py +0 -0
  160. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_geometry.py +0 -0
  161. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_imagebbox.py +0 -0
  162. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_insertimage.py +0 -0
  163. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_insertpdf.py +0 -0
  164. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_linequad.py +0 -0
  165. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_nonpdf.py +0 -0
  166. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_object_manipulation.py +0 -0
  167. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_optional_content.py +0 -0
  168. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_page_links.py +0 -0
  169. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_pagedelete.py +0 -0
  170. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_pagelabels.py +0 -0
  171. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_pixmap.py +0 -0
  172. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_showpdfpage.py +0 -0
  173. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_story.py +0 -0
  174. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_tesseract.py +0 -0
  175. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_textbox.py +0 -0
  176. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_textextract.py +0 -0
  177. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_textsearch.py +0 -0
  178. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/tests/test_word_delimiters.py +0 -0
  179. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/valgrind.supp +0 -0
  180. {PyMuPDF-1.23.26 → PyMuPDF-1.24.1}/wdev.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyMuPDF
3
- Version: 1.23.26
3
+ Version: 1.24.1
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.23.22
1
+ # PyMuPDF 1.24.1
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,66 @@ Change Log
2
2
  ==========
3
3
 
4
4
 
5
+ **Changes in version 1.24.1 (2024-04-02)**
6
+
7
+ * Fixed issues:
8
+
9
+ * **Fixed** `3278 <https://github.com/pymupdf/PyMuPDF/issues/3278>`_: apply_redactions moves some unredacted text
10
+ * **Fixed** `3301 <https://github.com/pymupdf/PyMuPDF/issues/3301>`_: Be more permissive when classifying links as kind LINK_URI
11
+ * **Fixed** `3306 <https://github.com/pymupdf/PyMuPDF/issues/3306>`_: Text containing capital 'ET' not appearing as annotation
12
+
13
+ * Other:
14
+
15
+ * Use MuPDF-1.24.1.
16
+ * Support ObjStm Compression.
17
+ Methods `Document.save()`, `Document.ez_save()` and `Document.write()`
18
+ now support new parameters `use_objstm`, compression_effort` and
19
+ `preserve_metadata`.
20
+
21
+
22
+ **Changes in version 1.24.0 (2024-03-21)**
23
+
24
+ * Fixed issues:
25
+
26
+ * **Fixed** `3281 <https://github.com/pymupdf/PyMuPDF/issues/3281>`_: Preparing metadata (pyproject.toml) did not run successfully
27
+ * **Fixed** `3279 <https://github.com/pymupdf/PyMuPDF/issues/3279>`_: PyMuPDF no longer builds in Alpine Linux
28
+ * **Fixed** `3257 <https://github.com/pymupdf/PyMuPDF/issues/3257>`_: apply_redactions() deleting text outside of annoted box
29
+ * **Fixed** `3216 <https://github.com/pymupdf/PyMuPDF/issues/3216>`_: AttributeError: 'Annot' object has no attribute '__del__'
30
+ * **Fixed** `3207 <https://github.com/pymupdf/PyMuPDF/issues/3207>`_: get_drawings's items is missing line from h path operator
31
+ * **Fixed** `3201 <https://github.com/pymupdf/PyMuPDF/issues/3201>`_: Memory leaks when merging PDFs
32
+ * **Fixed** `3197 <https://github.com/pymupdf/PyMuPDF/issues/3197>`_: page.get_text() returns hexadecimal text for some characters
33
+ * **Fixed** `3196 <https://github.com/pymupdf/PyMuPDF/issues/3196>`_: Remove text not working in 1.23.25 version vs 1.20.2
34
+ * **Fixed** `3172 <https://github.com/pymupdf/PyMuPDF/issues/3172>`_: PDF's 45º lines dissapearing in png conversion
35
+ * **Fixed** `3135 <https://github.com/pymupdf/PyMuPDF/issues/3135>`_: Do not log warnings to stdout
36
+ * **Fixed** `3125 <https://github.com/pymupdf/PyMuPDF/issues/3125>`_: get_pixmap method stuck on one page and runs forever
37
+ * **Fixed** `2964 <https://github.com/pymupdf/PyMuPDF/issues/2964>`_: There is an issue with the image generated by the page.get_pixmap() function
38
+
39
+ * Other:
40
+
41
+ * Use MuPDF-1.24.0.
42
+ * Add support for redacting vector graphics.
43
+ * Several fixes for table module
44
+
45
+ * Add new method for outputting the table as a markdown string.
46
+
47
+ * Address errors in computing the table header object:
48
+
49
+ We now allow None as the cell value, because this will be resolved where
50
+ needed (e.g. in the pandas DataFrame).
51
+
52
+ We previously tried to enforce rect-like tuples in all header cell
53
+ bboxes, however this fails for tables with all-None columns. This fix
54
+ enables this and constructs an empty string in the corresponding cell
55
+ string.
56
+
57
+ We now correctly include start / stop points of lines in the bbox of the
58
+ clustered graphic. We previously joined the line's rectangle - which had
59
+ no effect because this is always empty.
60
+
61
+ * Improved exception text if we fail to open document.
62
+ * Fixed build with new libclang 18.
63
+
64
+
5
65
  **Changes in version 1.23.26 (2024-02-29)**
6
66
 
7
67
  * Fixed issues:
@@ -0,0 +1,8 @@
1
+ [build-system]
2
+ # We define required packages in setup.py:get_requires_for_build_wheel().
3
+ requires = []
4
+
5
+ # See pep-517.
6
+ #
7
+ build-backend = "setup"
8
+ backend-path = ["."]
@@ -259,18 +259,29 @@ def build( platform_=None, valgrind=False):
259
259
  log(f'Not running cibuildwheel because CIBW_ARCHS_MACOS is empty string.')
260
260
  return
261
261
 
262
- def env_set(name, value, pass_=False):
263
- assert isinstance( value, str)
264
- if not name.startswith('CIBW'):
265
- assert pass_, f'{name=} {value=}'
266
- env_extra[ name] = value
267
- if pass_ and platform.system() == 'Linux':
262
+ def env_pass(name):
263
+ '''
264
+ Adds `name` to CIBW_ENVIRONMENT_PASS_LINUX if required to be available
265
+ when building wheel with cibuildwheel.
266
+ '''
267
+ if platform.system() == 'Linux':
268
268
  v = env_extra.get('CIBW_ENVIRONMENT_PASS_LINUX', '')
269
269
  if v:
270
270
  v += ' '
271
271
  v += name
272
272
  env_extra['CIBW_ENVIRONMENT_PASS_LINUX'] = v
273
+
274
+ def env_set(name, value, pass_=False):
275
+ assert isinstance( value, str)
276
+ if not name.startswith('CIBW'):
277
+ assert pass_, f'{name=} {value=}'
278
+ env_extra[ name] = value
279
+ if pass_:
280
+ env_pass(name)
273
281
 
282
+ if os.environ.get('PYMUPDF_SETUP_LIBCLANG'):
283
+ env_pass('PYMUPDF_SETUP_LIBCLANG')
284
+
274
285
  env_set('PYMUPDF_SETUP_IMPLEMENTATIONS', inputs_wheels_implementations, pass_=1)
275
286
  if inputs_skeleton:
276
287
  env_set('PYMUPDF_SETUP_SKELETON', inputs_skeleton, pass_=1)
@@ -640,7 +651,8 @@ def run(command, env_extra=None, check=1, timeout=None):
640
651
  Whether to raise exception if command fails.
641
652
  timeout:
642
653
  If not None, timeout in seconds; passed directory to
643
- subprocess.run().
654
+ subprocess.run(). Note that on MacOS subprocess.run() seems to
655
+ leave processes running if timeout expires.
644
656
  '''
645
657
  env = None
646
658
  if env_extra:
@@ -662,15 +674,17 @@ def platform_tag():
662
674
  assert 0, f'Unrecognised: {platform.system()=}'
663
675
 
664
676
 
665
- # If this has changed, need to update
666
- # .github/workflows/*.yml.
667
- #
668
- test_packages = 'pytest fontTools psutil pymupdf-fonts flake8'
677
+ test_packages = 'pytest fontTools pymupdf-fonts flake8 pylint'
669
678
  if platform.system() == 'Windows' and cpu_bits() == 32:
670
679
  # No pillow wheel available, and doesn't build easily.
671
680
  pass
672
681
  else:
673
682
  test_packages += ' pillow'
683
+ if platform.system().startswith('MSYS_NT-'):
684
+ # psutil not available on msys2.
685
+ pass
686
+ else:
687
+ test_packages += ' psutil'
674
688
 
675
689
 
676
690
  if __name__ == '__main__':
@@ -206,11 +206,7 @@ def main():
206
206
  if pip == 'sudo':
207
207
  print('## Installing Python packages required for building MuPDF and PyMuPDF.')
208
208
  run(f'sudo pip install --upgrade pip')
209
- names = (''
210
- + test_py.get_pyproject_required(os.path.abspath(f'{__file__}/../../pyproject.toml'))
211
- + ' '
212
- + test_py.get_pyproject_required(os.path.abspath(f'{mupdf_dir}/pyproject.toml'))
213
- )
209
+ names = test_py.wrap_get_requires_for_build_wheel(f'{__file__}/../..')
214
210
  run(f'sudo pip install {names}')
215
211
 
216
212
  print('## Build and install MuPDF.')
@@ -272,6 +268,7 @@ def main():
272
268
  # `python -m installer` fails to overwrite existing files.
273
269
  run(f'{sudo}rm -r {p}/site-packages/fitz || true')
274
270
  run(f'{sudo}rm -r {p}/site-packages/PyMuPDF-*.dist-info || true')
271
+ run(f'{sudo}rm -r {root_prefix}/bin/pymupdf || true')
275
272
  if pip == 'venv':
276
273
  run(f'{sudo}{venv_name}/bin/python -m installer --destdir {root} --prefix {prefix} {wheel}')
277
274
  else:
@@ -339,8 +336,13 @@ def main():
339
336
  command = ''
340
337
  if pip == 'venv':
341
338
  command += f'. {test_venv}/bin/activate &&'
342
- command += f' LD_LIBRARY_PATH={root_prefix}/lib PYTHONPATH={pythonpath}'
343
- command += f' pytest -k "not test_color_count and not test_3050" {pymupdf_dir}'
339
+ command += f' LD_LIBRARY_PATH={root_prefix}/lib PYTHONPATH={pythonpath} PATH=$PATH:{root_prefix}/bin'
340
+ run(f'ls -l {root_prefix}/bin/')
341
+ # 2024-03-20: Not sure whether/where `pymupdf` binary is installed, so we
342
+ # disable the test_cli* tests.
343
+ excluded_tests = 'test_color_count test_3050 test_cli test_cli_out test_pylint'.split()
344
+ excluded_tests = ' and not '.join(excluded_tests)
345
+ command += f' pytest -k "not {excluded_tests}" {pymupdf_dir}'
344
346
  run(command)
345
347
 
346
348
 
@@ -13,8 +13,8 @@ Examples:
13
13
  ./PyMuPDF/scripts/test.py --mupdf 'git:https://git.ghostscript.com/mupdf.git' buildtest
14
14
  Build and test with internal checkout of mupdf master.
15
15
 
16
- ./PyMuPDF/scripts/test.py --mupdf 'git:--branch 1.23.x https://github.com/ArtifexSoftware/mupdf.git' buildtest
17
- Build and test using internal checkout of mupdf 1.23.x branch from Github.
16
+ ./PyMuPDF/scripts/test.py --mupdf 'git:--branch 1.24.x https://github.com/ArtifexSoftware/mupdf.git' buildtest
17
+ Build and test using internal checkout of mupdf 1.24.x branch from Github.
18
18
 
19
19
  Usage:
20
20
  scripts/test.py <options> <commands>
@@ -300,12 +300,11 @@ def build(
300
300
  print(f'{build_type=}')
301
301
  print(f'{build_isolation=}')
302
302
 
303
- if platform.system() == 'OpenBSD':
304
- # libclang not available on pypi.org, so we need to force use of system
305
- # package py3-llvm with --no-build-isolation, manually installing other
306
- # required packages.
307
- if build_isolation is None:
308
- build_isolation = False
303
+ if build_isolation is None:
304
+ # On OpenBSD libclang is not available on pypi.org, so we need to force
305
+ # use of system package py3-llvm with --no-build-isolation, manually
306
+ # installing other required packages.
307
+ build_isolation = False if platform.system() == 'OpenBSD' else True
309
308
 
310
309
  if build_isolation:
311
310
  # This is the default on non-OpenBSD.
@@ -314,12 +313,11 @@ def build(
314
313
  # Not using build isolation - i.e. pip will not be using its own clean
315
314
  # venv, so we need to explicitly install required packages. Manually
316
315
  # install required packages from pyproject.toml.
317
- names = get_pyproject_required()
318
- if platform.system() == 'OpenBSD':
319
- # libclang not available. We require system already has py3-llvm
320
- # installed.
321
- log(f'OpenBSD: libclang not available; assuming system package py3-llvm is installed.')
322
- names = names.replace('libclang', '')
316
+ sys.path.insert(0, os.path.abspath(f'{__file__}/../..'))
317
+ import setup
318
+ names = setup.get_requires_for_build_wheel()
319
+ del sys.path[0]
320
+ names = ' '.join(names)
323
321
  if venv_quick:
324
322
  log(f'{venv_quick=}: Not installing packages with pip: {names}')
325
323
  else:
@@ -442,6 +440,27 @@ def get_pyproject_required(ppt=None):
442
440
  else:
443
441
  assert 0, f'Failed to find "requires" line in {ppt}'
444
442
 
443
+ def wrap_get_requires_for_build_wheel(dir_):
444
+ '''
445
+ Returns space-separated list of required
446
+ packages. Looks at `dir_`/pyproject.toml and calls
447
+ `dir_`/setup.py:get_requires_for_build_wheel().
448
+ '''
449
+ dir_abs = os.path.abspath(dir_)
450
+ ret = list()
451
+ ppt = os.path.join(dir_abs, 'pyproject.toml')
452
+ if os.path.exists(ppt):
453
+ ret += get_pyproject_required(ppt)
454
+ if os.path.exists(os.path.join(dir_abs, 'setup.py')):
455
+ sys.path.insert(0, dir_abs)
456
+ try:
457
+ from setup import get_requires_for_build_wheel as foo
458
+ for i in foo():
459
+ ret.append(i)
460
+ finally:
461
+ del sys.path[0]
462
+ return ' '.join(ret)
463
+
445
464
 
446
465
  def log(text):
447
466
  gh_release.log(text, caller=1)
@@ -68,6 +68,9 @@ Environmental variables:
68
68
  Build wheel called `PyMuPDFb` containing only shared libraries
69
69
  that are not specific to a particular Python version - e.g.
70
70
  on Linux this will be `libmupdf.so` and `libmupdfcpp.so`.
71
+
72
+ PYMUPDF_SETUP_LIBCLANG
73
+ For internal testing.
71
74
 
72
75
  PYMUPDF_SETUP_MUPDF_BUILD
73
76
  If set, overrides location of MuPDF when building PyMuPDF:
@@ -202,12 +205,6 @@ assert g_flavour in ('p', 'b', 'pb'), \
202
205
 
203
206
  g_root = os.path.abspath( f'{__file__}/..')
204
207
 
205
- # setuptools seems to require current directory to be PyMuPDF.
206
- #
207
- assert os.path.abspath( os.getcwd()) == g_root, \
208
- f'Current directory must be the PyMuPDF directory'
209
-
210
-
211
208
  def _fs_remove(path):
212
209
  '''
213
210
  Removes file or directory, without raising exception if it doesn't exist.
@@ -384,7 +381,7 @@ def get_mupdf_internal(out, location=None, sha=None, local_tgz=None):
384
381
  log(f'get_mupdf_internal(): {out=} {location=} {sha=}')
385
382
  assert out in ('dir', 'tgz')
386
383
  if location is None:
387
- location = 'https://mupdf.com/downloads/archive/mupdf-1.23.10-source.tar.gz'
384
+ location = 'https://mupdf.com/downloads/archive/mupdf-1.24.1-source.tar.gz'
388
385
  #location = 'git:--branch master https://github.com/ArtifexSoftware/mupdf.git'
389
386
 
390
387
  if location == '':
@@ -498,6 +495,7 @@ openbsd = sys.platform.startswith( 'openbsd')
498
495
  freebsd = sys.platform.startswith( 'freebsd')
499
496
  darwin = sys.platform.startswith( 'darwin')
500
497
  windows = platform.system() == 'Windows' or platform.system().startswith('CYGWIN')
498
+ msys2 = platform.system().startswith('MSYS_NT-')
501
499
  pyodide = os.environ.get('OS') == 'pyodide'
502
500
 
503
501
 
@@ -779,7 +777,13 @@ def build_mupdf_unix( mupdf_local, env, build_type):
779
777
  if build_prefix_extra:
780
778
  build_prefix += f'{build_prefix_extra}-'
781
779
  build_prefix += 'shared-'
782
- if os.environ.get('PYMUPDF_SETUP_MUPDF_TESSERACT') != '0':
780
+ if msys2:
781
+ # Error in mupdf/scripts/tesseract/endianness.h:
782
+ # #error "I don't know what architecture this is!"
783
+ log(f'msys2: building MuPDF without tesseract.')
784
+ elif os.environ.get('PYMUPDF_SETUP_MUPDF_TESSERACT') == '0':
785
+ log(f'PYMUPDF_SETUP_MUPDF_TESSERACT=0 so building mupdf without tesseract.')
786
+ else:
783
787
  build_prefix += 'tesseract-'
784
788
  unix_build_dir = f'{mupdf_local}/build/{build_prefix}{build_type}'
785
789
  # We need MuPDF's Python bindings, so we build MuPDF with
@@ -1094,8 +1098,8 @@ with open( f'{g_root}/READMErb.md', encoding='utf-8') as f:
1094
1098
  # We generate different wheels depending on g_flavour.
1095
1099
  #
1096
1100
 
1097
- version = '1.23.26'
1098
- version_b = '1.23.22'
1101
+ version = '1.24.1'
1102
+ version_b = '1.24.1'
1099
1103
 
1100
1104
  tag_python = None
1101
1105
  requires_dist = None,
@@ -1158,7 +1162,32 @@ p = pipcl.Package(
1158
1162
  build_wheel = p.build_wheel
1159
1163
  build_sdist = p.build_sdist
1160
1164
 
1165
+ def get_requires_for_build_wheel(config_settings=None):
1166
+ '''
1167
+ Adds to pyproject.toml:[build-system]:requires, allowing programmatic
1168
+ control over what packages we require.
1169
+ '''
1170
+ ret = list()
1171
+ ret.append('setuptools')
1172
+ libclang = os.environ.get('PYMUPDF_SETUP_LIBCLANG')
1173
+ if libclang:
1174
+ print(f'Overriding to use {libclang=}.')
1175
+ ret.append(libclang)
1176
+ elif openbsd:
1177
+ print(f'OpenBSD: libclang not available via pip; assuming `pkg_add py3-llvm`.')
1178
+ elif darwin and platform.machine() == 'arm64':
1179
+ 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.`')
1180
+ ret.append('libclang==16.0.6')
1181
+ else:
1182
+ ret.append('libclang')
1183
+ if msys2:
1184
+ print(f'msys2: pip install of swig does not build; assuming `pacman -S swig`.')
1185
+ elif openbsd:
1186
+ print(f'OpenBSD: pip install of swig does not build; assuming `pkg_add swig`.')
1187
+ else:
1188
+ ret.append( 'swig')
1189
+ return ret
1190
+
1161
1191
 
1162
- import sys
1163
1192
  if __name__ == '__main__':
1164
1193
  p.handle_argv(sys.argv)