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