1{
2 lib,
3 stdenv,
4 buildPythonPackage,
5 pythonOlder,
6 fetchFromGitHub,
7 python,
8
9 # build-system
10 libclang,
11 psutil,
12 setuptools,
13 swig,
14
15 # native dependencies
16 freetype,
17 harfbuzz,
18 openjpeg,
19 jbig2dec,
20 libjpeg_turbo,
21 gumbo,
22 memstreamHook,
23
24 # dependencies
25 mupdf,
26
27 # tests
28 fonttools,
29 pytestCheckHook,
30}:
31
32let
33 # PyMuPDF needs the C++ bindings generated
34 mupdf-cxx = mupdf.override {
35 enableOcr = true;
36 enableCxx = true;
37 enablePython = true;
38 python3 = python;
39 };
40in
41buildPythonPackage rec {
42 pname = "pymupdf";
43 version = "1.23.26";
44 pyproject = true;
45
46 disabled = pythonOlder "3.7";
47
48 src = fetchFromGitHub {
49 owner = "pymupdf";
50 repo = "PyMuPDF";
51 rev = "refs/tags/${version}";
52 hash = "sha256-m2zq04+PDnlzFuqeSt27UhdHXTHxpHdMPIg5RQl/5bQ=";
53 };
54
55 # swig is not wrapped as Python package
56 # libclang calls itself just clang in wheel metadata
57 postPatch = ''
58 substituteInPlace pyproject.toml \
59 --replace-fail '"swig",' "" \
60 --replace-fail "libclang" "clang"
61 '';
62
63 nativeBuildInputs = [
64 libclang
65 swig
66 psutil
67 setuptools
68 ];
69
70 buildInputs = [
71 freetype
72 harfbuzz
73 openjpeg
74 jbig2dec
75 libjpeg_turbo
76 gumbo
77 ] ++ lib.optionals (stdenv.system == "x86_64-darwin") [ memstreamHook ];
78
79 propagatedBuildInputs = [ mupdf-cxx ];
80
81 env = {
82 # force using system MuPDF (must be defined in environment and empty)
83 PYMUPDF_SETUP_MUPDF_BUILD = "";
84 # provide MuPDF paths
85 PYMUPDF_MUPDF_LIB = "${lib.getLib mupdf-cxx}/lib";
86 PYMUPDF_MUPDF_INCLUDE = "${lib.getDev mupdf-cxx}/include";
87 };
88
89 # TODO: manually add mupdf rpath until upstream fixes it
90 postInstall = lib.optionalString stdenv.isDarwin ''
91 for lib in */*.so $out/${python.sitePackages}/*/*.so; do
92 install_name_tool -add_rpath ${lib.getLib mupdf-cxx}/lib "$lib"
93 done
94 '';
95
96 nativeCheckInputs = [
97 pytestCheckHook
98 fonttools
99 ];
100
101 preCheck = ''
102 export PATH="$PATH:$out/bin";
103 '';
104
105 disabledTests =
106 [
107 # fails for indeterminate reasons
108 "test_2548"
109 "test_2753"
110 "test_3020"
111 "test_3050"
112 "test_3058"
113 "test_3177"
114 "test_3186"
115 "test_color_count"
116 "test_pilsave"
117 "test_fz_write_pixmap_as_jpeg"
118 # NotImplementedError
119 "test_1824"
120 "test_2093"
121 "test_2093"
122 "test_2108"
123 "test_2182"
124 "test_2182"
125 "test_2246"
126 "test_2270"
127 "test_2270"
128 "test_2391"
129 "test_2788"
130 "test_2861"
131 "test_2871"
132 "test_2886"
133 "test_2904"
134 "test_2922"
135 "test_2934"
136 "test_2957"
137 "test_2969"
138 "test_3070"
139 "test_3131"
140 "test_3140"
141 "test_3209"
142 "test_3209"
143 "test_caret"
144 "test_deletion"
145 "test_file_info"
146 "test_line"
147 "test_page_links_generator"
148 "test_polyline"
149 "test_redact"
150 "test_techwriter_append"
151 "test_text2"
152 # Issue with FzArchive
153 "test_htmlbox"
154 "test_2246"
155 "test_3140"
156 "test_fit_springer"
157 "test_write_stabilized_with_links"
158 "test_textbox"
159 "test_delete_image"
160 # Fonts not available
161 "test_fontarchive"
162 "test_subset_fonts"
163 # Exclude lint tests
164 "test_flake8"
165 ]
166 ++ lib.optionals stdenv.isDarwin [
167 # darwin does not support OCR right now
168 "test_tesseract"
169 ];
170
171 disabledTestPaths = [
172 # Issue with FzArchive
173 "tests/test_docs_samples.py"
174 ];
175
176 pythonImportsCheck = [
177 "fitz"
178 "fitz_old"
179 ];
180
181 meta = with lib; {
182 description = "Python bindings for MuPDF's rendering library";
183 homepage = "https://github.com/pymupdf/PyMuPDF";
184 changelog = "https://github.com/pymupdf/PyMuPDF/releases/tag/${version}";
185 license = licenses.agpl3Only;
186 maintainers = with maintainers; [ teto ];
187 platforms = platforms.unix;
188 };
189}