PyMuPDF 1.26.1__tar.gz → 1.26.4__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.1 → pymupdf-1.26.4}/PKG-INFO +1 -1
- {pymupdf-1.26.1 → pymupdf-1.26.4}/changes.txt +52 -1
- {pymupdf-1.26.1 → pymupdf-1.26.4}/pipcl.py +393 -29
- {pymupdf-1.26.1 → pymupdf-1.26.4}/scripts/sysinstall.py +20 -4
- {pymupdf-1.26.1 → pymupdf-1.26.4}/scripts/test.py +209 -54
- {pymupdf-1.26.1 → pymupdf-1.26.4}/setup.py +67 -29
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/__init__.py +76 -47
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/table.py +126 -3
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/utils.py +6 -2
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/README.md +8 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/conftest.py +63 -6
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/gentle_compare.py +9 -10
- pymupdf-1.26.4/tests/resources/test-styled-table.pdf +0 -0
- pymupdf-1.26.4/tests/resources/test_3806-expected.png +0 -0
- pymupdf-1.26.4/tests/resources/test_3806.pdf +0 -0
- pymupdf-1.26.4/tests/resources/test_4388_BOZ1.pdf +0 -0
- pymupdf-1.26.4/tests/resources/test_4388_BUL1.pdf +0 -0
- pymupdf-1.26.4/tests/resources/test_4496.hwpx +0 -0
- pymupdf-1.26.4/tests/resources/test_4503.pdf +0 -0
- pymupdf-1.26.4/tests/resources/test_4564.pdf +51 -0
- pymupdf-1.26.4/tests/resources/test_4571.pdf +0 -0
- pymupdf-1.26.4/tests/resources/test_4614.pdf +5843 -7
- pymupdf-1.26.4/tests/resources/test_4639.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/run_compound.py +2 -1
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_2548.py +5 -1
- pymupdf-1.26.4/tests/test_4503.py +38 -0
- pymupdf-1.26.4/tests/test_4614.py +10 -0
- pymupdf-1.26.4/tests/test_clip_page.py +37 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_font.py +32 -26
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_general.py +188 -31
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_insertpdf.py +19 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_memory.py +6 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_pagedelete.py +22 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_pixmap.py +49 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_pylint.py +1 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_story.py +4 -1
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_tables.py +45 -10
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_textextract.py +87 -46
- {pymupdf-1.26.1 → pymupdf-1.26.4}/COPYING +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/README.md +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/READMEb.md +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/READMEd.md +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/pyproject.toml +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/pytest.ini +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/scripts/gh_release.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/__main__.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/_apply_pages.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/_wxcolors.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/extra.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/fitz___init__.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/fitz_table.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/fitz_utils.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src/pymupdf.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/__init__.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/__main__.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/_config.h +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/fitz_old.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-annot.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-convert.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-defines.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-devices.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-fields.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-fileobj.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-geo-c.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-geo-py.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-globals.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-other.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-pdfinfo.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-pixmap.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-portfolio.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-python.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-select.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-stext.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/helper-xobject.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/utils.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/src_classic/version.i +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/001003ED.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/1.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/2.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/2201.00069.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/3.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/4.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/Bezier.epub +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/PragmaticaC.otf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/battery-file-22.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/bug1945.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/bug1971.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/chinese-tables.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/chinese-tables.pickle +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/circular-toc.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/cms-etc-filled.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/cython.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/cython.pickle +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/dotted-gridlines.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/full_toc.txt +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/github_sample.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/has-bad-fonts.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/image-file1.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/img-regular.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/img-transparent.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/img-transparent.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/interfield-calculation.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/joined.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/merge-form1.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/merge-form2.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/metadata.txt +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/mupdf_explored.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/nur-ruhig.jpg +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/quad-calc-0.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/simple_toc.txt +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/small-table.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/strict-yes-no.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/symbol-list.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/symbols.txt +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-2333.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-2462.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-2812.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-3143.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-3150.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-3207.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-3591.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-3820.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-4055.pdf +0 -0
- /pymupdf-1.26.1/tests/resources/test_4503.pdf → /pymupdf-1.26.4/tests/resources/test-4503.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-707448.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-707673.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-E+A.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-linebreaks.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test-rewrite-images.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test2093.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test2182.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test2238.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_1645_expected.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_1824.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2108.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2270.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2533.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2548.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2553-2.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2553.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2596.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2608_expected +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2608_expected_1.26 +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2634.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2635.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2645_1.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2645_2.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2645_3.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2710.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2730.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2742.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2788.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2791_content.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2791_coverpage.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2861.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2871.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2885.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2904.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2907.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2954.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2957_1.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2957_2.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2969.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_2979.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3050_expected.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3058.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3062.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3070.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3072.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3087.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3179.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3186.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3197.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3357.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3362.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3376.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3448.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3448.pdf-expected.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3450.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3493.epub +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3569.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3594.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3615.epub +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3624.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3624_expected.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3650.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3654.docx +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3677.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3687-3.epub +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3687.epub +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3705.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3725.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3727.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3780.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3789.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3842.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3848.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3854.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3854_expected.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3863.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3863.pdf.pdf.0.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3863.pdf.pdf.1.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3863.pdf.pdf.2.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3863.pdf.pdf.3.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3863.pdf.pdf.4.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3863.pdf.pdf.5.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3863.pdf.pdf.6.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3863.pdf.pdf.7.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3886.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3887.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3933.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3950.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_3994.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4004.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4017.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4026.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4034.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4043.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4047.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4079.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4079_after.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4079_after_1.25.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4090.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4125.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4139.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4141.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4147.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4179.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4179_expected.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4180.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4180_expected.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4182.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4182_expected.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4224.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4245.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4245_expected.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4263.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4363.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4412.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4415.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4415_out_expected.png +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4423.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4435.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4479.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4505.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_4546.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_annot_file_info.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_delete_image.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.cbz +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.doc +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.docx +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.epub +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.fb2 +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.html +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.jpg +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.mobi +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.svg +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.xhtml +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.xml +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2.xps +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_open2_expected.json +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/test_toc_count.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/text-find-ligatures.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/type3font.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/v110-changes.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/resources/widgettest.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_2634.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_2904.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_2907.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_4141.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_4466.pdf +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_4505.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_4520.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_annots.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_badfonts.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_balance_count.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_barcode.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_cluster_drawings.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_codespell.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_crypting.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_docs_samples.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_drawings.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_embeddedfiles.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_extractimage.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_flake8.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_geometry.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_imagebbox.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_imagemasks.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_import.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_insertimage.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_linebreaks.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_linequad.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_metadata.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_mupdf_regressions.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_named_links.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_nonpdf.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_object_manipulation.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_objectstreams.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_optional_content.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_page_links.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_pagelabels.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_remove-rotation.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_rewrite_images.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_rtl.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_showpdfpage.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_spikes.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_tesseract.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_textbox.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_textsearch.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_toc.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_widgets.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/test_word_delimiters.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/tests/util.py +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/valgrind.supp +0 -0
- {pymupdf-1.26.1 → pymupdf-1.26.4}/wdev.py +0 -0
|
@@ -2,7 +2,57 @@ Change Log
|
|
|
2
2
|
==========
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
**Changes in version 1.26.
|
|
5
|
+
**Changes in version 1.26.4**
|
|
6
|
+
|
|
7
|
+
* Use MuPDF-1.26.7.
|
|
8
|
+
|
|
9
|
+
* Fixed issues:
|
|
10
|
+
|
|
11
|
+
* **Fixed** `3806 <https://github.com/pymupdf/PyMuPDF/issues/3806>`_: pdf to image rendering ignore optional content offs
|
|
12
|
+
* **Fixed** `4388 <https://github.com/pymupdf/PyMuPDF/issues/4388>`_: Incorrect PixMap from page due to cached data from other PDF
|
|
13
|
+
* **Fixed** `4457 <https://github.com/pymupdf/PyMuPDF/issues/4457>`_: Wrong characters displayed after font subsetting (w/ native method)
|
|
14
|
+
* **Fixed** `4462 <https://github.com/pymupdf/PyMuPDF/issues/4462>`_: delete_pages() does not accept a single int
|
|
15
|
+
* **Fixed** `4533 <https://github.com/pymupdf/PyMuPDF/issues/4533>`_: Open PDF error segmentation fault
|
|
16
|
+
* **Fixed** `4565 <https://github.com/pymupdf/PyMuPDF/issues/4565>`_: MacOS uses Tesseract and not Tesseract-OCR
|
|
17
|
+
* **Fixed** `4571 <https://github.com/pymupdf/PyMuPDF/issues/4571>`_: Broken merged pdfs.
|
|
18
|
+
* **Fixed** `4590 <https://github.com/pymupdf/PyMuPDF/issues/4590>`_: TypeError in utils.py scrub(): annot.update_file(buffer=...) is invalid
|
|
19
|
+
* **Fixed** `4614 <https://github.com/pymupdf/PyMuPDF/issues/4614>`_: Intercept bad widgets when inserting to another PDF
|
|
20
|
+
* **Fixed** `4639 <https://github.com/pymupdf/PyMuPDF/issues/4639>`_: pymupdf.mupdf.FzErrorGeneric: code=1: Director error: <class 'AttributeError'>: 'JM_new_bbox_device_Device' object has no attribute 'layer_name'
|
|
21
|
+
|
|
22
|
+
* Other:
|
|
23
|
+
|
|
24
|
+
* Check that #4392 `Segfault when running with pytest and -Werror` is fixed if PyMuPDF is built with swig>=4.4.
|
|
25
|
+
* Add `Page.clip_to_rect()`.
|
|
26
|
+
* Improved search for Tesseract data.
|
|
27
|
+
* Retrospectively mark #4496 as fixed in 1.26.1.
|
|
28
|
+
* Retrospectively mark #4503 as fixed in 1.26.3.
|
|
29
|
+
* Added experimental support for Graal.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
**Changes in version 1.26.3 (2025-07-02)**
|
|
33
|
+
|
|
34
|
+
* Use MuPDF-1.26.3.
|
|
35
|
+
|
|
36
|
+
* Fixed issues:
|
|
37
|
+
|
|
38
|
+
* **Fixed** `4462 <https://github.com/pymupdf/PyMuPDF/issues/4462>`_: delete_pages() does not accept a single int
|
|
39
|
+
* **Fixed** `4503 <https://github.com/pymupdf/PyMuPDF/issues/4503>`_: Undetected character styles
|
|
40
|
+
* **Fixed** `4527 <https://github.com/pymupdf/PyMuPDF/issues/4527>`_: Rect.intersects() is much slower than necessary
|
|
41
|
+
* **Fixed** `4564 <https://github.com/pymupdf/PyMuPDF/issues/4564>`_: Possible encoding issue in PDF metadata
|
|
42
|
+
* **Fixed** `4575 <https://github.com/pymupdf/PyMuPDF/issues/4575>`_: Bug with IRect contains method
|
|
43
|
+
|
|
44
|
+
* Other:
|
|
45
|
+
|
|
46
|
+
* Class Shape is now available as pymupdf.Shape.
|
|
47
|
+
* Added table cell markdown support.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
**Changes in version 1.26.2**
|
|
51
|
+
|
|
52
|
+
[Skipped.]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
**Changes in version 1.26.1 (2025-06-11)**
|
|
6
56
|
|
|
7
57
|
* Use MuPDF-1.26.2.
|
|
8
58
|
|
|
@@ -11,6 +61,7 @@ Change Log
|
|
|
11
61
|
* **Fixed** `4520 <https://github.com/pymupdf/PyMuPDF/issues/4520>`_: show_pdf_page does not like empty pages created by new_page
|
|
12
62
|
* **Fixed** `4524 <https://github.com/pymupdf/PyMuPDF/issues/4524>`_: fitz.get_text ignores 'pages' kwarg
|
|
13
63
|
* **Fixed** `4412 <https://github.com/pymupdf/PyMuPDF/issues/4412>`_: Regression? Spurious error? in insert_pdf in v1.25.4
|
|
64
|
+
* **Fixed** `4496 <https://github.com/pymupdf/PyMuPDF/issues/4496>`_: pymupdf4llm with pymupdfpro
|
|
14
65
|
|
|
15
66
|
* Other:
|
|
16
67
|
|
|
@@ -11,9 +11,14 @@ a SWIG extension, but we also give access to the located compiler/linker so
|
|
|
11
11
|
that a `setup.py` script can take over the details itself.
|
|
12
12
|
|
|
13
13
|
Run doctests with: `python -m doctest pipcl.py`
|
|
14
|
+
|
|
15
|
+
For Graal we require that PIPCL_GRAAL_PYTHON is set to non-graal Python (we
|
|
16
|
+
build for non-graal except with Graal Python's include paths and library
|
|
17
|
+
directory).
|
|
14
18
|
'''
|
|
15
19
|
|
|
16
20
|
import base64
|
|
21
|
+
import codecs
|
|
17
22
|
import glob
|
|
18
23
|
import hashlib
|
|
19
24
|
import inspect
|
|
@@ -572,6 +577,11 @@ class Package:
|
|
|
572
577
|
|
|
573
578
|
self.wheel_compression = wheel_compression
|
|
574
579
|
self.wheel_compresslevel = wheel_compresslevel
|
|
580
|
+
|
|
581
|
+
# If true and we are building for graal, we set PIPCL_PYTHON_CONFIG to
|
|
582
|
+
# a command that will print includes/libs from graal_py's sysconfig.
|
|
583
|
+
#
|
|
584
|
+
self.graal_legacy_python_config = True
|
|
575
585
|
|
|
576
586
|
|
|
577
587
|
def build_wheel(self,
|
|
@@ -592,6 +602,59 @@ class Package:
|
|
|
592
602
|
f' metadata_directory={metadata_directory!r}'
|
|
593
603
|
)
|
|
594
604
|
|
|
605
|
+
if sys.implementation.name == 'graalpy':
|
|
606
|
+
# We build for Graal by building a native Python wheel with Graal
|
|
607
|
+
# Python's include paths and library directory. We then rename the
|
|
608
|
+
# wheel to contain graal's tag etc.
|
|
609
|
+
#
|
|
610
|
+
log0(f'### Graal build: deferring to cpython.')
|
|
611
|
+
python_native = os.environ.get('PIPCL_GRAAL_PYTHON')
|
|
612
|
+
assert python_native, f'Graal build requires that PIPCL_GRAAL_PYTHON is set.'
|
|
613
|
+
env_extra = dict(
|
|
614
|
+
PIPCL_SYSCONFIG_PATH_include = sysconfig.get_path('include'),
|
|
615
|
+
PIPCL_SYSCONFIG_PATH_platinclude = sysconfig.get_path('platinclude'),
|
|
616
|
+
PIPCL_SYSCONFIG_CONFIG_VAR_LIBDIR = sysconfig.get_config_var('LIBDIR'),
|
|
617
|
+
)
|
|
618
|
+
# Tell native build to run pipcl.py itself to get python-config
|
|
619
|
+
# information about include paths etc.
|
|
620
|
+
if self.graal_legacy_python_config:
|
|
621
|
+
env_extra['PIPCL_PYTHON_CONFIG'] = f'{python_native} {os.path.abspath(__file__)} --graal-legacy-python-config'
|
|
622
|
+
|
|
623
|
+
# Create venv.
|
|
624
|
+
venv_name = os.environ.get('PIPCL_GRAAL_NATIVE_VENV')
|
|
625
|
+
if venv_name:
|
|
626
|
+
log1(f'Graal using pre-existing {venv_name=}')
|
|
627
|
+
else:
|
|
628
|
+
venv_name = 'venv-pipcl-graal-native'
|
|
629
|
+
run(f'{shlex.quote(python_native)} -m venv {venv_name}')
|
|
630
|
+
log1(f'Graal using {venv_name=}')
|
|
631
|
+
|
|
632
|
+
newfiles = NewFiles(f'{wheel_directory}/*.whl')
|
|
633
|
+
run(
|
|
634
|
+
f'. {venv_name}/bin/activate && python setup.py --dist-dir {shlex.quote(wheel_directory)} bdist_wheel',
|
|
635
|
+
env_extra = env_extra,
|
|
636
|
+
prefix = f'pipcl.py graal {python_native}: ',
|
|
637
|
+
)
|
|
638
|
+
wheel = newfiles.get_one()
|
|
639
|
+
wheel_leaf = os.path.basename(wheel)
|
|
640
|
+
python_major_minor = run(f'{shlex.quote(python_native)} -c "import platform; import sys; sys.stdout.write(str().join(platform.python_version_tuple()[:2]))"', capture=1)
|
|
641
|
+
cpabi = f'cp{python_major_minor}-abi3'
|
|
642
|
+
assert cpabi in wheel_leaf, f'Expected wheel to be for {cpabi=}, but {wheel=}.'
|
|
643
|
+
graalpy_ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')
|
|
644
|
+
log1(f'{graalpy_ext_suffix=}')
|
|
645
|
+
m = re.match(r'\.graalpy(\d+[^\-]*)-(\d+)', graalpy_ext_suffix)
|
|
646
|
+
gpver = m[1]
|
|
647
|
+
cpver = m[2]
|
|
648
|
+
graalpy_wheel_tag = f'graalpy{cpver}-graalpy{gpver}_{cpver}_native'
|
|
649
|
+
name = wheel_leaf.replace(cpabi, graalpy_wheel_tag)
|
|
650
|
+
destination = f'{wheel_directory}/{name}'
|
|
651
|
+
log0(f'### Graal build: copying {wheel=} to {destination=}')
|
|
652
|
+
# Copying results in two wheels which appears to confuse pip, showing:
|
|
653
|
+
# Found multiple .whl files; unspecified behaviour. Will call build_wheel.
|
|
654
|
+
os.rename(wheel, destination)
|
|
655
|
+
log1(f'Returning {name=}.')
|
|
656
|
+
return name
|
|
657
|
+
|
|
595
658
|
wheel_name = self.wheel_name()
|
|
596
659
|
path = f'{wheel_directory}/{wheel_name}'
|
|
597
660
|
|
|
@@ -1137,6 +1200,10 @@ class Package:
|
|
|
1137
1200
|
assert command is None, 'Two commands specified: {command} and {arg}.'
|
|
1138
1201
|
command = arg
|
|
1139
1202
|
|
|
1203
|
+
elif arg in ('windows-vs', 'windows-python', 'show-sysconfig'):
|
|
1204
|
+
assert command is None, 'Two commands specified: {command} and {arg}.'
|
|
1205
|
+
command = arg
|
|
1206
|
+
|
|
1140
1207
|
elif arg == '--all': opt_all = True
|
|
1141
1208
|
elif arg == '--compile': pass
|
|
1142
1209
|
elif arg == '--dist-dir' or arg == '-d': opt_dist_dir = args.next()
|
|
@@ -1149,12 +1216,6 @@ class Package:
|
|
|
1149
1216
|
elif arg == '--single-version-externally-managed': pass
|
|
1150
1217
|
elif arg == '--verbose' or arg == '-v': g_verbose += 1
|
|
1151
1218
|
|
|
1152
|
-
elif arg == 'windows-vs':
|
|
1153
|
-
command = arg
|
|
1154
|
-
break
|
|
1155
|
-
elif arg == 'windows-python':
|
|
1156
|
-
command = arg
|
|
1157
|
-
break
|
|
1158
1219
|
else:
|
|
1159
1220
|
raise Exception(f'Unrecognised arg: {arg}')
|
|
1160
1221
|
|
|
@@ -1205,6 +1266,39 @@ class Package:
|
|
|
1205
1266
|
vs = wdev.WindowsVS(year=year, grade=grade, version=version)
|
|
1206
1267
|
print(f'Visual Studio is:\n{vs.description_ml(" ")}')
|
|
1207
1268
|
|
|
1269
|
+
elif command == 'show-sysconfig':
|
|
1270
|
+
show_sysconfig()
|
|
1271
|
+
for mod in platform, sys:
|
|
1272
|
+
log0(f'{mod.__name__}:')
|
|
1273
|
+
for n in dir(mod):
|
|
1274
|
+
if n.startswith('_'):
|
|
1275
|
+
continue
|
|
1276
|
+
log0(f'{mod.__name__}.{n}')
|
|
1277
|
+
if mod is platform and n == 'uname':
|
|
1278
|
+
continue
|
|
1279
|
+
if mod is platform and n == 'pdb':
|
|
1280
|
+
continue
|
|
1281
|
+
if mod is sys and n in ('breakpointhook', 'exit'):
|
|
1282
|
+
# We don't want to call these.
|
|
1283
|
+
continue
|
|
1284
|
+
v = getattr(mod, n)
|
|
1285
|
+
if callable(v):
|
|
1286
|
+
try:
|
|
1287
|
+
v = v()
|
|
1288
|
+
except Exception:
|
|
1289
|
+
pass
|
|
1290
|
+
else:
|
|
1291
|
+
#print(f'{n=}', flush=1)
|
|
1292
|
+
try:
|
|
1293
|
+
print(f' {mod.__name__}.{n}()={v!r}')
|
|
1294
|
+
except Exception:
|
|
1295
|
+
print(f' Failed to print value of {mod.__name__}.{n}().')
|
|
1296
|
+
else:
|
|
1297
|
+
try:
|
|
1298
|
+
print(f' {mod.__name__}.{n}={v!r}')
|
|
1299
|
+
except Exception:
|
|
1300
|
+
print(f' Failed to print value of {mod.__name__}.{n}.')
|
|
1301
|
+
|
|
1208
1302
|
else:
|
|
1209
1303
|
assert 0, f'Unrecognised command: {command}'
|
|
1210
1304
|
|
|
@@ -1402,7 +1496,7 @@ def build_extension(
|
|
|
1402
1496
|
debug=False,
|
|
1403
1497
|
compiler_extra='',
|
|
1404
1498
|
linker_extra='',
|
|
1405
|
-
swig=
|
|
1499
|
+
swig=None,
|
|
1406
1500
|
cpp=True,
|
|
1407
1501
|
prerequisites_swig=None,
|
|
1408
1502
|
prerequisites_compile=None,
|
|
@@ -1453,7 +1547,7 @@ def build_extension(
|
|
|
1453
1547
|
linker_extra:
|
|
1454
1548
|
Extra linker flags. Can be None.
|
|
1455
1549
|
swig:
|
|
1456
|
-
|
|
1550
|
+
Swig command; if false we use 'swig'.
|
|
1457
1551
|
cpp:
|
|
1458
1552
|
If true we tell SWIG to generate C++ code instead of C.
|
|
1459
1553
|
prerequisites_swig:
|
|
@@ -1503,6 +1597,8 @@ def build_extension(
|
|
|
1503
1597
|
linker_extra = ''
|
|
1504
1598
|
if builddir is None:
|
|
1505
1599
|
builddir = outdir
|
|
1600
|
+
if not swig:
|
|
1601
|
+
swig = 'swig'
|
|
1506
1602
|
includes_text = _flags( includes, '-I')
|
|
1507
1603
|
defines_text = _flags( defines, '-D')
|
|
1508
1604
|
libpaths_text = _flags( libpaths, '/LIBPATH:', '"') if windows() else _flags( libpaths, '-L')
|
|
@@ -1863,6 +1959,34 @@ def base_linker(vs=None, pythonflags=None, cpp=False, use_env=True):
|
|
|
1863
1959
|
return linker, pythonflags
|
|
1864
1960
|
|
|
1865
1961
|
|
|
1962
|
+
def git_info( directory):
|
|
1963
|
+
'''
|
|
1964
|
+
Returns `(sha, comment, diff, branch)`, all items are str or None if not
|
|
1965
|
+
available.
|
|
1966
|
+
|
|
1967
|
+
directory:
|
|
1968
|
+
Root of git checkout.
|
|
1969
|
+
'''
|
|
1970
|
+
sha, comment, diff, branch = None, None, None, None
|
|
1971
|
+
e, out = run(
|
|
1972
|
+
f'cd {directory} && (PAGER= git show --pretty=oneline|head -n 1 && git diff)',
|
|
1973
|
+
capture=1,
|
|
1974
|
+
check=0
|
|
1975
|
+
)
|
|
1976
|
+
if not e:
|
|
1977
|
+
sha, _ = out.split(' ', 1)
|
|
1978
|
+
comment, diff = _.split('\n', 1)
|
|
1979
|
+
e, out = run(
|
|
1980
|
+
f'cd {directory} && git rev-parse --abbrev-ref HEAD',
|
|
1981
|
+
capture=1,
|
|
1982
|
+
check=0
|
|
1983
|
+
)
|
|
1984
|
+
if not e:
|
|
1985
|
+
branch = out.strip()
|
|
1986
|
+
log(f'git_info(): directory={directory!r} returning branch={branch!r} sha={sha!r} comment={comment!r}')
|
|
1987
|
+
return sha, comment, diff, branch
|
|
1988
|
+
|
|
1989
|
+
|
|
1866
1990
|
def git_items( directory, submodules=False):
|
|
1867
1991
|
'''
|
|
1868
1992
|
Returns list of paths for all files known to git within a `directory`.
|
|
@@ -1912,37 +2036,78 @@ def git_get(
|
|
|
1912
2036
|
tag=None,
|
|
1913
2037
|
update=True,
|
|
1914
2038
|
submodules=True,
|
|
2039
|
+
default_remote=None,
|
|
1915
2040
|
):
|
|
1916
2041
|
'''
|
|
1917
2042
|
Ensures that <local> is a git checkout (at either <tag>, or <branch> HEAD)
|
|
1918
2043
|
of a remote repository.
|
|
1919
2044
|
|
|
1920
|
-
Exactly one of <branch> and <tag> must be specified
|
|
2045
|
+
Exactly one of <branch> and <tag> must be specified, or <remote> must start
|
|
2046
|
+
with 'git:' and match the syntax described below.
|
|
1921
2047
|
|
|
1922
2048
|
Args:
|
|
1923
2049
|
remote:
|
|
1924
2050
|
Remote git repostitory, for example
|
|
1925
2051
|
'https://github.com/ArtifexSoftware/mupdf.git'.
|
|
2052
|
+
|
|
2053
|
+
If starts with 'git:', the remaining text should be a command-line
|
|
2054
|
+
style string containing some or all of these args:
|
|
2055
|
+
--branch <branch>
|
|
2056
|
+
--tag <tag>
|
|
2057
|
+
<remote>
|
|
2058
|
+
These overrides <branch>, <tag> and <default_remote>.
|
|
2059
|
+
|
|
2060
|
+
For example these all clone/update/branch master of https://foo.bar/qwerty.git to local
|
|
2061
|
+
checkout 'foo-local':
|
|
2062
|
+
|
|
2063
|
+
git_get('https://foo.bar/qwerty.git', 'foo-local', branch='master')
|
|
2064
|
+
git_get('git:--branch master https://foo.bar/qwerty.git', 'foo-local')
|
|
2065
|
+
git_get('git:--branch master', 'foo-local', default_remote='https://foo.bar/qwerty.git')
|
|
2066
|
+
git_get('git:', 'foo-local', branch='master', default_remote='https://foo.bar/qwerty.git')
|
|
2067
|
+
|
|
1926
2068
|
local:
|
|
1927
2069
|
Local directory. If <local>/.git exists, we attempt to run `git
|
|
1928
2070
|
update` in it.
|
|
1929
2071
|
branch:
|
|
1930
|
-
Branch to use.
|
|
2072
|
+
Branch to use. Is used as default if remote starts with 'git:'.
|
|
1931
2073
|
depth:
|
|
1932
2074
|
Depth of local checkout when cloning and fetching, or None.
|
|
1933
2075
|
env_extra:
|
|
1934
2076
|
Dict of extra name=value environment variables to use whenever we
|
|
1935
2077
|
run git.
|
|
1936
2078
|
tag:
|
|
1937
|
-
Tag to use.
|
|
2079
|
+
Tag to use. Is used as default if remote starts with 'git:'.
|
|
1938
2080
|
update:
|
|
1939
2081
|
If false we do not update existing repository. Might be useful if
|
|
1940
2082
|
testing without network access.
|
|
1941
2083
|
submodules:
|
|
1942
2084
|
If true, we clone with `--recursive --shallow-submodules` and run
|
|
1943
2085
|
`git submodule update --init --recursive` before returning.
|
|
2086
|
+
default_remote:
|
|
2087
|
+
The remote URL if <remote> starts with 'git:' but does not specify
|
|
2088
|
+
the remote URL.
|
|
1944
2089
|
'''
|
|
1945
2090
|
log0(f'{remote=} {local=} {branch=} {tag=}')
|
|
2091
|
+
if remote.startswith('git:'):
|
|
2092
|
+
remote0 = remote
|
|
2093
|
+
args = iter(shlex.split(remote0[len('git:'):]))
|
|
2094
|
+
remote = default_remote
|
|
2095
|
+
while 1:
|
|
2096
|
+
try:
|
|
2097
|
+
arg = next(args)
|
|
2098
|
+
except StopIteration:
|
|
2099
|
+
break
|
|
2100
|
+
if arg == '--branch':
|
|
2101
|
+
branch = next(args)
|
|
2102
|
+
tag = None
|
|
2103
|
+
elif arg == '--tag':
|
|
2104
|
+
tag == next(args)
|
|
2105
|
+
branch = None
|
|
2106
|
+
else:
|
|
2107
|
+
remote = arg
|
|
2108
|
+
assert remote, f'{default_remote=} and no remote specified in remote={remote0!r}.'
|
|
2109
|
+
assert branch or tag, f'{branch=} {tag=} and no branch/tag specified in remote={remote0!r}.'
|
|
2110
|
+
|
|
1946
2111
|
assert (branch and not tag) or (not branch and tag), f'Must specify exactly one of <branch> and <tag>.'
|
|
1947
2112
|
|
|
1948
2113
|
depth_arg = f' --depth {depth}' if depth else ''
|
|
@@ -2007,9 +2172,11 @@ def run(
|
|
|
2007
2172
|
capture=False,
|
|
2008
2173
|
check=1,
|
|
2009
2174
|
verbose=1,
|
|
2175
|
+
env=None,
|
|
2010
2176
|
env_extra=None,
|
|
2011
2177
|
timeout=None,
|
|
2012
2178
|
caller=1,
|
|
2179
|
+
prefix=None,
|
|
2013
2180
|
):
|
|
2014
2181
|
'''
|
|
2015
2182
|
Runs a command using `subprocess.run()`.
|
|
@@ -2032,12 +2199,22 @@ def run(
|
|
|
2032
2199
|
command's returncode in our return value.
|
|
2033
2200
|
verbose:
|
|
2034
2201
|
If true we show the command.
|
|
2202
|
+
env:
|
|
2203
|
+
None or dict to use instead of <os.environ>.
|
|
2035
2204
|
env_extra:
|
|
2036
|
-
None or dict to add to environ
|
|
2205
|
+
None or dict to add to <os.environ> or <env>.
|
|
2037
2206
|
timeout:
|
|
2038
2207
|
If not None, timeout in seconds; passed directly to
|
|
2039
2208
|
subprocess.run(). Note that on MacOS subprocess.run() seems to
|
|
2040
2209
|
leave processes running if timeout expires.
|
|
2210
|
+
prefix:
|
|
2211
|
+
String prefix for each line of output.
|
|
2212
|
+
|
|
2213
|
+
If true:
|
|
2214
|
+
* We run command with stdout=subprocess.PIPE and
|
|
2215
|
+
stderr=subprocess.STDOUT, repetaedly reading the command's output
|
|
2216
|
+
and writing it to stdout with <prefix>.
|
|
2217
|
+
* We do not support <timeout>, which must be None.
|
|
2041
2218
|
Returns:
|
|
2042
2219
|
check capture Return
|
|
2043
2220
|
--------------------------
|
|
@@ -2046,9 +2223,11 @@ def run(
|
|
|
2046
2223
|
true false None or raise exception
|
|
2047
2224
|
true true output or raise exception
|
|
2048
2225
|
'''
|
|
2049
|
-
env
|
|
2226
|
+
if env is None:
|
|
2227
|
+
env = os.environ
|
|
2228
|
+
if env_extra:
|
|
2229
|
+
env = env.copy()
|
|
2050
2230
|
if env_extra:
|
|
2051
|
-
env = os.environ.copy()
|
|
2052
2231
|
env.update(env_extra)
|
|
2053
2232
|
lines = _command_lines( command)
|
|
2054
2233
|
if verbose:
|
|
@@ -2061,16 +2240,59 @@ def run(
|
|
|
2061
2240
|
log1(text, caller=caller+1)
|
|
2062
2241
|
sep = ' ' if windows() else ' \\\n'
|
|
2063
2242
|
command2 = sep.join( lines)
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2243
|
+
|
|
2244
|
+
if prefix:
|
|
2245
|
+
assert not timeout, f'Timeout not supported with prefix.'
|
|
2246
|
+
child = subprocess.Popen(
|
|
2247
|
+
command2,
|
|
2248
|
+
shell=True,
|
|
2249
|
+
stdout=subprocess.PIPE,
|
|
2250
|
+
stderr=subprocess.STDOUT,
|
|
2251
|
+
encoding='utf8',
|
|
2252
|
+
env=env,
|
|
2253
|
+
)
|
|
2254
|
+
if capture:
|
|
2255
|
+
capture_text = ''
|
|
2256
|
+
decoder = codecs.getincrementaldecoder('utf8')('replace')
|
|
2257
|
+
line_start = True
|
|
2258
|
+
while 1:
|
|
2259
|
+
raw = os.read( child.stdout.fileno(), 10000)
|
|
2260
|
+
text = decoder.decode(raw, final=not raw)
|
|
2261
|
+
if text:
|
|
2262
|
+
if capture:
|
|
2263
|
+
capture_text += text
|
|
2264
|
+
lines = text.split('\n')
|
|
2265
|
+
for i, line in enumerate(lines):
|
|
2266
|
+
if line_start:
|
|
2267
|
+
sys.stdout.write(prefix)
|
|
2268
|
+
line_start = False
|
|
2269
|
+
sys.stdout.write(line)
|
|
2270
|
+
if i < len(lines) - 1:
|
|
2271
|
+
sys.stdout.write('\n')
|
|
2272
|
+
line_start = True
|
|
2273
|
+
sys.stdout.flush()
|
|
2274
|
+
if not raw:
|
|
2275
|
+
break
|
|
2276
|
+
if not line_start:
|
|
2277
|
+
sys.stdout.write('\n')
|
|
2278
|
+
e = child.wait()
|
|
2279
|
+
if check and e:
|
|
2280
|
+
raise subprocess.CalledProcessError(e, command2, capture_text if capture else None)
|
|
2281
|
+
if check:
|
|
2282
|
+
return capture_text if capture else None
|
|
2283
|
+
else:
|
|
2284
|
+
return (e, capture_text) if capture else e
|
|
2285
|
+
else:
|
|
2286
|
+
cp = subprocess.run(
|
|
2287
|
+
command2,
|
|
2288
|
+
shell=True,
|
|
2289
|
+
stdout=subprocess.PIPE if capture else None,
|
|
2290
|
+
stderr=subprocess.STDOUT if capture else None,
|
|
2291
|
+
check=check,
|
|
2292
|
+
encoding='utf8',
|
|
2293
|
+
env=env,
|
|
2294
|
+
timeout=timeout,
|
|
2295
|
+
)
|
|
2074
2296
|
if check:
|
|
2075
2297
|
return cp.stdout if capture else None
|
|
2076
2298
|
else:
|
|
@@ -2108,9 +2330,11 @@ def show_system():
|
|
|
2108
2330
|
log(f'{os.getcwd()=}')
|
|
2109
2331
|
log(f'{platform.machine()=}')
|
|
2110
2332
|
log(f'{platform.platform()=}')
|
|
2333
|
+
log(f'{platform.python_implementation()=}')
|
|
2111
2334
|
log(f'{platform.python_version()=}')
|
|
2112
2335
|
log(f'{platform.system()=}')
|
|
2113
|
-
|
|
2336
|
+
if sys.implementation.name != 'graalpy':
|
|
2337
|
+
log(f'{platform.uname()=}')
|
|
2114
2338
|
log(f'{sys.executable=}')
|
|
2115
2339
|
log(f'{sys.version=}')
|
|
2116
2340
|
log(f'{sys.version_info=}')
|
|
@@ -2143,8 +2367,23 @@ class PythonFlags:
|
|
|
2143
2367
|
String containing linker flags for library paths.
|
|
2144
2368
|
'''
|
|
2145
2369
|
def __init__(self):
|
|
2370
|
+
|
|
2371
|
+
# Experimental detection of python flags from sysconfig.*() instead of
|
|
2372
|
+
# python-config command.
|
|
2373
|
+
includes_, ldflags_ = sysconfig_python_flags()
|
|
2374
|
+
|
|
2375
|
+
if pyodide():
|
|
2376
|
+
_include_dir = os.environ[ 'PYO3_CROSS_INCLUDE_DIR']
|
|
2377
|
+
_lib_dir = os.environ[ 'PYO3_CROSS_LIB_DIR']
|
|
2378
|
+
self.includes = f'-I {_include_dir}'
|
|
2379
|
+
self.ldflags = f'-L {_lib_dir}'
|
|
2146
2380
|
|
|
2147
|
-
|
|
2381
|
+
elif 0:
|
|
2382
|
+
|
|
2383
|
+
self.includes = includes_
|
|
2384
|
+
self.ldflags = ldflags_
|
|
2385
|
+
|
|
2386
|
+
elif windows():
|
|
2148
2387
|
wp = wdev.WindowsPython()
|
|
2149
2388
|
self.includes = f'/I"{wp.include}"'
|
|
2150
2389
|
self.ldflags = f'/LIBPATH:"{wp.libs}"'
|
|
@@ -2213,8 +2452,10 @@ class PythonFlags:
|
|
|
2213
2452
|
log2(f'### Have removed `-lcrypt` from ldflags: {self.ldflags!r} -> {ldflags2!r}')
|
|
2214
2453
|
self.ldflags = ldflags2
|
|
2215
2454
|
|
|
2216
|
-
|
|
2217
|
-
|
|
2455
|
+
log1(f'{self.includes=}')
|
|
2456
|
+
log1(f' {includes_=}')
|
|
2457
|
+
log1(f'{self.ldflags=}')
|
|
2458
|
+
log1(f' {ldflags_=}')
|
|
2218
2459
|
|
|
2219
2460
|
|
|
2220
2461
|
def macos_add_cross_flags(command):
|
|
@@ -2758,7 +2999,10 @@ class NewFiles:
|
|
|
2758
2999
|
def _file_id(self, path):
|
|
2759
3000
|
mtime = os.stat(path).st_mtime
|
|
2760
3001
|
with open(path, 'rb') as f:
|
|
2761
|
-
|
|
3002
|
+
content = f.read()
|
|
3003
|
+
hash_ = hashlib.md5(content).digest()
|
|
3004
|
+
# With python >= 3.11 we can do:
|
|
3005
|
+
#hash_ = hashlib.file_digest(f, hashlib.md5).digest()
|
|
2762
3006
|
return mtime, hash_
|
|
2763
3007
|
def _items(self):
|
|
2764
3008
|
ret = dict()
|
|
@@ -2766,3 +3010,123 @@ class NewFiles:
|
|
|
2766
3010
|
if os.path.isfile(path):
|
|
2767
3011
|
ret[path] = self._file_id(path)
|
|
2768
3012
|
return ret
|
|
3013
|
+
|
|
3014
|
+
|
|
3015
|
+
def swig_get(swig, quick, swig_local='pipcl-swig-git'):
|
|
3016
|
+
'''
|
|
3017
|
+
Returns <swig> or a new swig binary.
|
|
3018
|
+
|
|
3019
|
+
If <swig> is true and starts with 'git:' (not Windows), the remaining text
|
|
3020
|
+
is passed to git_get() and we clone/update/build swig, and return the built
|
|
3021
|
+
binary. We default to the main swig repository, branch master, so for
|
|
3022
|
+
example 'git:' will return the latest swig from branch master.
|
|
3023
|
+
|
|
3024
|
+
Otherwise we simply return <swig>.
|
|
3025
|
+
|
|
3026
|
+
Args:
|
|
3027
|
+
swig:
|
|
3028
|
+
If starts with 'git:', passed as <remote> arg to git_remote().
|
|
3029
|
+
quick:
|
|
3030
|
+
If true, we do not update/build local checkout if the binary is
|
|
3031
|
+
already present.
|
|
3032
|
+
swig_local:
|
|
3033
|
+
path to use for checkout.
|
|
3034
|
+
'''
|
|
3035
|
+
if swig and swig.startswith('git:'):
|
|
3036
|
+
assert platform.system() != 'Windows'
|
|
3037
|
+
swig_local = os.path.abspath(swig_local)
|
|
3038
|
+
# Note that {swig_local}/install/bin/swig doesn't work on MacoS because
|
|
3039
|
+
# {swig_local}/INSTALL is a file and the fs is case-insensitive.
|
|
3040
|
+
swig_binary = f'{swig_local}/install-dir/bin/swig'
|
|
3041
|
+
if quick and os.path.isfile(swig_binary):
|
|
3042
|
+
log1(f'{quick=} and {swig_binary=} already exists, so not downloading/building.')
|
|
3043
|
+
else:
|
|
3044
|
+
# Clone swig.
|
|
3045
|
+
swig_env_extra = None
|
|
3046
|
+
git_get(
|
|
3047
|
+
swig,
|
|
3048
|
+
swig_local,
|
|
3049
|
+
default_remote='https://github.com/swig/swig.git',
|
|
3050
|
+
branch='master',
|
|
3051
|
+
)
|
|
3052
|
+
if darwin():
|
|
3053
|
+
run(f'brew install automake')
|
|
3054
|
+
run(f'brew install pcre2')
|
|
3055
|
+
# Default bison doesn't work, and Brew's bison is not added to $PATH.
|
|
3056
|
+
#
|
|
3057
|
+
# > bison is keg-only, which means it was not symlinked into /opt/homebrew,
|
|
3058
|
+
# > because macOS already provides this software and installing another version in
|
|
3059
|
+
# > parallel can cause all kinds of trouble.
|
|
3060
|
+
# >
|
|
3061
|
+
# > If you need to have bison first in your PATH, run:
|
|
3062
|
+
# > echo 'export PATH="/opt/homebrew/opt/bison/bin:$PATH"' >> ~/.zshrc
|
|
3063
|
+
#
|
|
3064
|
+
run(f'brew install bison')
|
|
3065
|
+
PATH = os.environ['PATH']
|
|
3066
|
+
PATH = f'/opt/homebrew/opt/bison/bin:{PATH}'
|
|
3067
|
+
swig_env_extra = dict(PATH=PATH)
|
|
3068
|
+
# Build swig.
|
|
3069
|
+
run(f'cd {swig_local} && ./autogen.sh', env_extra=swig_env_extra)
|
|
3070
|
+
run(f'cd {swig_local} && ./configure --prefix={swig_local}/install-dir', env_extra=swig_env_extra)
|
|
3071
|
+
run(f'cd {swig_local} && make', env_extra=swig_env_extra)
|
|
3072
|
+
run(f'cd {swig_local} && make install', env_extra=swig_env_extra)
|
|
3073
|
+
assert os.path.isfile(swig_binary)
|
|
3074
|
+
return swig_binary
|
|
3075
|
+
else:
|
|
3076
|
+
return swig
|
|
3077
|
+
|
|
3078
|
+
|
|
3079
|
+
def _show_dict(d):
|
|
3080
|
+
ret = ''
|
|
3081
|
+
for n in sorted(d.keys()):
|
|
3082
|
+
v = d[n]
|
|
3083
|
+
ret += f' {n}: {v!r}\n'
|
|
3084
|
+
return ret
|
|
3085
|
+
|
|
3086
|
+
def show_sysconfig():
|
|
3087
|
+
'''
|
|
3088
|
+
Shows contents of sysconfig.get_paths() and sysconfig.get_config_vars() dicts.
|
|
3089
|
+
'''
|
|
3090
|
+
import sysconfig
|
|
3091
|
+
paths = sysconfig.get_paths()
|
|
3092
|
+
log0(f'show_sysconfig().')
|
|
3093
|
+
log0(f'sysconfig.get_paths():\n{_show_dict(sysconfig.get_paths())}')
|
|
3094
|
+
log0(f'sysconfig.get_config_vars():\n{_show_dict(sysconfig.get_config_vars())}')
|
|
3095
|
+
|
|
3096
|
+
|
|
3097
|
+
def sysconfig_python_flags():
|
|
3098
|
+
'''
|
|
3099
|
+
Returns include paths and library directory for Python.
|
|
3100
|
+
|
|
3101
|
+
Uses sysconfig.*(), overridden by environment variables
|
|
3102
|
+
PIPCL_SYSCONFIG_PATH_include, PIPCL_SYSCONFIG_PATH_platinclude and
|
|
3103
|
+
PIPCL_SYSCONFIG_CONFIG_VAR_LIBDIR if set.
|
|
3104
|
+
'''
|
|
3105
|
+
include1_ = os.environ.get('PIPCL_SYSCONFIG_PATH_include') or sysconfig.get_path('include')
|
|
3106
|
+
include2_ = os.environ.get('PIPCL_SYSCONFIG_PATH_platinclude') or sysconfig.get_path('platinclude')
|
|
3107
|
+
ldflags_ = os.environ.get('PIPCL_SYSCONFIG_CONFIG_VAR_LIBDIR') or sysconfig.get_config_var('LIBDIR')
|
|
3108
|
+
|
|
3109
|
+
includes_ = [include1_]
|
|
3110
|
+
if include2_ != include1_:
|
|
3111
|
+
includes_.append(include2_)
|
|
3112
|
+
if windows():
|
|
3113
|
+
includes_ = [f'/I"{i}"' for i in includes_]
|
|
3114
|
+
ldflags_ = f'/LIBPATH:"{ldflags_}"'
|
|
3115
|
+
else:
|
|
3116
|
+
includes_ = [f'-I {i}' for i in includes_]
|
|
3117
|
+
ldflags_ = f'-L {ldflags_}'
|
|
3118
|
+
includes_ = ' '.join(includes_)
|
|
3119
|
+
return includes_, ldflags_
|
|
3120
|
+
|
|
3121
|
+
|
|
3122
|
+
if __name__ == '__main__':
|
|
3123
|
+
# Internal-only limited command line support, used if
|
|
3124
|
+
# graal_legacy_python_config is true.
|
|
3125
|
+
#
|
|
3126
|
+
includes, ldflags = sysconfig_python_flags()
|
|
3127
|
+
if sys.argv[1:] == ['--graal-legacy-python-config', '--includes']:
|
|
3128
|
+
print(includes)
|
|
3129
|
+
elif sys.argv[1:] == ['--graal-legacy-python-config', '--ldflags']:
|
|
3130
|
+
print(ldflags)
|
|
3131
|
+
else:
|
|
3132
|
+
assert 0, f'Expected `--graal-legacy-python-config --includes|--ldflags` but {sys.argv=}'
|