Skip to content

Commit 418bcd6

Browse files
authored
Merge branch 'main' into address-4050
2 parents cd28994 + fac6678 commit 418bcd6

File tree

7 files changed

+90
-8
lines changed

7 files changed

+90
-8
lines changed

.github/workflows/test_mupdf-release-branch.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727

2828
- name: test_mupdf-release-branch
2929
env:
30-
inputs_PYMUPDF_SETUP_MUPDF_BUILD: "git:--recursive --depth 1 --shallow-submodules --branch 1.24.x https://github.com/ArtifexSoftware/mupdf.git"
30+
inputs_PYMUPDF_SETUP_MUPDF_BUILD: "git:--recursive --depth 1 --shallow-submodules --branch 1.25.x https://github.com/ArtifexSoftware/mupdf.git"
3131
inputs_flavours: "0"
3232
inputs_sdist: "0"
3333
inputs_wheels_cps: "cp312*"

.github/workflows/test_sysinstall.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ jobs:
3434
- name: sysinstall_venv
3535
run:
3636
# Use venv.
37-
python3 scripts/sysinstall.py --root / --mupdf-git '--branch master https://github.com/ArtifexSoftware/mupdf.git'
37+
python3 scripts/sysinstall.py --mupdf-git '--branch master https://github.com/ArtifexSoftware/mupdf.git'
3838

3939
- name: sysinstall_sudo
4040
run:
4141
# Do not use a venv, instead install required packages with sudo.
42-
python3 scripts/sysinstall.py --pip sudo --root / --mupdf-git '--branch master https://github.com/ArtifexSoftware/mupdf-julian.git'
42+
python3 scripts/sysinstall.py --mupdf-git '--branch master https://github.com/ArtifexSoftware/mupdf.git' --pip sudo --root /

pipcl.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ def __init__(self,
364364
* https://pypi.org/classifiers/
365365
366366
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.
368368
requires_python:
369369
A string or list of strings.
370370
requires_external:
@@ -489,6 +489,7 @@ def __init__(self,
489489
Used as `zipfile.ZipFile()`'s `compresslevel` parameter when
490490
creating wheels.
491491
492+
Occurrences of `None` in lists are ignored.
492493
'''
493494
assert name
494495
assert version
@@ -1261,7 +1262,8 @@ def add(key, value):
12611262
return
12621263
if isinstance( value, (tuple, list)):
12631264
for v in value:
1264-
add( key, v)
1265+
if v is not None:
1266+
add( key, v)
12651267
return
12661268
if key == 'License' and '\n' in value:
12671269
# This is ok because we write `self.license` into

scripts/sysinstall.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
--pymupdf-do 0|1
5050
Whether to build and install pymupdf.
5151
--root <root>
52-
Root of install directory; default is `/`.
52+
Root of install directory; default is 'pymupdf-sysinstall-test-root'.
5353
--tesseract5 0|1
5454
If 1 (the default), we force installation of libtesseract-dev version
5555
5 (which is not available as a default package in Ubuntu-22.04) from
@@ -140,7 +140,7 @@ def main():
140140
packages = True
141141
prefix = '/usr/local'
142142
pymupdf_do = True
143-
root = 'sysinstall_test'
143+
root = 'pymupdf-sysinstall-test-root'
144144
tesseract5 = True
145145
pytest_args = None
146146
pytest_do = True

scripts/test.py

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@
9090
Whether to rebuild mupdf when we build PyMuPDF. Default is 1.
9191
--gdb 0|1
9292
Run tests under gdb.
93+
--pybind 0|1
94+
Run tests inside C++ pybind.Requires `sudo apt install pybind11-dev` or
95+
similar.
9396
--system-site-packages 0|1
9497
If 1, use `--system-site-packages` when creating venv.
9598
--timeout <seconds>
@@ -165,6 +168,7 @@ def main(argv):
165168
implementations = 'r'
166169
test_names = list()
167170
venv = 2
171+
pybind = False
168172
pytest_options = None
169173
timeout = None
170174
pytest_k = None
@@ -211,6 +215,8 @@ def main(argv):
211215
value = next(args)
212216
assert value in ('0', '1'), f'`-s` must be followed by `0` or `1`, not {value=}.'
213217
os.environ['PYMUPDF_SETUP_PY_LIMITED_API'] = value
218+
elif arg == '--pybind':
219+
pybind = int(next(args))
214220
elif arg == '--system-site-packages':
215221
system_site_packages = int(next(args))
216222
elif arg == '-t':
@@ -282,6 +288,7 @@ def do_test():
282288
gdb=gdb,
283289
test_fitz=test_fitz,
284290
pytest_k=pytest_k,
291+
pybind=pybind,
285292
)
286293

287294
for command in commands:
@@ -621,7 +628,8 @@ def test(
621628
timeout=None,
622629
gdb=False,
623630
test_fitz=True,
624-
pytest_k=None
631+
pytest_k=None,
632+
pybind=False,
625633
):
626634
'''
627635
Args:
@@ -642,6 +650,65 @@ def test(
642650
test_fitz:
643651
See top-level option `-f`.
644652
'''
653+
if pybind:
654+
cpp_path = 'pymupdf_test_pybind.cpp'
655+
cpp_exe = 'pymupdf_test_pybind.exe'
656+
cpp = textwrap.dedent('''
657+
#include <pybind11/embed.h>
658+
659+
int main()
660+
{
661+
pybind11::scoped_interpreter guard{};
662+
pybind11::exec(R"(
663+
print('Hello world', flush=1)
664+
import pymupdf
665+
pymupdf.JM_mupdf_show_warnings = 1
666+
print(f'{pymupdf.version=}', flush=1)
667+
doc = pymupdf.Document()
668+
pymupdf.mupdf.fz_warn('Dummy warning.')
669+
pymupdf.mupdf.fz_warn('Dummy warning.')
670+
pymupdf.mupdf.fz_warn('Dummy warning.')
671+
print(f'{doc=}', flush=1)
672+
)");
673+
}
674+
''')
675+
def fs_read(path):
676+
try:
677+
with open(path) as f:
678+
return f.read()
679+
except Exception:
680+
return
681+
def fs_remove(path):
682+
try:
683+
os.remove(path)
684+
except Exception:
685+
pass
686+
cpp_existing = fs_read(cpp_path)
687+
if cpp == cpp_existing:
688+
log(f'Not creating {cpp_exe} because unchanged: {cpp_path}')
689+
else:
690+
with open(cpp_path, 'w') as f:
691+
f.write(cpp)
692+
def getmtime(path):
693+
try:
694+
return os.path.getmtime(path)
695+
except Exception:
696+
return 0
697+
python_config = f'{os.path.realpath(sys.executable)}-config'
698+
# `--embed` adds `-lpython3.11` to the link command, which appears to
699+
# be necessary when building an executable.
700+
flags = run(f'{python_config} --cflags --ldflags --embed', capture=1)
701+
build_command = f'c++ {cpp_path} -o {cpp_exe} -g -W -Wall {flags}'
702+
build_path = f'{cpp_exe}.cmd'
703+
build_command_prev = fs_read(build_path)
704+
if build_command != build_command_prev or getmtime(cpp_path) >= getmtime(cpp_exe):
705+
fs_remove(build_path)
706+
run(build_command)
707+
with open(build_path, 'w') as f:
708+
f.write(build_command)
709+
run(f'./{cpp_exe}')
710+
return
711+
645712
pymupdf_dir_rel = gh_release.relpath(pymupdf_dir)
646713
if pytest_options is None:
647714
if valgrind:

tests/resources/test_4026.pdf

2.27 MB
Binary file not shown.

tests/test_textextract.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,3 +387,16 @@ def test_3650():
387387
'RECUEIL DES ACTES ADMINISTRATIFS\n',
388388
'n° 78 du 28 avril 2023\n',
389389
]
390+
391+
def test_4026():
392+
path = os.path.normpath(f'{__file__}/../../tests/resources/test_4026.pdf')
393+
with pymupdf.open(path) as document:
394+
page = document[4]
395+
blocks = page.get_text('blocks')
396+
for i, block in enumerate(blocks):
397+
print(f'block {i}: {block}')
398+
if pymupdf.mupdf_version_tuple < (1, 25):
399+
assert len(blocks) == 15
400+
else:
401+
assert len(blocks) == 5
402+

0 commit comments

Comments
 (0)