diff --git a/pipcl.py b/pipcl.py index e1cac6979..cfc834d06 100644 --- a/pipcl.py +++ b/pipcl.py @@ -3348,14 +3348,6 @@ def swig_get(swig, quick, swig_local='pipcl-swig-git'): if quick and os.path.isfile(swig_binary): log1(f'{quick=} and {swig_binary=} already exists, so not downloading/building.') else: - # Clone swig. - swig_env_extra = None - swig_local = git_get( - swig_local, - text=swig, - remote='https://github.com/swig/swig.git', - branch='master', - ) if darwin(): run(f'brew install automake') run(f'brew install pcre2') @@ -3373,6 +3365,57 @@ def swig_get(swig, quick, swig_local='pipcl-swig-git'): macos_add_brew_path('bison', swig_env_extra) run(f'which bison') run(f'which bison', env_extra=swig_env_extra) + + # Building swig requires bison>=3.5. + bison_ok = 0 + e, text = run(f'bison --version', capture=1, check=0, env_extra=swig_env_extra) + if not e: + log(textwrap.indent(text, ' ')) + m = re.search('bison (GNU Bison) ([0-9]+)[.]([0-9]+)', text) + if m: + assert m, f'Unexpected output from `bison --version`: {text!r}' + version_tuple = int(m.group(1)), int(m.group2()) + if version_tuple >= (3, 5): + bison_ok = 1 + if not bison_ok: + if 0: + # Use git checkout. Fails to find scan-code.c. Presumably + # something wrong with ./bootstrap? + log(f'Cloning/fetching/build/installing bison.') + bison_git = git_get( + 'pipcl-bison-git', + remote='https://git.savannah.gnu.org/git/bison.git', + #branch='master', + tag='v3.5.4', + submodules=0, # recursive update fails. + ) + run(f'cd {bison_git} && git submodule update --init', prefix='bison git submodule update --init: ') + run(f'cd {bison_git} && ./bootstrap', prefix='bison bootstrap: ') + run(f'cd {bison_git} && ./configure', prefix='bison configure: ') + run(f'cd {bison_git} && make', prefix='bison make: ') + run(f'cd {bison_git} && sudo make install', prefix='bison make install: ') + else: + bison_version = 'bison-3.5.4' + if not os.path.exists(f'{bison_version}.tar.gz'): + run( + f'wget -O {bison_version}.tar.gz-0 http://www.mirrorservice.org/sites/ftp.gnu.org/gnu/bison/{bison_version}.tar.gz', + prefix='bison wget: ', + ) + os.rename(f'{bison_version}.tar.gz-0', f'{bison_version}.tar.gz') + if not os.path.exists(f'{bison_version}'): + run(f'tar -xzf {bison_version}.tar.gz', prefix='bison extract: ') + run(f'cd {bison_version} && ./configure', prefix='bison configure: ') + run(f'cd {bison_version} && make', prefix='bison make: ') + run(f'cd {bison_version} && sudo make install', prefix='bison make install: ') + + # Clone swig. + swig_env_extra = None + swig_local = git_get( + swig_local, + text=swig, + remote='https://github.com/swig/swig.git', + branch='master', + ) # Build swig. run(f'cd {swig_local} && ./autogen.sh', env_extra=swig_env_extra) run(f'cd {swig_local} && ./configure --prefix={swig_local}/install-dir', env_extra=swig_env_extra) diff --git a/setup.py b/setup.py index ea7a7a395..e6b6f43e2 100755 --- a/setup.py +++ b/setup.py @@ -665,6 +665,7 @@ def add(flavour, from_, to_): add('p', f'{g_root}/src/_wxcolors.py', to_dir) add('p', f'{g_root}/src/_apply_pages.py', to_dir) add('p', f'{g_root}/src/build/extra.py', to_dir) + add('p', b'', f'{to_dir}/py.typed') if path_so_leaf: add('p', f'{g_root}/src/build/{path_so_leaf}', to_dir) diff --git a/src/py.typed b/src/py.typed deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/test_typing.py b/tests/test_typing.py new file mode 100644 index 000000000..cab4450de --- /dev/null +++ b/tests/test_typing.py @@ -0,0 +1,33 @@ +import os +import subprocess + +import pymupdf + + +def run(command, check=1): + print(f'Running: {command}') + subprocess.run(command, shell=1, check=check) + +def test_py_typed(): + print(f'test_py_typed(): {pymupdf.__path__=}') + run('pip uninstall -y mypy') + run('pip install mypy') + root = os.path.abspath(f'{__file__}/../..') + + # Run mypy on this .py file; it will fail at `import pymypdf` if the + # pymupdf install does not have a py.typed file. + # + # This doesn't actually check pymupdf's typing. It looks like + # we can do that with `mypy -m pymupdf`, but as of 2026-1-18 this + # gives many errors such as: + # + # ...site-packages/pymupdf/__init__.py:15346: error: point_like? has no attribute "y" [attr-defined] + # + # It's important to use `--no-incremental`, otherwise if one has + # experimented with `mypy -m pymupdf`, this test will get the + # same failures, via `.mypy_cache/` directories. + # + # We run in sub-directory to avoid spurious mypy errors + # if there is a local mupdf/ directory. + # + run(f'cd {root}/tests && mypy --no-incremental {os.path.abspath(__file__)}')