1{
2 lib,
3 stdenv,
4 buildPythonPackage,
5 pythonOlder,
6 fetchFromGitHub,
7 fetchpatch,
8 python,
9 toPythonModule,
10
11 # build-system
12 libclang,
13 psutil,
14 setuptools,
15 swig,
16
17 # native dependencies
18 freetype,
19 harfbuzz,
20 openjpeg,
21 jbig2dec,
22 libjpeg_turbo,
23 gumbo,
24
25 # dependencies
26 mupdf,
27
28 # tests
29 pytestCheckHook,
30 fonttools,
31 pillow,
32 pymupdf-fonts,
33}:
34
35let
36 # PyMuPDF needs the C++ bindings generated
37 mupdf-cxx = mupdf.override {
38 enableOcr = true;
39 enableCxx = true;
40 enablePython = true;
41 enableBarcode = true;
42 python3 = python;
43 };
44 mupdf-cxx-lib = toPythonModule (lib.getLib mupdf-cxx);
45 mupdf-cxx-dev = lib.getDev mupdf-cxx;
46in
47buildPythonPackage rec {
48 pname = "pymupdf";
49 version = "1.26.1";
50 pyproject = true;
51
52 disabled = pythonOlder "3.9";
53
54 src = fetchFromGitHub {
55 owner = "pymupdf";
56 repo = "PyMuPDF";
57 tag = version;
58 hash = "sha256-Z+TO4MaLFmgNSRMTltY77bHnA5RHc4Ii45sDjJsFZto=";
59 };
60
61 # swig is not wrapped as Python package
62 postPatch = ''
63 substituteInPlace setup.py \
64 --replace-fail "ret.append( 'swig')" "pass" \
65 '';
66
67 nativeBuildInputs = [
68 libclang
69 swig
70 psutil
71 setuptools
72 ];
73
74 buildInputs = [
75 freetype
76 harfbuzz
77 openjpeg
78 jbig2dec
79 libjpeg_turbo
80 gumbo
81 ];
82
83 propagatedBuildInputs = [ mupdf-cxx-lib ];
84
85 env = {
86 # force using system MuPDF (must be defined in environment and empty)
87 PYMUPDF_SETUP_MUPDF_BUILD = "";
88 # Setup the name of the package away from the default 'libclang'
89 PYMUPDF_SETUP_LIBCLANG = "clang";
90 # provide MuPDF paths
91 PYMUPDF_MUPDF_LIB = "${mupdf-cxx-lib}/lib";
92 PYMUPDF_MUPDF_INCLUDE = "${mupdf-cxx-dev}/include";
93 };
94
95 # TODO: manually add mupdf rpath until upstream fixes it
96 postInstall = lib.optionalString stdenv.hostPlatform.isDarwin ''
97 for lib in */*.so $out/${python.sitePackages}/*/*.so; do
98 install_name_tool -add_rpath ${mupdf-cxx-lib}/lib "$lib"
99 done
100 '';
101
102 nativeCheckInputs = [
103 pytestCheckHook
104 ];
105
106 checkInputs = [
107 fonttools
108 pillow
109 pymupdf-fonts
110 ];
111
112 disabledTests = [
113 # Do not lint code
114 "test_codespell"
115 "test_pylint"
116 "test_flake8"
117 # Upstream recommends disabling these when not using bundled MuPDF build
118 "test_color_count"
119 "test_3050"
120 "test_textbox3"
121 "test_3493"
122 "test_4180"
123 # Requires downloads
124 "test_4457"
125 "test_4445"
126 # Not a git repository, so git ls-files fails
127 "test_open2"
128 ];
129
130 pythonImportsCheck = [
131 "pymupdf"
132 "fitz"
133 ];
134
135 preCheck = ''
136 export PATH="$out/bin:$PATH";
137
138 # Fixes at least one test; see:
139 # * <https://github.com/pymupdf/PyMuPDF/blob/refs/tags/1.25.1/scripts/sysinstall.py#L390>
140 # * <https://github.com/pymupdf/PyMuPDF/blob/refs/tags/1.25.1/tests/test_pixmap.py#L425-L428>
141 export PYMUPDF_SYSINSTALL_TEST=1
142 '';
143
144 meta = {
145 description = "Python bindings for MuPDF's rendering library";
146 homepage = "https://github.com/pymupdf/PyMuPDF";
147 changelog = "https://github.com/pymupdf/PyMuPDF/releases/tag/${src.tag}";
148 license = lib.licenses.agpl3Only;
149 maintainers = [ ];
150 platforms = lib.platforms.unix;
151 };
152}