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