PyMuPDF 1.24.2__tar.gz → 1.24.3__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 (191) hide show
  1. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/PKG-INFO +4 -6
  2. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/README.md +4 -2
  3. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/READMErb.md +1 -1
  4. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/changes.txt +30 -0
  5. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/pipcl.py +105 -86
  6. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/scripts/gh_release.py +167 -143
  7. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/scripts/sysinstall.py +3 -1
  8. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/scripts/test.py +49 -9
  9. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/setup.py +148 -97
  10. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src/__init__.py +212 -488
  11. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src/__main__.py +60 -60
  12. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src/extra.i +3 -3
  13. PyMuPDF-1.24.3/src/fitz___init__.py +6 -0
  14. PyMuPDF-1.24.3/src/fitz_table.py +2 -0
  15. PyMuPDF-1.24.3/src/fitz_utils.py +2 -0
  16. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src/table.py +1 -0
  17. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src/utils.py +514 -507
  18. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/conftest.py +4 -1
  19. PyMuPDF-1.24.3/tests/gentle_compare.py +26 -0
  20. PyMuPDF-1.24.3/tests/resources/test-2812.pdf +0 -0
  21. PyMuPDF-1.24.3/tests/resources/test_1645_expected_1.24.2.pdf +0 -0
  22. PyMuPDF-1.24.3/tests/resources/test_1645_expected_1.25.pdf +0 -0
  23. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_2548.py +51 -51
  24. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_2634.py +5 -5
  25. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_2791.py +4 -4
  26. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_2904.py +9 -9
  27. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_2907.py +5 -5
  28. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_annots.py +56 -47
  29. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_badfonts.py +2 -2
  30. PyMuPDF-1.24.3/tests/test_balance_count.py +52 -0
  31. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_cluster_drawings.py +12 -12
  32. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_crypting.py +9 -9
  33. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_drawings.py +14 -14
  34. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_embeddedfiles.py +2 -2
  35. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_extractimage.py +6 -6
  36. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_flake8.py +3 -2
  37. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_font.py +22 -22
  38. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_general.py +171 -156
  39. PyMuPDF-1.24.3/tests/test_geometry.py +348 -0
  40. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_imagebbox.py +3 -3
  41. PyMuPDF-1.24.3/tests/test_import.py +18 -0
  42. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_insertimage.py +11 -11
  43. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_insertpdf.py +13 -13
  44. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_linequad.py +3 -3
  45. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_metadata.py +3 -3
  46. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_mupdf_regressions.py +21 -42
  47. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_named_links.py +22 -22
  48. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_nonpdf.py +3 -3
  49. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_object_manipulation.py +5 -5
  50. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_objectstreams.py +7 -7
  51. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_optional_content.py +11 -11
  52. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_page_links.py +2 -2
  53. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_pagedelete.py +7 -7
  54. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_pagelabels.py +2 -2
  55. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_pixmap.py +47 -47
  56. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_pylint.py +8 -4
  57. PyMuPDF-1.24.3/tests/test_remove-rotation.py +30 -0
  58. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_showpdfpage.py +11 -11
  59. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_story.py +22 -22
  60. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_tables.py +26 -26
  61. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_tesseract.py +9 -9
  62. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_textbox.py +64 -59
  63. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_textextract.py +38 -38
  64. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_textsearch.py +4 -4
  65. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_toc.py +15 -15
  66. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_widgets.py +118 -50
  67. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_word_delimiters.py +2 -2
  68. PyMuPDF-1.24.2/tests/test_balance_count.py +0 -31
  69. PyMuPDF-1.24.2/tests/test_geometry.py +0 -348
  70. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/COPYING +0 -0
  71. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/MANIFEST.in +0 -0
  72. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/pyproject.toml +0 -0
  73. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/pytest.ini +0 -0
  74. /PyMuPDF-1.24.2/src/fitz.py → /PyMuPDF-1.24.3/src/pymupdf.py +0 -0
  75. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/__init__.py +0 -0
  76. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/__main__.py +0 -0
  77. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/_config.h +0 -0
  78. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/fitz_old.i +0 -0
  79. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-annot.i +0 -0
  80. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-convert.i +0 -0
  81. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-defines.i +0 -0
  82. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-devices.i +0 -0
  83. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-fields.i +0 -0
  84. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-fileobj.i +0 -0
  85. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-geo-c.i +0 -0
  86. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-geo-py.i +0 -0
  87. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-globals.i +0 -0
  88. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-other.i +0 -0
  89. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-pdfinfo.i +0 -0
  90. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-pixmap.i +0 -0
  91. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-portfolio.i +0 -0
  92. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-python.i +0 -0
  93. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-select.i +0 -0
  94. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-stext.i +0 -0
  95. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/helper-xobject.i +0 -0
  96. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/utils.py +0 -0
  97. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/src_classic/version.i +0 -0
  98. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/README.md +0 -0
  99. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/001003ED.pdf +0 -0
  100. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/1.pdf +0 -0
  101. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/2.pdf +0 -0
  102. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/2201.00069.pdf +0 -0
  103. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/3.pdf +0 -0
  104. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/4.pdf +0 -0
  105. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/Bezier.epub +0 -0
  106. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/PragmaticaC.otf +0 -0
  107. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/battery-file-22.pdf +0 -0
  108. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/bug1945.pdf +0 -0
  109. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/bug1971.pdf +0 -0
  110. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/chinese-tables.pdf +0 -0
  111. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/chinese-tables.pickle +0 -0
  112. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/circular-toc.pdf +0 -0
  113. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/cython.pdf +0 -0
  114. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/cython.pickle +0 -0
  115. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/full_toc.txt +0 -0
  116. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/github_sample.pdf +0 -0
  117. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/has-bad-fonts.pdf +0 -0
  118. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/image-file1.pdf +0 -0
  119. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/img-transparent.png +0 -0
  120. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/joined.pdf +0 -0
  121. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/metadata.txt +0 -0
  122. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/mupdf_explored.pdf +0 -0
  123. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/nur-ruhig.jpg +0 -0
  124. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/quad-calc-0.pdf +0 -0
  125. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/simple_toc.txt +0 -0
  126. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/small-table.pdf +0 -0
  127. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/strict-yes-no.pdf +0 -0
  128. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/symbol-list.pdf +0 -0
  129. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/symbols.txt +0 -0
  130. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test-2333.pdf +0 -0
  131. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test-2462.pdf +0 -0
  132. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test-3143.pdf +0 -0
  133. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test-3150.pdf +0 -0
  134. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test-3207.pdf +0 -0
  135. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test-707448.pdf +0 -0
  136. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test-707673.pdf +0 -0
  137. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test2093.pdf +0 -0
  138. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test2182.pdf +0 -0
  139. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test2238.pdf +0 -0
  140. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_1645_expected_1.22.pdf +0 -0
  141. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_1645_expected_1.24.pdf +0 -0
  142. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_1824.pdf +0 -0
  143. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2108.pdf +0 -0
  144. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2270.pdf +0 -0
  145. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2533.pdf +0 -0
  146. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2548.pdf +0 -0
  147. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2553-2.pdf +0 -0
  148. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2553.pdf +0 -0
  149. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2596.pdf +0 -0
  150. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2608_expected +0 -0
  151. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2634.pdf +0 -0
  152. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2635.pdf +0 -0
  153. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2645_1.pdf +0 -0
  154. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2645_2.pdf +0 -0
  155. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2645_3.pdf +0 -0
  156. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2710.pdf +0 -0
  157. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2730.pdf +0 -0
  158. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2742.pdf +0 -0
  159. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2788.pdf +0 -0
  160. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2791_content.pdf +0 -0
  161. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2791_coverpage.pdf +0 -0
  162. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2861.pdf +0 -0
  163. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2871.pdf +0 -0
  164. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2885.pdf +0 -0
  165. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2904.pdf +0 -0
  166. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2907.pdf +0 -0
  167. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2954.pdf +0 -0
  168. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2957_1.pdf +0 -0
  169. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2957_2.pdf +0 -0
  170. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2969.pdf +0 -0
  171. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_2979.pdf +0 -0
  172. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3058.pdf +0 -0
  173. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3062.pdf +0 -0
  174. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3070.pdf +0 -0
  175. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3072.pdf +0 -0
  176. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3087.pdf +0 -0
  177. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3179.pdf +0 -0
  178. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3186.pdf +0 -0
  179. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3197.pdf +0 -0
  180. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3357.pdf +0 -0
  181. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3362.pdf +0 -0
  182. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_3376.pdf +0 -0
  183. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_annot_file_info.pdf +0 -0
  184. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/test_delete_image.pdf +0 -0
  185. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/type3font.pdf +0 -0
  186. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/v110-changes.pdf +0 -0
  187. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/resources/widgettest.pdf +0 -0
  188. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/run_compound.py +0 -0
  189. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/tests/test_docs_samples.py +0 -0
  190. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/valgrind.supp +0 -0
  191. {PyMuPDF-1.24.2 → PyMuPDF-1.24.3}/wdev.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyMuPDF
3
- Version: 1.24.2
3
+ Version: 1.24.3
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
@@ -29,6 +29,9 @@ Project-URL: Changelog, https://pymupdf.readthedocs.io/en/latest/changes.html
29
29
 
30
30
  **PyMuPDF** is a high performance **Python** library for data extraction, analysis, conversion & manipulation of [PDF (and other) documents](https://pymupdf.readthedocs.io/en/latest/the-basics.html#supported-file-types).
31
31
 
32
+ # Community
33
+ Join us on **Discord** here: [#pymupdf](https://discord.gg/TSpYGBW4eq)
34
+
32
35
 
33
36
  # Installation
34
37
 
@@ -78,8 +81,3 @@ Full documentation can be found on [pymupdf.readthedocs.io](https://pymupdf.read
78
81
  # License and Copyright
79
82
 
80
83
  **PyMuPDF** is available under [open-source AGPL](https://www.gnu.org/licenses/agpl-3.0.html) and commercial license agreements. If you determine you cannot meet the requirements of the **AGPL**, please contact [Artifex](https://artifex.com/contact/pymupdf-inquiry.php) for more information regarding a commercial license.
81
-
82
-
83
-
84
- # Contact
85
- Join us on **Discord** here: [#pymupdf](https://discord.gg/TSpYGBW4eq)
@@ -2,6 +2,9 @@
2
2
 
3
3
  **PyMuPDF** is a high performance **Python** library for data extraction, analysis, conversion & manipulation of [PDF (and other) documents](https://pymupdf.readthedocs.io/en/latest/the-basics.html#supported-file-types).
4
4
 
5
+ # Community
6
+ Join us on **Discord** here: [#pymupdf](https://discord.gg/TSpYGBW4eq)
7
+
5
8
 
6
9
  # Installation
7
10
 
@@ -54,5 +57,4 @@ Full documentation can be found on [pymupdf.readthedocs.io](https://pymupdf.read
54
57
 
55
58
 
56
59
 
57
- # Contact
58
- Join us on **Discord** here: [#pymupdf](https://discord.gg/TSpYGBW4eq)
60
+
@@ -1,4 +1,4 @@
1
- # PyMuPDF 1.24.1
1
+ # PyMuPDF 1.24.3
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,36 @@ Change Log
2
2
  ==========
3
3
 
4
4
 
5
+ **Changes in version 1.24.3 (2024-05-09)**
6
+
7
+ *
8
+ The Python module is now called `pymupdf`. `fitz` is still supported for
9
+ backwards compatibility.
10
+
11
+ * Use MuPDF-1.24.2.
12
+
13
+ * Fixed issues:
14
+
15
+ * **Fixed** `3357 <https://github.com/pymupdf/PyMuPDF/issues/3357>`_: PyMuPDF==1.24.0 will hanging when using page.get_text("text")
16
+ * **Fixed** `3376 <https://github.com/pymupdf/PyMuPDF/issues/3376>`_: Redacting results are not as expected in 1.24.x.
17
+ * **Fixed** `3379 <https://github.com/pymupdf/PyMuPDF/issues/3379>`_: Documentation mismatch for get_text_blocks return value order.
18
+ * **Fixed** `3381 <https://github.com/pymupdf/PyMuPDF/issues/3381>`_: Contents stream contains floats in scientific notation
19
+ * **Fixed** `3402 <https://github.com/pymupdf/PyMuPDF/issues/3402>`_: Cannot add Widgets containing inter-field-calculation JavaScript
20
+ * **Fixed** `3414 <https://github.com/pymupdf/PyMuPDF/issues/3414>`_: missing attribute set_dpi()
21
+ * **Fixed** `3430 <https://github.com/pymupdf/PyMuPDF/issues/3430>`_: page.get_text() cause process freeze with certain pdf on v1.24.2
22
+
23
+ * Other:
24
+
25
+ * New/modified methods:
26
+
27
+ * `Page.remove_rotation()`: new, set page rotation to zero while keeping appearance.
28
+
29
+ * Fixed some problems when checking for PDF properties.
30
+ * Fixed pip builds from sdist
31
+ (see discussion `3360 <https://github.com/pymupdf/PyMuPDF/discussions/3360>`_:
32
+ Alpine linux docker build failing "No matching distribution found for pymupdfb==1.24.1").
33
+
34
+
5
35
  **Changes in version 1.24.2 (2024-04-17)**
6
36
 
7
37
  * Removed obsolete classic implementation from releases
@@ -78,6 +78,7 @@ class Package:
78
78
  ... ('cli.py', 'foo/__main__.py'),
79
79
  ... (f'build/{so_leaf}', f'foo/'),
80
80
  ... ('README', '$dist-info/'),
81
+ ... (b'Hello world', 'foo/hw.txt'),
81
82
  ... ]
82
83
  ...
83
84
  ... def sdist():
@@ -88,6 +89,7 @@ class Package:
88
89
  ... 'pipcl.py',
89
90
  ... 'wdev.py',
90
91
  ... 'README',
92
+ ... (b'Hello word2', 'hw2.txt'),
91
93
  ... ]
92
94
  ...
93
95
  ... p = pipcl.Package(
@@ -394,16 +396,18 @@ class Package:
394
396
  A function taking no args, or a single `config_settings` dict
395
397
  arg (as described in PEP-517), that builds the package.
396
398
 
397
- Should return a list of items; each item should be a tuple of
398
- two strings `(from_, to_)`, or a single string `path` which is
399
- treated as the tuple `(path, path)`.
399
+ Should return a list of items; each item should be a tuple
400
+ `(from_, to_)`, or a single string `path` which is treated as
401
+ the tuple `(path, path)`.
400
402
 
401
- `from_` should be the path to a file; if a relative path it is
402
- assumed to be relative to `root`.
403
+ `from_` can be a string or a `bytes`. If a string it should
404
+ be the path to a file; a relative path is treated as relative
405
+ to `root`. If a `bytes` it is the contents of the file to be
406
+ added.
403
407
 
404
408
  `to_` identifies what the file should be called within a wheel
405
409
  or when installing. If `to_` ends with `/`, the leaf of `from_`
406
- is appended to it.
410
+ is appended to it (and `from_` must not be a `bytes`).
407
411
 
408
412
  Initial `$dist-info/` in `_to` is replaced by
409
413
  `{name}-{version}.dist-info/`; this is useful for license files
@@ -437,13 +441,9 @@ class Package:
437
441
 
438
442
  fn_sdist:
439
443
  A function taking no args, or a single `config_settings` dict
440
- arg (as described in PEP517), that returns a list of paths for
441
- files that should be copied into the sdist. Each item in the
442
- list can also be a tuple `(from_, to_)`, where `from_` is the
443
- path of a file and `to_` is its name within the sdist.
444
-
445
- Relative paths are interpreted as relative to `root`. It is an
446
- error if a path does not exist or is not a file.
444
+ arg (as described in PEP517), that returns a list of items to
445
+ be copied into the sdist. The list should be in the same format
446
+ as returned by `fn_build`.
447
447
 
448
448
  It can be convenient to use `pipcl.git_items()`.
449
449
 
@@ -646,21 +646,26 @@ class Package:
646
646
  record = _Record()
647
647
  with zipfile.ZipFile(path, 'w', self.wheel_compression, self.wheel_compresslevel) as z:
648
648
 
649
- def add_file(from_, to_):
650
- z.write(from_, to_)
651
- record.add_file(from_, to_)
649
+ def add(from_, to_):
650
+ if isinstance(from_, str):
651
+ z.write(from_, to_)
652
+ record.add_file(from_, to_)
653
+ elif isinstance(from_, bytes):
654
+ z.writestr(to_, from_)
655
+ record.add_content(from_, to_)
656
+ else:
657
+ assert 0
652
658
 
653
659
  def add_str(content, to_):
654
- z.writestr(to_, content)
655
- record.add_content(content, to_)
660
+ add(content.encode('utf8'), to_)
656
661
 
657
662
  dist_info_dir = self._dist_info_dir()
658
663
 
659
664
  # Add the files returned by fn_build().
660
665
  #
661
666
  for item in items:
662
- (from_abs, from_rel), (to_abs, to_rel) = self._fromto(item)
663
- add_file(from_abs, to_rel)
667
+ from_, (to_abs, to_rel) = self._fromto(item)
668
+ add(from_, to_rel)
664
669
 
665
670
  # Add <name>-<version>.dist-info/WHEEL.
666
671
  #
@@ -726,60 +731,63 @@ class Package:
726
731
  else:
727
732
  items = self.fn_sdist()
728
733
 
729
- manifest = []
730
- names_in_tar = []
731
- def check_name(name):
732
- if name in names_in_tar:
733
- raise Exception(f'Name specified twice: {name}')
734
- names_in_tar.append(name)
735
-
736
734
  prefix = f'{self.name}-{self.version}'
737
- def add_content(tar, name, contents):
738
- '''
739
- Adds item called `name` to `tarfile.TarInfo` `tar`, containing
740
- `contents`. If contents is a string, it is encoded using utf8.
741
- '''
742
- log2( f'Adding: {name}')
743
- if isinstance(contents, str):
744
- contents = contents.encode('utf8')
745
- check_name(name)
746
- ti = tarfile.TarInfo(f'{prefix}/{name}')
747
- ti.size = len(contents)
748
- ti.mtime = time.time()
749
- tar.addfile(ti, io.BytesIO(contents))
750
-
751
- def add_file(tar, path_abs, name):
752
- log2( f'Adding file: {os.path.relpath(path_abs)} => {name}')
753
- check_name(name)
754
- tar.add( path_abs, f'{prefix}/{name}', recursive=False)
755
-
756
735
  os.makedirs(sdist_directory, exist_ok=True)
757
736
  tarpath = f'{sdist_directory}/{prefix}.tar.gz'
758
737
  log2(f'Creating sdist: {tarpath}')
738
+
759
739
  with tarfile.open(tarpath, 'w:gz') as tar:
740
+
741
+ names_in_tar = list()
742
+ def check_name(name):
743
+ if name in names_in_tar:
744
+ raise Exception(f'Name specified twice: {name}')
745
+ names_in_tar.append(name)
746
+
747
+ def add(from_, name):
748
+ check_name(name)
749
+ if isinstance(from_, str):
750
+ log2( f'Adding file: {os.path.relpath(from_)} => {name}')
751
+ tar.add( from_, f'{prefix}/{name}', recursive=False)
752
+ elif isinstance(from_, bytes):
753
+ log2( f'Adding: {name}')
754
+ ti = tarfile.TarInfo(f'{prefix}/{name}')
755
+ ti.size = len(from_)
756
+ ti.mtime = time.time()
757
+ tar.addfile(ti, io.BytesIO(from_))
758
+ else:
759
+ assert 0
760
+
761
+ def add_string(text, name):
762
+ textb = text.encode('utf8')
763
+ return add(textb, name)
764
+
760
765
  found_pyproject_toml = False
761
766
  for item in items:
762
- (from_abs, from_rel), (to_abs, to_rel) = self._fromto(item)
763
- if from_abs.startswith(f'{os.path.abspath(sdist_directory)}/'):
764
- # Source files should not be inside <sdist_directory>.
765
- assert 0, f'Path is inside sdist_directory={sdist_directory}: {from_abs!r}'
766
- assert os.path.exists(from_abs), f'Path does not exist: {from_abs!r}'
767
- assert os.path.isfile(from_abs), f'Path is not a file: {from_abs!r}'
768
- if to_rel == 'pyproject.toml':
769
- found_pyproject_toml = True
770
- add_file( tar, from_abs, to_rel)
771
- manifest.append(to_rel)
767
+ from_, (to_abs, to_rel) = self._fromto(item)
768
+ if isinstance(from_, bytes):
769
+ add(from_, to_rel)
770
+ else:
771
+ if from_.startswith(f'{os.path.abspath(sdist_directory)}/'):
772
+ # Source files should not be inside <sdist_directory>.
773
+ assert 0, f'Path is inside sdist_directory={sdist_directory}: {from_!r}'
774
+ assert os.path.exists(from_), f'Path does not exist: {from_!r}'
775
+ assert os.path.isfile(from_), f'Path is not a file: {from_!r}'
776
+ if to_rel == 'pyproject.toml':
777
+ found_pyproject_toml = True
778
+ add(from_, to_rel)
779
+
772
780
  if not found_pyproject_toml:
773
781
  log0(f'Warning: no pyproject.toml specified.')
774
782
 
775
783
  # Always add a PKG-INFO file.
776
- add_content(tar, f'PKG-INFO', self._metainfo())
784
+ add_string(self._metainfo(), 'PKG-INFO')
777
785
 
778
786
  if self.license:
779
787
  if 'COPYING' in names_in_tar:
780
788
  log2(f'Not writing .license because file already in sdist: COPYING')
781
789
  else:
782
- add_content(tar, f'COPYING', self.license)
790
+ add_string(self.license, 'COPYING')
783
791
 
784
792
  log1( f'Have created sdist: {tarpath}')
785
793
  return os.path.basename(tarpath)
@@ -849,11 +857,18 @@ class Package:
849
857
  record_path = f'{root2}/{dist_info_dir}/RECORD'
850
858
  record = _Record()
851
859
 
852
- def add_file(from_abs, from_rel, to_abs, to_rel):
853
- log2(f'Copying from {from_rel} to {to_abs}')
860
+ def add_file(from_, to_abs, to_rel):
854
861
  os.makedirs( os.path.dirname( to_abs), exist_ok=True)
855
- shutil.copy2( from_abs, to_abs)
856
- record.add_file(from_rel, to_rel)
862
+ if isinstance(from_, bytes):
863
+ log2(f'Copying content into {to_abs}.')
864
+ with open(to_abs, 'wb') as f:
865
+ f.write(from_)
866
+ record.add_content(from_, to_rel)
867
+ else:
868
+ log0(f'{from_=}')
869
+ log2(f'Copying from {os.path.relpath(from_, self.root)} to {to_abs}')
870
+ shutil.copy2( from_, to_abs)
871
+ record.add_file(from_, to_rel)
857
872
 
858
873
  def add_str(content, to_abs, to_rel):
859
874
  log2( f'Writing to: {to_abs}')
@@ -863,9 +878,10 @@ class Package:
863
878
  record.add_content(content, to_rel)
864
879
 
865
880
  for item in items:
866
- (from_abs, from_rel), (to_abs, to_rel) = self._fromto(item)
881
+ from_, (to_abs, to_rel) = self._fromto(item)
882
+ log0(f'{from_=} {to_abs=} {to_rel=}')
867
883
  to_abs2 = f'{root2}/{to_rel}'
868
- add_file( from_abs, from_rel, to_abs2, to_rel)
884
+ add_file( from_, to_abs2, to_rel)
869
885
 
870
886
  add_str( self._metainfo(), f'{root2}/{dist_info_dir}/METADATA', f'{dist_info_dir}/METADATA')
871
887
 
@@ -1245,12 +1261,14 @@ class Package:
1245
1261
 
1246
1262
  def _fromto(self, p):
1247
1263
  '''
1248
- Returns `((from_abs, from_rel), (to_abs, to_rel))`.
1264
+ Returns `(from_, (to_abs, to_rel))`.
1249
1265
 
1250
- If `p` is a string we convert to `(p, p)`. Otherwise we assert
1251
- that `p` is a tuple of two string, `(from_, to_)`. Non-absolute
1252
- paths are assumed to be relative to `self.root`. If `to_` is
1253
- empty or ends with `/`, we append the leaf of `from_`.
1266
+ If `p` is a string we convert to `(p, p)`. Otherwise we assert that
1267
+ `p` is a tuple `(from_, to_)` where `from_` is str/bytes and `to_` is
1268
+ str. If `from_` is a bytes it is contents of file to add, otherwise the
1269
+ path of an existing file; non-absolute paths are assumed to be relative
1270
+ to `self.root`. If `to_` is empty or ends with `/`, we append the leaf
1271
+ of `from_` (which must be a str).
1254
1272
 
1255
1273
  If `to_` starts with `$dist-info/`, we replace this with
1256
1274
  `self._dist_info_dir()`.
@@ -1258,21 +1276,18 @@ class Package:
1258
1276
  If `to_` starts with `$data/`, we replace this with
1259
1277
  `{self.name}-{self.version}.data/`.
1260
1278
 
1261
- `from_abs` and `to_abs` are absolute paths. We assert that `to_abs` is
1262
- `within self.root`.
1279
+ We assert that `to_abs` is `within self.root`.
1263
1280
 
1264
- `from_rel` and `to_rel` are derived from the `_abs` paths and are
1265
- `relative to self.root`.
1281
+ `to_rel` is derived from the `to_abs` and is relative to self.root`.
1266
1282
  '''
1267
1283
  ret = None
1268
1284
  if isinstance(p, str):
1269
- ret = p, p
1270
- elif isinstance(p, tuple) and len(p) == 2:
1271
- from_, to_ = p
1272
- if isinstance(from_, str) and isinstance(to_, str):
1273
- ret = from_, to_
1274
- assert ret, 'p should be str or (str, str), but is: {p}'
1275
- from_, to_ = ret
1285
+ p = p, p
1286
+ assert isinstance(p, tuple) and len(p) == 2
1287
+
1288
+ from_, to_ = p
1289
+ assert isinstance(from_, (str, bytes))
1290
+ assert isinstance(to_, str)
1276
1291
  if to_.endswith('/') or to_=='':
1277
1292
  to_ += os.path.basename(from_)
1278
1293
  prefix = '$dist-info/'
@@ -1281,8 +1296,11 @@ class Package:
1281
1296
  prefix = '$data/'
1282
1297
  if to_.startswith( prefix):
1283
1298
  to_ = f'{self.name}-{self.version}.data/{to_[ len(prefix):]}'
1284
- from_ = self._path_relative_to_root( from_, assert_within_root=False)
1299
+ if isinstance(from_, str):
1300
+ from_, _ = self._path_relative_to_root( from_, assert_within_root=False)
1285
1301
  to_ = self._path_relative_to_root(to_)
1302
+ assert isinstance(from_, (str, bytes))
1303
+ log2(f'returning {from_=} {to_=}')
1286
1304
  return from_, to_
1287
1305
 
1288
1306
 
@@ -2212,7 +2230,7 @@ def _fs_mtime( filename, default=0):
2212
2230
  except OSError:
2213
2231
  return default
2214
2232
 
2215
- g_verbose = int(os.environ.get('PIPCL_VERBOSE', '2'))
2233
+ g_verbose = int(os.environ.get('PIPCL_VERBOSE', '1'))
2216
2234
 
2217
2235
  def verbose(level=None):
2218
2236
  '''
@@ -2324,7 +2342,7 @@ class _Record:
2324
2342
  def __init__(self):
2325
2343
  self.text = ''
2326
2344
 
2327
- def add_content(self, content, to_):
2345
+ def add_content(self, content, to_, verbose=True):
2328
2346
  if isinstance(content, str):
2329
2347
  content = content.encode('utf8')
2330
2348
 
@@ -2339,13 +2357,14 @@ class _Record:
2339
2357
  digest = digest.decode('utf8')
2340
2358
 
2341
2359
  self.text += f'{to_},sha256={digest},{len(content)}\n'
2342
- log2(f'Adding {to_}')
2360
+ if verbose:
2361
+ log2(f'Adding {to_}')
2343
2362
 
2344
2363
  def add_file(self, from_, to_):
2364
+ log2(f'Adding file: {os.path.relpath(from_)} => {to_}')
2345
2365
  with open(from_, 'rb') as f:
2346
2366
  content = f.read()
2347
- self.add_content(content, to_)
2348
- log2(f'Adding file: {os.path.relpath(from_)} => {to_}')
2367
+ self.add_content(content, to_, verbose=False)
2349
2368
 
2350
2369
  def get(self, record_path=None):
2351
2370
  '''