PyMuPDF 1.23.22__tar.gz → 1.23.24__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 (171) hide show
  1. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/PKG-INFO +1 -1
  2. PyMuPDF-1.23.24/READMErb.md +7 -0
  3. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/changes.txt +39 -0
  4. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/scripts/gh_release.py +3 -2
  5. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/scripts/sysinstall.py +98 -49
  6. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/scripts/test.py +43 -17
  7. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/setup.py +1 -1
  8. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src/__init__.py +168 -290
  9. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src/extra.i +17 -0
  10. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src/table.py +87 -46
  11. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src/utils.py +29 -29
  12. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/fitz_old.i +13 -6
  13. PyMuPDF-1.23.24/src_classic/helper-select.i +71 -0
  14. PyMuPDF-1.23.24/src_classic/version.i +7 -0
  15. PyMuPDF-1.23.24/tests/resources/test-3150.pdf +0 -0
  16. PyMuPDF-1.23.24/tests/resources/test_1645_expected_1.24.pdf +0 -0
  17. PyMuPDF-1.23.24/tests/resources/test_2742.pdf +360 -0
  18. PyMuPDF-1.23.24/tests/resources/test_3179.pdf +0 -0
  19. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_annots.py +16 -1
  20. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_general.py +45 -1
  21. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_geometry.py +4 -0
  22. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_optional_content.py +65 -0
  23. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_pagedelete.py +17 -1
  24. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_pixmap.py +16 -0
  25. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_showpdfpage.py +16 -0
  26. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_tables.py +37 -0
  27. PyMuPDF-1.23.22/READMErb.md +0 -6
  28. PyMuPDF-1.23.22/src_classic/helper-select.i +0 -394
  29. PyMuPDF-1.23.22/src_classic/version.i +0 -7
  30. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/COPYING +0 -0
  31. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/MANIFEST.in +0 -0
  32. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/README.md +0 -0
  33. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/mupdf.tgz +0 -0
  34. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/pipcl.py +0 -0
  35. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/pyproject.toml +0 -0
  36. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/pytest.ini +0 -0
  37. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src/__main__.py +0 -0
  38. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src/fitz.py +0 -0
  39. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/__init__.py +0 -0
  40. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/__main__.py +0 -0
  41. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/_config.h +0 -0
  42. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-annot.i +0 -0
  43. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-convert.i +0 -0
  44. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-defines.i +0 -0
  45. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-devices.i +0 -0
  46. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-fields.i +0 -0
  47. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-fileobj.i +0 -0
  48. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-geo-c.i +0 -0
  49. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-geo-py.i +0 -0
  50. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-globals.i +0 -0
  51. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-other.i +0 -0
  52. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-pdfinfo.i +0 -0
  53. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-pixmap.i +0 -0
  54. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-portfolio.i +0 -0
  55. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-python.i +0 -0
  56. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-stext.i +0 -0
  57. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/helper-xobject.i +0 -0
  58. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/src_classic/utils.py +0 -0
  59. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/README.md +0 -0
  60. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/001003ED.pdf +0 -0
  61. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/1.pdf +0 -0
  62. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/2.pdf +0 -0
  63. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/2201.00069.pdf +0 -0
  64. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/3.pdf +0 -0
  65. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/4.pdf +0 -0
  66. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/Bezier.epub +0 -0
  67. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/PragmaticaC.otf +0 -0
  68. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/bug1945.pdf +0 -0
  69. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/bug1971.pdf +0 -0
  70. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/chinese-tables.pdf +0 -0
  71. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/chinese-tables.pickle +0 -0
  72. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/circular-toc.pdf +0 -0
  73. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/cython.pdf +0 -0
  74. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/cython.pickle +0 -0
  75. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/full_toc.txt +0 -0
  76. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/full_toc2.txt +0 -0
  77. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/github_sample.pdf +0 -0
  78. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/has-bad-fonts.pdf +0 -0
  79. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/image-file1.pdf +0 -0
  80. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/img-transparent.png +0 -0
  81. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/joined.pdf +0 -0
  82. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/metadata.txt +0 -0
  83. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/mupdf_explored.pdf +0 -0
  84. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/nur-ruhig.jpg +0 -0
  85. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/quad-calc-0.pdf +0 -0
  86. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/simple_toc.txt +0 -0
  87. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/small-table.pdf +0 -0
  88. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/strict-yes-no.pdf +0 -0
  89. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/symbol-list.pdf +0 -0
  90. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/symbols.txt +0 -0
  91. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test-2333.pdf +0 -0
  92. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test-2462.pdf +0 -0
  93. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test-3143.pdf +0 -0
  94. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test2093.pdf +0 -0
  95. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test2182.pdf +0 -0
  96. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test2238.pdf +0 -0
  97. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_1645_expected.pdf +0 -0
  98. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_1645_expected_1.22.pdf +0 -0
  99. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_1824.pdf +0 -0
  100. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2108.pdf +0 -0
  101. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2270.pdf +0 -0
  102. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2533.pdf +0 -0
  103. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2548.pdf +0 -0
  104. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2553-2.pdf +0 -0
  105. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2553.pdf +0 -0
  106. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2596.pdf +0 -0
  107. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2608_expected +0 -0
  108. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2634.pdf +0 -0
  109. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2635.pdf +0 -0
  110. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2645_1.pdf +0 -0
  111. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2645_2.pdf +0 -0
  112. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2645_3.pdf +0 -0
  113. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2710.pdf +0 -0
  114. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2730.pdf +0 -0
  115. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2788.pdf +0 -0
  116. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2791_content.pdf +0 -0
  117. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2791_coverpage.pdf +0 -0
  118. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2861.pdf +0 -0
  119. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2871.pdf +0 -0
  120. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2885.pdf +0 -0
  121. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2904.pdf +0 -0
  122. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2907.pdf +0 -0
  123. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2954.pdf +0 -0
  124. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2957_1.pdf +0 -0
  125. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2957_2.pdf +0 -0
  126. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2969.pdf +0 -0
  127. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_2979.pdf +0 -0
  128. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_3058.pdf +0 -0
  129. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_3062.pdf +0 -0
  130. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_3070.pdf +0 -0
  131. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_3072.pdf +0 -0
  132. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_3087.pdf +0 -0
  133. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_annot_file_info.pdf +0 -0
  134. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/test_delete_image.pdf +0 -0
  135. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/type3font.pdf +0 -0
  136. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/v110-changes.pdf +0 -0
  137. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/resources/widgettest.pdf +0 -0
  138. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/run_compound.py +0 -0
  139. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_2548.py +0 -0
  140. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_2634.py +0 -0
  141. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_2791.py +0 -0
  142. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_2904.py +0 -0
  143. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_2907.py +0 -0
  144. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_badfonts.py +0 -0
  145. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_crypting.py +0 -0
  146. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_docs_samples.py +0 -0
  147. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_drawings.py +0 -0
  148. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_embeddedfiles.py +0 -0
  149. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_extractimage.py +0 -0
  150. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_flake8.py +0 -0
  151. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_font.py +0 -0
  152. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_imagebbox.py +0 -0
  153. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_insertimage.py +0 -0
  154. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_insertpdf.py +0 -0
  155. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_linequad.py +0 -0
  156. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_metadata.py +0 -0
  157. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_named_links.py +0 -0
  158. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_nonpdf.py +0 -0
  159. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_object_manipulation.py +0 -0
  160. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_page_links.py +0 -0
  161. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_pagelabels.py +0 -0
  162. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_story.py +0 -0
  163. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_tesseract.py +0 -0
  164. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_textbox.py +0 -0
  165. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_textextract.py +0 -0
  166. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_textsearch.py +0 -0
  167. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_toc.py +0 -0
  168. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_widgets.py +0 -0
  169. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/tests/test_word_delimiters.py +0 -0
  170. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/valgrind.supp +0 -0
  171. {PyMuPDF-1.23.22 → PyMuPDF-1.23.24}/wdev.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyMuPDF
3
- Version: 1.23.22
3
+ Version: 1.23.24
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
@@ -0,0 +1,7 @@
1
+ # PyMuPDF 1.23.22
2
+
3
+ This wheel contains [MuPDF](https://mupdf.readthedocs.io/) shared libraries for
4
+ use by [PyMuPDF](https://pymupdf.readthedocs.io/).
5
+
6
+ This wheel is shared by PyMuPDF wheels that are specific to different Python
7
+ versions, significantly reducing the total size of a release.
@@ -2,6 +2,45 @@ Change Log
2
2
  ==========
3
3
 
4
4
 
5
+ **Changes in version 1.23.24 (2024-02-19)**
6
+
7
+ * Fixed issues:
8
+
9
+ * **Fixed** `3148 <https://github.com/pymupdf/PyMuPDF/issues/3148>`_: Table extraction - vertical text not handled correctly
10
+ * **Fixed** `3179 <https://github.com/pymupdf/PyMuPDF/issues/3179>`_: Table Detection: Incorrect Separation of Vector Graphics Clusters
11
+ * **Fixed** `3180 <https://github.com/pymupdf/PyMuPDF/issues/3180>`_: Cannot show optional content group: AttributeError: module 'fitz.mupdf' has no attribute 'pdf_array_push_drop'
12
+
13
+ * Other:
14
+
15
+ * Be able to test system install using `sudo pip install` instead of a venv.
16
+
17
+
18
+ **Changes in version 1.23.23 (2024-02-18)**
19
+
20
+ * Fixed issues:
21
+
22
+ * **Fixed** `3126 <https://github.com/pymupdf/PyMuPDF/issues/3126>`_: Initialising Archive with a pathlib.Path fails.
23
+ * **Fixed** `3131 <https://github.com/pymupdf/PyMuPDF/issues/3131>`_: Calling the next attribute of an Annot raises a "No attribute .parent" warning
24
+ * **Fixed** `3134 <https://github.com/pymupdf/PyMuPDF/issues/3134>`_: Using an IRect as clip parameter in Page.get_pixmap no longer works since 1.23.9
25
+ * **Fixed** `3140 <https://github.com/pymupdf/PyMuPDF/issues/3140>`_: PDF document stays in use after closing
26
+ * **Fixed** `3150 <https://github.com/pymupdf/PyMuPDF/issues/3150>`_: doc.select() hangs on this doc.
27
+ * **Fixed** `3163 <https://github.com/pymupdf/PyMuPDF/issues/3163>`_: AssertionError on using fitz.IRect
28
+ * **Fixed** `3177 <https://github.com/pymupdf/PyMuPDF/issues/3177>`_: fitz.Pixmap(None, pix) Unrecognised args for constructing Pixmap
29
+
30
+ * Other:
31
+
32
+ *
33
+ Improved `Document.select() by using new MuPDF function
34
+ `pdf_rearrange_pages()`. This is a more complete (and faster)
35
+ implementation of what needs to be done here in that not only pages will
36
+ be rearranged, but also consequential changes will be made to the table
37
+ of contents, links to removed pages and affected entries in the Optional
38
+ Content definitions.
39
+ * `TextWriter.appendv()`: added `small_caps` arg.
40
+ * Fixed some valgrind errors with MuPDF master.
41
+ * Fixed `Document.insert_image()` when build with MuPDF master.
42
+
43
+
5
44
  **Changes in version 1.23.22 (2024-02-12)**
6
45
 
7
46
  * Fixed issues:
@@ -434,6 +434,7 @@ def venv( command=None, packages=None, quick=False):
434
434
  log(f'{quick=}: Not creating venv because directory already exists: {venv_name}')
435
435
  command2 += 'true'
436
436
  else:
437
+ quick = False
437
438
  command2 += f'{sys.executable} -m venv{ssp} {venv_name}'
438
439
  if platform.system() == 'Windows':
439
440
  command2 += f' && {venv_name}\\Scripts\\activate'
@@ -471,7 +472,7 @@ def test( project, package, valgrind):
471
472
  run(
472
473
  f'{sys.executable} {project}/tests/run_compound.py'
473
474
  f' valgrind --suppressions={project}/valgrind.supp --error-exitcode=100 --errors-for-leak-kinds=none --fullpath-after='
474
- f' pytest -s -vv {project}/tests'
475
+ f' pytest {project}/tests'
475
476
  ,
476
477
  env_extra=dict(
477
478
  PYTHONMALLOC='malloc',
@@ -479,7 +480,7 @@ def test( project, package, valgrind):
479
480
  ),
480
481
  )
481
482
  else:
482
- run(f'{sys.executable} {project}/tests/run_compound.py pytest -s {project}/tests')
483
+ run(f'{sys.executable} {project}/tests/run_compound.py pytest {project}/tests')
483
484
 
484
485
 
485
486
  def pyodide_setup(clean=False):
@@ -24,28 +24,39 @@ Args:
24
24
  --mupdf-git <git_args>
25
25
  Get or update `mupdf_dir` using git. If `mupdf_dir` already
26
26
  exists we run `git pull` in it; otherwise we run `git
27
- clone` with `git_args`. For example:
27
+ clone` with `<git_args> <mupdf_dir>`. For example:
28
28
  --mupdf-git "--branch master https://github.com/ArtifexSoftware/mupdf.git"
29
- --pymupdf-dir <pymupdf_dir>
30
- Path of PyMuPDF checkout; default is 'PyMuPDF'.
29
+ --mupdf-so-mode <mode>
30
+ Used with `install -m <mode> ...` when installing MuPDF. For example
31
+ `--mupdf-so-mode 744`.
32
+ --packages 0|1
33
+ If 1 (the default) we install required system packages such as
34
+ `libfreetype-dev`.
35
+ --pip 0|venv|sudo
36
+ Whether/how to install Python packages.
37
+ If '0' we assume required packages are already available.
38
+ If 'sudo' we install required Python packages using `sudo pip install
39
+ ...`.
40
+ If 'venv' (the default) we install Python packages and run installer
41
+ and test commands inside venv's.
31
42
  --prefix:
32
43
  Directory within `root`; default is `/usr/local`. Must start with `/`.
44
+ --pymupdf-dir <pymupdf_dir>
45
+ Path of PyMuPDF checkout; default is 'PyMuPDF'.
33
46
  --root <root>
34
47
  Root of install directory; default is `/`.
35
48
  --tesseract5 0|1
36
49
  If 1 (the default), we force installation of libtesseract-dev version
37
50
  5 (which is not available as a default package in Ubuntu-22.04) from
38
51
  package repository ppa:alex-p/tesseract-ocr-devel.
39
- --test-venv <venv_path>
40
- Run tests in specified venv; the default is a hard-coded venv name. The
41
- venv will be created and required packages installed using `pip`. If
42
- `venv-path` is empty string, we do not create or use a venv, and will
43
- instead attempt to install required packages with `pip` in the current
44
- Python environment.
52
+ --test-venv <test_venv>
53
+ Set the name of the venv in which we run tests (only with `--pip
54
+ venv`); the default is a hard-coded venv name. The venv will be
55
+ created, and required packages installed using `pip`.
45
56
  --use-installer 0|1
46
57
  If 1 (the default), we use `python -m installer` to install PyMuPDF
47
- from a generated wheel. Otherwise we use `pip install`, which refuses
48
- to do a system install with `--root /`, referencing PEP-668.
58
+ from a generated wheel. [Otherwise we use `pip install`, which refuses
59
+ to do a system install with `--root /`, referencing PEP-668.]
49
60
  -m 0|1
50
61
  If 1 (the default) we build and install MuPDF, otherwise we just show
51
62
  what command we would have run.
@@ -61,12 +72,14 @@ To only show what commands would be run, but not actually run them, specify `-m
61
72
  '''
62
73
 
63
74
  import glob
75
+ import multiprocessing
64
76
  import os
65
77
  import platform
66
78
  import subprocess
67
79
  import sys
68
80
  import sysconfig
69
81
 
82
+ import test as test_py
70
83
 
71
84
  # Requirements for a system build and install:
72
85
  #
@@ -107,6 +120,8 @@ def main():
107
120
  mupdf = True
108
121
  mupdf_dir = 'mupdf'
109
122
  mupdf_git = None
123
+ mupdf_so_mode = None
124
+ packages = True
110
125
  prefix = '/usr/local'
111
126
  pymupdf = True
112
127
  pymupdf_dir = os.path.abspath( f'{__file__}/../..')
@@ -114,6 +129,7 @@ def main():
114
129
  tesseract5 = True
115
130
  test = True
116
131
  test_venv = 'venv-pymupdf-sysinstall-test'
132
+ pip = 'venv'
117
133
 
118
134
  # Parse command-line.
119
135
  #
@@ -128,12 +144,15 @@ def main():
128
144
  return
129
145
  elif arg == '--mupdf-dir': mupdf_dir = next(args)
130
146
  elif arg == '--mupdf-git': mupdf_git = next(args)
147
+ elif arg == '--mupdf-so-mode': mupdf_so_mode = next(args)
148
+ elif arg == '--packages': packages = int(next(args))
131
149
  elif arg == '--prefix': prefix = next(args)
132
150
  elif arg == '--pymupdf-dir': pymupdf_dir = next(args)
133
151
  elif arg == '--root': root = next(args)
134
152
  elif arg == '--tesseract5': tesseract5 = int(next(args))
135
153
  elif arg == '--test-venv': test_venv = next(args)
136
154
  elif arg == '--use-installer': use_installer = int(next(args))
155
+ elif arg == '--pip': pip = next(args)
137
156
  elif arg == '-m': mupdf = int(next(args))
138
157
  elif arg == '-p': pymupdf = int(next(args))
139
158
  elif arg == '-t': test = int(next(args))
@@ -141,6 +160,8 @@ def main():
141
160
  assert 0, f'Unrecognised arg: {arg!r}'
142
161
 
143
162
  assert prefix.startswith('/')
163
+ pip_values = ('0', 'sudo', 'venv')
164
+ assert pip in pip_values, f'Unrecognised --pip value {pip!r} should be one of: {pip_values!r}'
144
165
  root = os.path.abspath(root)
145
166
  root_prefix = f'{root}{prefix}'.replace('//', '/')
146
167
 
@@ -161,44 +182,54 @@ def main():
161
182
  print(f'## Clone MuPDF into {mupdf_dir}.')
162
183
  run(f'git clone --recursive --depth 1 --shallow-submodules {mupdf_git} {mupdf_dir}')
163
184
 
164
- # Install required system packages. We assume a Debian package system.
165
- #
166
- print('## Install system packages required by MuPDF.')
167
- run(f'sudo apt update')
168
- run(f'sudo apt install {" ".join(g_sys_packages)}')
169
- # Ubuntu-22.04 has freeglut3-dev, not libglut-dev.
170
- run(f'sudo apt install libglut-dev | sudo apt install freeglut3-dev')
171
- if tesseract5:
172
- print(f'## Force installation of libtesseract-dev version 5.')
173
- # https://stackoverflow.com/questions/76834972/how-can-i-run-pytesseract-python-library-in-ubuntu-22-04
185
+ if packages:
186
+ # Install required system packages. We assume a Debian package system.
174
187
  #
175
- run('sudo apt install -y software-properties-common')
176
- run('sudo add-apt-repository ppa:alex-p/tesseract-ocr-devel')
177
- run('sudo apt update')
178
- run('sudo apt install -y libtesseract-dev')
179
- else:
180
- run('sudo apt install libtesseract-dev')
188
+ print('## Install system packages required by MuPDF.')
189
+ run(f'sudo apt update')
190
+ run(f'sudo apt install {" ".join(g_sys_packages)}')
191
+ # Ubuntu-22.04 has freeglut3-dev, not libglut-dev.
192
+ run(f'sudo apt install libglut-dev | sudo apt install freeglut3-dev')
193
+ if tesseract5:
194
+ print(f'## Force installation of libtesseract-dev version 5.')
195
+ # https://stackoverflow.com/questions/76834972/how-can-i-run-pytesseract-python-library-in-ubuntu-22-04
196
+ #
197
+ run('sudo apt install -y software-properties-common')
198
+ run('sudo add-apt-repository ppa:alex-p/tesseract-ocr-devel')
199
+ run('sudo apt update')
200
+ run('sudo apt install -y libtesseract-dev')
201
+ else:
202
+ run('sudo apt install libtesseract-dev')
181
203
 
182
204
  # Build+install MuPDF. We use mupd:Makefile's install-shared-python target.
183
205
  #
206
+ if pip == 'sudo':
207
+ print('## Installing Python packages required for building MuPDF and PyMuPDF.')
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
+ )
214
+ run(f'sudo pip install {names}')
215
+
184
216
  print('## Build and install MuPDF.')
185
- if 1:
186
- # Current MuPDF creates softlinks with `ln -s` which breaks if there
187
- # was a previous build; it should do `ln -sf`. We make things work by
188
- # deleting any existing softlinks here.
189
- run(f'rm {root_prefix}/lib/libmupdf.so || true')
190
- run(f'rm {root_prefix}/lib/libmupdfcpp.so || true')
191
217
  command = f'cd {mupdf_dir}'
192
218
  command += f' && {sudo}make'
219
+ command += f' -j {multiprocessing.cpu_count()}'
193
220
  #command += f' EXE_LDFLAGS=-Wl,--trace' # Makes linker generate diagnostics as it runs.
194
221
  command += f' DESTDIR={root}'
195
222
  command += f' HAVE_LEPTONICA=yes'
196
223
  command += f' HAVE_TESSERACT=yes'
197
224
  command += f' USE_SYSTEM_LIBS=yes'
225
+ command += f' VENV_FLAG={"--venv" if pip == "venv" else ""}'
226
+ if mupdf_so_mode:
227
+ command += f' SO_INSTALL_MODE={mupdf_so_mode}'
198
228
  command += f' build_prefix=system-libs-'
199
229
  command += f' prefix={prefix}'
200
230
  command += f' verbose=yes'
201
231
  command += f' install-shared-python'
232
+ command += f' INSTALL_MODE=755'
202
233
  run( command)
203
234
 
204
235
  # Build+install PyMuPDF.
@@ -217,23 +248,34 @@ def main():
217
248
  env += f'PYMUPDF_SETUP_IMPLEMENTATIONS=b' # Only build the rebased implementation.
218
249
  if use_installer:
219
250
  print(f'## Building wheel.')
251
+ if pip == 'venv':
252
+ venv_name = 'venv-pymupdf-sysinstall'
220
253
  run(f'pwd')
221
254
  run(f'rm dist/* || true')
222
- run(f'{env} pip wheel -vv -w dist {os.path.abspath(pymupdf_dir)}')
255
+ if pip == 'venv':
256
+ run(f'{sys.executable} -m venv {venv_name}')
257
+ run(f'. {venv_name}/bin/activate && pip install --upgrade pip')
258
+ run(f'. {venv_name}/bin/activate && pip install --upgrade installer')
259
+ run(f'{env} {venv_name}/bin/python -m pip wheel -vv -w dist {os.path.abspath(pymupdf_dir)}')
260
+ elif pip == 'sudo':
261
+ run(f'sudo pip install --upgrade pip')
262
+ run(f'sudo pip install installer')
263
+ run(f'{env} pip wheel -vv -w dist {os.path.abspath(pymupdf_dir)}')
264
+ else:
265
+ log(f'Not installing "installer" because {pip=}.')
223
266
  wheel = glob.glob(f'dist/*')
224
267
  assert len(wheel) == 1, f'{wheel=}'
225
268
  wheel = wheel[0]
226
269
  print(f'## Installing wheel using `installer`.')
227
- venv = 'venv-pymupdf-sysinstall'
228
- run(f'{sys.executable} -m venv {venv}')
229
- run(f'. {venv}/bin/activate && pip install --upgrade pip')
230
- run(f'. {venv}/bin/activate && pip install --upgrade installer')
231
270
  pv = '.'.join(platform.python_version_tuple()[:2])
232
271
  p = f'{root_prefix}/lib/python{pv}'
233
272
  # `python -m installer` fails to overwrite existing files.
234
273
  run(f'{sudo}rm -r {p}/site-packages/fitz || true')
235
274
  run(f'{sudo}rm -r {p}/site-packages/PyMuPDF-*.dist-info || true')
236
- run(f'{sudo}{venv}/bin/python -m installer --destdir {root} --prefix {prefix} {wheel}')
275
+ if pip == 'venv':
276
+ run(f'{sudo}{venv_name}/bin/python -m installer --destdir {root} --prefix {prefix} {wheel}')
277
+ else:
278
+ run(f'{sudo}{sys.executable} -m installer --destdir {root} --prefix {prefix} {wheel}')
237
279
  # It seems that MuPDF Python bindings are installed into
238
280
  # `.../dist-packages` (from mupdf:Mafile's call of `$(shell python3
239
281
  # -c "import sysconfig; print(sysconfig.get_path('platlib'))")` while
@@ -267,7 +309,7 @@ def main():
267
309
  del sys.path[0]
268
310
  pythonpath = pipcl.install_dir(root)
269
311
 
270
- # Show contents of installation director. This is very slow on github,
312
+ # Show contents of installation directory. This is very slow on github,
271
313
  # where /usr/local contains lots of things.
272
314
  #run(f'find {root_prefix}|sort')
273
315
 
@@ -277,20 +319,27 @@ def main():
277
319
  def run(command):
278
320
  return run_command(command, doit=test)
279
321
  import gh_release
280
- # Create venv.
281
- run(f'{sys.executable} -m venv {test_venv}')
282
- # Install required packages.
283
- command = f'. {test_venv}/bin/activate'
284
- command += f' && pip install --upgrade pip'
285
- command += f' && pip install --upgrade {gh_release.test_packages}'
286
- run(command)
322
+ if pip == 'venv':
323
+ # Create venv.
324
+ run(f'{sys.executable} -m venv {test_venv}')
325
+ # Install required packages.
326
+ command = f'. {test_venv}/bin/activate'
327
+ command += f' && pip install --upgrade pip'
328
+ command += f' && pip install --upgrade {gh_release.test_packages}'
329
+ run(command)
330
+ elif pip == 'sudo':
331
+ run(f'sudo pip install --upgrade {gh_release.test_packages}')
332
+ else:
333
+ log(f'Not installing packages for testing because {pip=}.')
287
334
  # Run pytest.
288
335
  #
289
336
  # We need to set PYTHONPATH and LD_LIBRARY_PATH. In particular we
290
337
  # use pipcl.install_dir() to find where pipcl will have installed
291
338
  # PyMuPDF.
292
- command = f'. {test_venv}/bin/activate'
293
- command += f' && LD_LIBRARY_PATH={root_prefix}/lib PYTHONPATH={pythonpath}'
339
+ command = ''
340
+ if pip == 'venv':
341
+ command += f'. {test_venv}/bin/activate &&'
342
+ command += f' LD_LIBRARY_PATH={root_prefix}/lib PYTHONPATH={pythonpath}'
294
343
  command += f' pytest -k "not test_color_count and not test_3050" {pymupdf_dir}'
295
344
  run(command)
296
345
 
@@ -58,11 +58,14 @@ Options:
58
58
  PYMUPDF_SETUP_MUPDF_BUILD, which is used by PyMuPDF/setup.py. If not
59
59
  specifed PyMuPDF will download its default mupdf .tgz.]
60
60
  -p <pytest-options>
61
- Set pytest options; default is '-s'.
62
- -t <name>
63
- Pytest test name. Should be relative to PyMuPDF directory. For example:
61
+ Set pytest options; default is ''.
62
+ -t <names>
63
+ Pytest test names, comma-separated. Should be relative to PyMuPDF
64
+ directory. For example:
64
65
  -t tests/test_general.py
65
- -t tests/test_general.py::test_subset_fonts
66
+ -t tests/test_general.py::test_subset_fonts.
67
+ To specify multiple tests, use comma-separated list and/or multiple `-t
68
+ <names>` args.
66
69
  -v
67
70
  Avoid delay if venv directory already exists. We assume the existing
68
71
  directory was created by us earlier and is a valid venv containing all
@@ -87,6 +90,10 @@ Commands:
87
90
  test
88
91
  Runs PyMuPDF's pytest tests in venv. Default is to test classic, rebased and
89
92
  unoptimised rebased; use `-i` to change this.
93
+
94
+ Environment:
95
+ PYMUDF_SCRIPTS_TEST_options
96
+ Is prepended to command line args.
90
97
  '''
91
98
 
92
99
  import gh_release
@@ -94,6 +101,7 @@ import gh_release
94
101
  import os
95
102
  import platform
96
103
  import re
104
+ import shlex
97
105
  import subprocess
98
106
  import sys
99
107
  import textwrap
@@ -113,12 +121,15 @@ def main(argv):
113
121
  build_type = None
114
122
  gdb = False
115
123
  implementations = None
116
- test_name = None
124
+ test_names = list()
117
125
  venv_quick = False
118
126
  pytest_options = None
119
127
  timeout = None
120
128
 
121
- args = iter( argv[1:])
129
+ options = os.environ.get('PYMUDF_SCRIPTS_TEST_options', '')
130
+ options = shlex.split(options)
131
+
132
+ args = iter(options + argv[1:])
122
133
  i = 0
123
134
  while 1:
124
135
  try:
@@ -148,7 +159,7 @@ def main(argv):
148
159
  elif arg == '-p':
149
160
  pytest_options = next(args)
150
161
  elif arg == '-t':
151
- test_name = next(args)
162
+ test_names += next(args).split(',')
152
163
  elif arg == '--timeout':
153
164
  timeout = float(next(args))
154
165
  elif arg == '-v':
@@ -193,7 +204,7 @@ def main(argv):
193
204
  implementations=implementations,
194
205
  valgrind=valgrind,
195
206
  venv_quick=venv_quick,
196
- test_name=test_name,
207
+ test_names=test_names,
197
208
  pytest_options=pytest_options,
198
209
  timeout=timeout,
199
210
  gdb=gdb,
@@ -213,6 +224,17 @@ def main(argv):
213
224
  assert 0
214
225
 
215
226
 
227
+ def get_env_bool(name, default=0):
228
+ v = os.environ.get(name)
229
+ if v in ('1', 'true'):
230
+ return 1
231
+ elif v in ('0', 'false'):
232
+ return 0
233
+ elif v is None:
234
+ return default
235
+ else:
236
+ assert 0, f'Bad environ {name=} {v=}'
237
+
216
238
  def show_help():
217
239
  print(__doc__)
218
240
  print(venv_info())
@@ -307,7 +329,7 @@ def test(
307
329
  implementations,
308
330
  valgrind,
309
331
  venv_quick=False,
310
- test_name=None,
332
+ test_names=None,
311
333
  pytest_options=None,
312
334
  timeout=None,
313
335
  gdb=False,
@@ -320,7 +342,7 @@ def test(
320
342
  See top-level option `--valgrind`.
321
343
  venv_quick:
322
344
  See top-level option `-v`.
323
- test_name:
345
+ test_names:
324
346
  See top-level option `-t`.
325
347
  pytest_options:
326
348
  See top-level option `-p`.
@@ -332,10 +354,13 @@ def test(
332
354
  if valgrind:
333
355
  pytest_options = '-s -vv'
334
356
  else:
335
- pytest_options = '-s'
336
- pytest_arg = pymupdf_dir_rel
337
- if test_name:
338
- pytest_arg += f'/{test_name}'
357
+ pytest_options = ''
358
+ pytest_arg = ''
359
+ if test_names:
360
+ for test_name in test_names:
361
+ pytest_arg += f' {pymupdf_dir_rel}/{test_name}'
362
+ else:
363
+ pytest_arg += f' {pymupdf_dir_rel}'
339
364
  python = gh_release.relpath(sys.executable)
340
365
  log('Running tests with tests/run_compound.py and pytest.')
341
366
  try:
@@ -359,7 +384,7 @@ def test(
359
384
  command = (
360
385
  f'{python} {pymupdf_dir_rel}/tests/run_compound.py{run_compound_args}'
361
386
  f' valgrind --suppressions={pymupdf_dir_rel}/valgrind.supp --error-exitcode=100 --errors-for-leak-kinds=none --fullpath-after='
362
- f' {python} -m pytest {pytest_options} {pytest_arg}'
387
+ f' {python} -m pytest {pytest_options}{pytest_arg}'
363
388
  )
364
389
  env_extra=dict(
365
390
  PYTHONMALLOC='malloc',
@@ -385,12 +410,13 @@ def test(
385
410
  log('\n' + venv_info(pytest_args=f'{pytest_options} {pytest_arg}'))
386
411
 
387
412
 
388
- def get_pyproject_required():
413
+ def get_pyproject_required(ppt=None):
389
414
  '''
390
415
  Returns space-separated names of required packages in pyproject.toml. We
391
416
  do not do a proper parse and rely on the packages being in a single line.
392
417
  '''
393
- ppt = os.path.abspath(f'{__file__}/../../pyproject.toml')
418
+ if ppt is None:
419
+ ppt = os.path.abspath(f'{__file__}/../../pyproject.toml')
394
420
  with open(ppt) as f:
395
421
  for line in f:
396
422
  m = re.match('^requires = \\[(.*)\\]$', line)
@@ -1072,7 +1072,7 @@ with open( f'{g_root}/READMErb.md', encoding='utf-8') as f:
1072
1072
  # We generate different wheels depending on g_flavour.
1073
1073
  #
1074
1074
 
1075
- version = '1.23.22'
1075
+ version = '1.23.24'
1076
1076
  version_b = '1.23.22'
1077
1077
 
1078
1078
  tag_python = None