PyMuPDF 1.26.0__tar.gz → 1.26.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pymupdf-1.26.0 → pymupdf-1.26.1}/PKG-INFO +1 -1
- {pymupdf-1.26.0 → pymupdf-1.26.1}/changes.txt +24 -1
- {pymupdf-1.26.0 → pymupdf-1.26.1}/pipcl.py +195 -48
- {pymupdf-1.26.0 → pymupdf-1.26.1}/scripts/test.py +616 -314
- {pymupdf-1.26.0 → pymupdf-1.26.1}/setup.py +37 -20
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/__init__.py +118 -626
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/utils.py +2 -3
- pymupdf-1.26.1/tests/resources/test-rewrite-images.pdf +0 -0
- pymupdf-1.26.1/tests/resources/test_2608_expected +14 -0
- pymupdf-1.26.1/tests/resources/test_3624_expected.png +0 -0
- pymupdf-1.26.1/tests/resources/test_4412.pdf +0 -0
- pymupdf-1.26.1/tests/resources/test_4503.pdf +0 -0
- pymupdf-1.26.1/tests/resources/test_4546.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/run_compound.py +14 -0
- pymupdf-1.26.1/tests/test_4520.py +11 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_font.py +6 -1
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_general.py +23 -3
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_insertpdf.py +16 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_memory.py +3 -3
- pymupdf-1.26.1/tests/test_rewrite_images.py +15 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_textextract.py +93 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/wdev.py +65 -13
- pymupdf-1.26.0/tests/resources/test_3624_expected.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/COPYING +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/README.md +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/READMEb.md +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/READMEd.md +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/pyproject.toml +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/pytest.ini +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/scripts/gh_release.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/scripts/sysinstall.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/__main__.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/_apply_pages.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/_wxcolors.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/extra.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/fitz___init__.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/fitz_table.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/fitz_utils.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/pymupdf.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src/table.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/__init__.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/__main__.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/_config.h +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/fitz_old.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-annot.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-convert.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-defines.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-devices.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-fields.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-fileobj.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-geo-c.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-geo-py.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-globals.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-other.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-pdfinfo.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-pixmap.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-portfolio.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-python.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-select.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-stext.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/helper-xobject.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/utils.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/src_classic/version.i +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/README.md +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/conftest.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/gentle_compare.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/001003ED.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/1.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/2.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/2201.00069.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/3.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/4.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/Bezier.epub +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/PragmaticaC.otf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/battery-file-22.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/bug1945.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/bug1971.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/chinese-tables.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/chinese-tables.pickle +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/circular-toc.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/cms-etc-filled.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/cython.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/cython.pickle +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/dotted-gridlines.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/full_toc.txt +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/github_sample.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/has-bad-fonts.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/image-file1.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/img-regular.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/img-transparent.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/img-transparent.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/interfield-calculation.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/joined.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/merge-form1.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/merge-form2.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/metadata.txt +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/mupdf_explored.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/nur-ruhig.jpg +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/quad-calc-0.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/simple_toc.txt +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/small-table.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/strict-yes-no.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/symbol-list.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/symbols.txt +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-2333.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-2462.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-2812.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-3143.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-3150.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-3207.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-3591.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-3820.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-4055.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-707448.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-707673.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-E+A.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test-linebreaks.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test2093.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test2182.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test2238.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_1645_expected.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_1824.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2108.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2270.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2533.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2548.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2553-2.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2553.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2596.pdf +0 -0
- /pymupdf-1.26.0/tests/resources/test_2608_expected → /pymupdf-1.26.1/tests/resources/test_2608_expected_1.26 +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2634.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2635.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2645_1.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2645_2.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2645_3.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2710.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2730.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2742.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2788.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2791_content.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2791_coverpage.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2861.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2871.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2885.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2904.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2907.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2954.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2957_1.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2957_2.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2969.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_2979.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3050_expected.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3058.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3062.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3070.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3072.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3087.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3179.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3186.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3197.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3357.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3362.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3376.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3448.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3448.pdf-expected.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3450.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3493.epub +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3569.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3594.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3615.epub +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3624.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3650.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3654.docx +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3677.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3687-3.epub +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3687.epub +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3705.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3725.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3727.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3780.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3789.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3842.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3848.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3854.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3854_expected.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3863.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3863.pdf.pdf.0.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3863.pdf.pdf.1.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3863.pdf.pdf.2.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3863.pdf.pdf.3.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3863.pdf.pdf.4.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3863.pdf.pdf.5.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3863.pdf.pdf.6.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3863.pdf.pdf.7.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3886.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3887.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3933.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3950.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_3994.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4004.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4017.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4026.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4034.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4043.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4047.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4079.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4079_after.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4079_after_1.25.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4090.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4125.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4139.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4141.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4147.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4179.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4179_expected.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4180.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4180_expected.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4182.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4182_expected.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4224.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4245.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4245_expected.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4263.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4363.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4415.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4415_out_expected.png +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4423.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4435.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4479.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_4505.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_annot_file_info.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_delete_image.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.cbz +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.doc +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.docx +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.epub +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.fb2 +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.html +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.jpg +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.mobi +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.svg +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.xhtml +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.xml +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2.xps +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_open2_expected.json +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/test_toc_count.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/text-find-ligatures.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/type3font.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/v110-changes.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/resources/widgettest.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_2548.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_2634.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_2904.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_2907.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_4141.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_4466.pdf +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_4505.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_annots.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_badfonts.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_balance_count.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_barcode.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_cluster_drawings.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_codespell.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_crypting.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_docs_samples.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_drawings.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_embeddedfiles.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_extractimage.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_flake8.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_geometry.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_imagebbox.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_imagemasks.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_import.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_insertimage.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_linebreaks.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_linequad.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_metadata.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_mupdf_regressions.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_named_links.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_nonpdf.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_object_manipulation.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_objectstreams.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_optional_content.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_page_links.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_pagedelete.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_pagelabels.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_pixmap.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_pylint.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_remove-rotation.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_rtl.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_showpdfpage.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_spikes.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_story.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_tables.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_tesseract.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_textbox.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_textsearch.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_toc.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_widgets.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/test_word_delimiters.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/tests/util.py +0 -0
- {pymupdf-1.26.0 → pymupdf-1.26.1}/valgrind.supp +0 -0
|
@@ -2,6 +2,27 @@ Change Log
|
|
|
2
2
|
==========
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
**Changes in version 1.26.1**
|
|
6
|
+
|
|
7
|
+
* Use MuPDF-1.26.2.
|
|
8
|
+
|
|
9
|
+
* Fixed issues:
|
|
10
|
+
|
|
11
|
+
* **Fixed** `4520 <https://github.com/pymupdf/PyMuPDF/issues/4520>`_: show_pdf_page does not like empty pages created by new_page
|
|
12
|
+
* **Fixed** `4524 <https://github.com/pymupdf/PyMuPDF/issues/4524>`_: fitz.get_text ignores 'pages' kwarg
|
|
13
|
+
* **Fixed** `4412 <https://github.com/pymupdf/PyMuPDF/issues/4412>`_: Regression? Spurious error? in insert_pdf in v1.25.4
|
|
14
|
+
|
|
15
|
+
* Other:
|
|
16
|
+
|
|
17
|
+
* Partial fix for `4503 <https://github.com/pymupdf/PyMuPDF/issues/4503>`_: Undetected character styles
|
|
18
|
+
* New method `Document.rewrite_images()`, useful for reducing file size, changing image formats, or converting color spaces.
|
|
19
|
+
* `Page.get_text()`: restrict positional args to match docs.
|
|
20
|
+
* Removed bogus definition of class `Shape`.
|
|
21
|
+
* Removed release date from module, docs and changelog.
|
|
22
|
+
* `pymupdf.pymupdf_date` and `pymupdf.VersionDate` are now both None.
|
|
23
|
+
* They will be removed in a future release.
|
|
24
|
+
|
|
25
|
+
|
|
5
26
|
**Changes in version 1.26.0 (2025-05-22)**
|
|
6
27
|
|
|
7
28
|
* Use MuPDF-1.26.1.
|
|
@@ -32,7 +53,9 @@ Change Log
|
|
|
32
53
|
* Added runtime assert that that PyMuPDF and MuPDF were built with compatible
|
|
33
54
|
NDEBUG settings (related to `4390 <https://github.com/pymupdf/PyMuPDF/issues/4390>`_).
|
|
34
55
|
* Simplified handling of filename/filetype when opening documents.
|
|
35
|
-
|
|
56
|
+
* Removed PDF linearization support.
|
|
57
|
+
* Calls to `Document.save()` with `linear` set to true will now raise an exception.
|
|
58
|
+
* See https://artifex.com/blog/mupdf-removes-linearisation for more information.
|
|
36
59
|
|
|
37
60
|
**Changes in version 1.25.5 (2025-03-31)**
|
|
38
61
|
|
|
@@ -21,6 +21,7 @@ import io
|
|
|
21
21
|
import os
|
|
22
22
|
import platform
|
|
23
23
|
import re
|
|
24
|
+
import shlex
|
|
24
25
|
import shutil
|
|
25
26
|
import site
|
|
26
27
|
import subprocess
|
|
@@ -654,12 +655,12 @@ class Package:
|
|
|
654
655
|
z.writestr(f'{dist_info_dir}/RECORD', record.get(f'{dist_info_dir}/RECORD'))
|
|
655
656
|
|
|
656
657
|
st = os.stat(path)
|
|
657
|
-
log1( f'Have created wheel size={st.st_size}: {path}')
|
|
658
|
+
log1( f'Have created wheel size={st.st_size:,}: {path}')
|
|
658
659
|
if g_verbose >= 2:
|
|
659
660
|
with zipfile.ZipFile(path, compression=self.wheel_compression) as z:
|
|
660
661
|
log2(f'Contents are:')
|
|
661
662
|
for zi in sorted(z.infolist(), key=lambda z: z.filename):
|
|
662
|
-
log2(f' {zi.file_size:
|
|
663
|
+
log2(f' {zi.file_size: 10,d} {zi.filename}')
|
|
663
664
|
|
|
664
665
|
return os.path.basename(path)
|
|
665
666
|
|
|
@@ -1901,6 +1902,105 @@ def git_items( directory, submodules=False):
|
|
|
1901
1902
|
return ret
|
|
1902
1903
|
|
|
1903
1904
|
|
|
1905
|
+
def git_get(
|
|
1906
|
+
remote,
|
|
1907
|
+
local,
|
|
1908
|
+
*,
|
|
1909
|
+
branch=None,
|
|
1910
|
+
depth=1,
|
|
1911
|
+
env_extra=None,
|
|
1912
|
+
tag=None,
|
|
1913
|
+
update=True,
|
|
1914
|
+
submodules=True,
|
|
1915
|
+
):
|
|
1916
|
+
'''
|
|
1917
|
+
Ensures that <local> is a git checkout (at either <tag>, or <branch> HEAD)
|
|
1918
|
+
of a remote repository.
|
|
1919
|
+
|
|
1920
|
+
Exactly one of <branch> and <tag> must be specified.
|
|
1921
|
+
|
|
1922
|
+
Args:
|
|
1923
|
+
remote:
|
|
1924
|
+
Remote git repostitory, for example
|
|
1925
|
+
'https://github.com/ArtifexSoftware/mupdf.git'.
|
|
1926
|
+
local:
|
|
1927
|
+
Local directory. If <local>/.git exists, we attempt to run `git
|
|
1928
|
+
update` in it.
|
|
1929
|
+
branch:
|
|
1930
|
+
Branch to use.
|
|
1931
|
+
depth:
|
|
1932
|
+
Depth of local checkout when cloning and fetching, or None.
|
|
1933
|
+
env_extra:
|
|
1934
|
+
Dict of extra name=value environment variables to use whenever we
|
|
1935
|
+
run git.
|
|
1936
|
+
tag:
|
|
1937
|
+
Tag to use.
|
|
1938
|
+
update:
|
|
1939
|
+
If false we do not update existing repository. Might be useful if
|
|
1940
|
+
testing without network access.
|
|
1941
|
+
submodules:
|
|
1942
|
+
If true, we clone with `--recursive --shallow-submodules` and run
|
|
1943
|
+
`git submodule update --init --recursive` before returning.
|
|
1944
|
+
'''
|
|
1945
|
+
log0(f'{remote=} {local=} {branch=} {tag=}')
|
|
1946
|
+
assert (branch and not tag) or (not branch and tag), f'Must specify exactly one of <branch> and <tag>.'
|
|
1947
|
+
|
|
1948
|
+
depth_arg = f' --depth {depth}' if depth else ''
|
|
1949
|
+
|
|
1950
|
+
def do_update():
|
|
1951
|
+
# This seems to pull in the entire repository.
|
|
1952
|
+
log0(f'do_update(): attempting to update {local=}.')
|
|
1953
|
+
# Remove any local changes.
|
|
1954
|
+
run(f'cd {local} && git checkout .', env_extra=env_extra)
|
|
1955
|
+
if tag:
|
|
1956
|
+
# `-u` avoids `fatal: Refusing to fetch into current branch`.
|
|
1957
|
+
# Using '+' and `revs/tags/` prefix seems to avoid errors like:
|
|
1958
|
+
# error: cannot update ref 'refs/heads/v3.16.44':
|
|
1959
|
+
# trying to write non-commit object
|
|
1960
|
+
# 06c4ae5fe39a03b37a25a8b95214d9f8f8a867b8 to branch
|
|
1961
|
+
# 'refs/heads/v3.16.44'
|
|
1962
|
+
#
|
|
1963
|
+
run(f'cd {local} && git fetch -fuv{depth_arg} {remote} +refs/tags/{tag}:refs/tags/{tag}', env_extra=env_extra)
|
|
1964
|
+
run(f'cd {local} && git checkout {tag}', env_extra=env_extra)
|
|
1965
|
+
if branch:
|
|
1966
|
+
# `-u` avoids `fatal: Refusing to fetch into current branch`.
|
|
1967
|
+
run(f'cd {local} && git fetch -fuv{depth_arg} {remote} {branch}:{branch}', env_extra=env_extra)
|
|
1968
|
+
run(f'cd {local} && git checkout {branch}', env_extra=env_extra)
|
|
1969
|
+
|
|
1970
|
+
do_clone = True
|
|
1971
|
+
if os.path.isdir(f'{local}/.git'):
|
|
1972
|
+
if update:
|
|
1973
|
+
# Try to update existing checkout.
|
|
1974
|
+
try:
|
|
1975
|
+
do_update()
|
|
1976
|
+
do_clone = False
|
|
1977
|
+
except Exception as e:
|
|
1978
|
+
log0(f'Failed to update existing checkout {local}: {e}')
|
|
1979
|
+
else:
|
|
1980
|
+
do_clone = False
|
|
1981
|
+
|
|
1982
|
+
if do_clone:
|
|
1983
|
+
# No existing git checkout, so do a fresh clone.
|
|
1984
|
+
#_fs_remove(local)
|
|
1985
|
+
log0(f'Cloning to: {local}')
|
|
1986
|
+
command = f'git clone --config core.longpaths=true{depth_arg}'
|
|
1987
|
+
if submodules:
|
|
1988
|
+
command += f' --recursive --shallow-submodules'
|
|
1989
|
+
if branch:
|
|
1990
|
+
command += f' -b {branch}'
|
|
1991
|
+
if tag:
|
|
1992
|
+
command += f' -b {tag}'
|
|
1993
|
+
command += f' {remote} {local}'
|
|
1994
|
+
run(command, env_extra=env_extra)
|
|
1995
|
+
do_update()
|
|
1996
|
+
|
|
1997
|
+
if submodules:
|
|
1998
|
+
run(f'cd {local} && git submodule update --init --recursive', env_extra=env_extra)
|
|
1999
|
+
|
|
2000
|
+
# Show sha of checkout.
|
|
2001
|
+
run( f'cd {local} && git show --pretty=oneline|head -n 1', check=False)
|
|
2002
|
+
|
|
2003
|
+
|
|
1904
2004
|
def run(
|
|
1905
2005
|
command,
|
|
1906
2006
|
*,
|
|
@@ -1951,9 +2051,14 @@ def run(
|
|
|
1951
2051
|
env = os.environ.copy()
|
|
1952
2052
|
env.update(env_extra)
|
|
1953
2053
|
lines = _command_lines( command)
|
|
1954
|
-
nl = '\n'
|
|
1955
2054
|
if verbose:
|
|
1956
|
-
|
|
2055
|
+
text = f'Running:'
|
|
2056
|
+
if env_extra:
|
|
2057
|
+
for k in sorted(env_extra.keys()):
|
|
2058
|
+
text += f' {k}={shlex.quote(env_extra[k])}'
|
|
2059
|
+
nl = '\n'
|
|
2060
|
+
text += f' {nl.join(lines)}'
|
|
2061
|
+
log1(text, caller=caller+1)
|
|
1957
2062
|
sep = ' ' if windows() else ' \\\n'
|
|
1958
2063
|
command2 = sep.join( lines)
|
|
1959
2064
|
cp = subprocess.run(
|
|
@@ -1990,6 +2095,39 @@ def linux():
|
|
|
1990
2095
|
def openbsd():
|
|
1991
2096
|
return platform.system() == 'OpenBSD'
|
|
1992
2097
|
|
|
2098
|
+
|
|
2099
|
+
def show_system():
|
|
2100
|
+
'''
|
|
2101
|
+
Show useful information about the system plus argv and environ.
|
|
2102
|
+
'''
|
|
2103
|
+
def log(text):
|
|
2104
|
+
log0(text, caller=3)
|
|
2105
|
+
|
|
2106
|
+
#log(f'{__file__=}')
|
|
2107
|
+
#log(f'{__name__=}')
|
|
2108
|
+
log(f'{os.getcwd()=}')
|
|
2109
|
+
log(f'{platform.machine()=}')
|
|
2110
|
+
log(f'{platform.platform()=}')
|
|
2111
|
+
log(f'{platform.python_version()=}')
|
|
2112
|
+
log(f'{platform.system()=}')
|
|
2113
|
+
log(f'{platform.uname()=}')
|
|
2114
|
+
log(f'{sys.executable=}')
|
|
2115
|
+
log(f'{sys.version=}')
|
|
2116
|
+
log(f'{sys.version_info=}')
|
|
2117
|
+
log(f'{list(sys.version_info)=}')
|
|
2118
|
+
|
|
2119
|
+
log(f'CPU bits: {cpu_bits()}')
|
|
2120
|
+
|
|
2121
|
+
log(f'sys.argv ({len(sys.argv)}):')
|
|
2122
|
+
for i, arg in enumerate(sys.argv):
|
|
2123
|
+
log(f' {i}: {arg!r}')
|
|
2124
|
+
|
|
2125
|
+
log(f'os.environ ({len(os.environ)}):')
|
|
2126
|
+
for k in sorted( os.environ.keys()):
|
|
2127
|
+
v = os.environ[ k]
|
|
2128
|
+
log( f' {k}: {v!r}')
|
|
2129
|
+
|
|
2130
|
+
|
|
1993
2131
|
class PythonFlags:
|
|
1994
2132
|
'''
|
|
1995
2133
|
Compile/link flags for the current python, for example the include path
|
|
@@ -2164,6 +2302,10 @@ def _command_lines( command):
|
|
|
2164
2302
|
return lines
|
|
2165
2303
|
|
|
2166
2304
|
|
|
2305
|
+
def cpu_bits():
|
|
2306
|
+
return int.bit_length(sys.maxsize+1)
|
|
2307
|
+
|
|
2308
|
+
|
|
2167
2309
|
def _cpu_name():
|
|
2168
2310
|
'''
|
|
2169
2311
|
Returns `x32` or `x64` depending on Python build.
|
|
@@ -2418,7 +2560,7 @@ def log2(text='', caller=1):
|
|
|
2418
2560
|
|
|
2419
2561
|
def _log(text, level, caller):
|
|
2420
2562
|
'''
|
|
2421
|
-
Logs lines with prefix
|
|
2563
|
+
Logs lines with prefix, if <level> is lower than <g_verbose>.
|
|
2422
2564
|
'''
|
|
2423
2565
|
if level <= g_verbose:
|
|
2424
2566
|
fr = inspect.stack(context=0)[caller]
|
|
@@ -2445,49 +2587,6 @@ def relpath(path, start=None):
|
|
|
2445
2587
|
return os.path.relpath(path, start)
|
|
2446
2588
|
|
|
2447
2589
|
|
|
2448
|
-
def number_sep( s):
|
|
2449
|
-
'''
|
|
2450
|
-
Simple number formatter, adds commas in-between thousands. `s` can be a
|
|
2451
|
-
number or a string. Returns a string.
|
|
2452
|
-
|
|
2453
|
-
>>> number_sep(1)
|
|
2454
|
-
'1'
|
|
2455
|
-
>>> number_sep(12)
|
|
2456
|
-
'12'
|
|
2457
|
-
>>> number_sep(123)
|
|
2458
|
-
'123'
|
|
2459
|
-
>>> number_sep(1234)
|
|
2460
|
-
'1,234'
|
|
2461
|
-
>>> number_sep(12345)
|
|
2462
|
-
'12,345'
|
|
2463
|
-
>>> number_sep(123456)
|
|
2464
|
-
'123,456'
|
|
2465
|
-
>>> number_sep(1234567)
|
|
2466
|
-
'1,234,567'
|
|
2467
|
-
>>> number_sep(-131072)
|
|
2468
|
-
'-131,072'
|
|
2469
|
-
'''
|
|
2470
|
-
if not isinstance( s, str):
|
|
2471
|
-
s = str( s)
|
|
2472
|
-
ret = ''
|
|
2473
|
-
if s.startswith('-'):
|
|
2474
|
-
ret += '-'
|
|
2475
|
-
s = s[1:]
|
|
2476
|
-
c = s.find( '.')
|
|
2477
|
-
if c==-1: c = len(s)
|
|
2478
|
-
end = s.find('e')
|
|
2479
|
-
if end == -1: end = s.find('E')
|
|
2480
|
-
if end == -1: end = len(s)
|
|
2481
|
-
for i in range( end):
|
|
2482
|
-
ret += s[i]
|
|
2483
|
-
if i<c-1 and (c-i-1)%3==0:
|
|
2484
|
-
ret += ','
|
|
2485
|
-
elif i>c and i<end-1 and (i-c)%3==0:
|
|
2486
|
-
ret += ','
|
|
2487
|
-
ret += s[end:]
|
|
2488
|
-
return ret
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
2590
|
def _so_suffix(use_so_versioning=True):
|
|
2492
2591
|
'''
|
|
2493
2592
|
Filename suffix for shared libraries is defined in pep-3149. The
|
|
@@ -2619,3 +2718,51 @@ class _Record:
|
|
|
2619
2718
|
if record_path:
|
|
2620
2719
|
ret += f'{record_path},,\n'
|
|
2621
2720
|
return ret
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
class NewFiles:
|
|
2724
|
+
'''
|
|
2725
|
+
Detects new/modified/updated files matching a glob pattern. Useful for
|
|
2726
|
+
detecting wheels created by pip or cubuildwheel etc.
|
|
2727
|
+
'''
|
|
2728
|
+
def __init__(self, glob_pattern):
|
|
2729
|
+
# Find current matches of <glob_pattern>.
|
|
2730
|
+
self.glob_pattern = glob_pattern
|
|
2731
|
+
self.items0 = self._items()
|
|
2732
|
+
def get(self):
|
|
2733
|
+
'''
|
|
2734
|
+
Returns list of new matches of <glob_pattern> - paths of files that
|
|
2735
|
+
were not present previously, or have different mtimes or have different
|
|
2736
|
+
contents.
|
|
2737
|
+
'''
|
|
2738
|
+
ret = list()
|
|
2739
|
+
items = self._items()
|
|
2740
|
+
for path, id_ in items.items():
|
|
2741
|
+
id0 = self.items0.get(path)
|
|
2742
|
+
if id0 != id_:
|
|
2743
|
+
#mtime0, hash0 = id0
|
|
2744
|
+
#mtime1, hash1 = id_
|
|
2745
|
+
#log0(f'New/modified file {path=}.')
|
|
2746
|
+
#log0(f' {mtime0=} {"==" if mtime0==mtime1 else "!="} {mtime1=}.')
|
|
2747
|
+
#log0(f' {hash0=} {"==" if hash0==hash1 else "!="} {hash1=}.')
|
|
2748
|
+
ret.append(path)
|
|
2749
|
+
return ret
|
|
2750
|
+
def get_one(self):
|
|
2751
|
+
'''
|
|
2752
|
+
Returns new match of <glob_pattern>, asserting that there is exactly
|
|
2753
|
+
one.
|
|
2754
|
+
'''
|
|
2755
|
+
ret = self.get()
|
|
2756
|
+
assert len(ret) == 1, f'{len(ret)=}'
|
|
2757
|
+
return ret[0]
|
|
2758
|
+
def _file_id(self, path):
|
|
2759
|
+
mtime = os.stat(path).st_mtime
|
|
2760
|
+
with open(path, 'rb') as f:
|
|
2761
|
+
hash_ = hashlib.file_digest(f, hashlib.md5).digest()
|
|
2762
|
+
return mtime, hash_
|
|
2763
|
+
def _items(self):
|
|
2764
|
+
ret = dict()
|
|
2765
|
+
for path in glob.glob(self.glob_pattern):
|
|
2766
|
+
if os.path.isfile(path):
|
|
2767
|
+
ret[path] = self._file_id(path)
|
|
2768
|
+
return ret
|