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 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 python3 = python;
41 };
42in
43buildPythonPackage rec {
44 pname = "pymupdf";
45 version = "1.24.14";
46 pyproject = true;
47
48 disabled = pythonOlder "3.7";
49
50 src = fetchFromGitHub {
51 owner = "pymupdf";
52 repo = "PyMuPDF";
53 rev = "refs/tags/${version}";
54 hash = "sha256-M7Ca3nqnqeClp4MGJqTAVGZhAGRniregjRrjtAhRkBc=";
55 };
56
57 # swig is not wrapped as Python package
58 # libclang calls itself just clang in wheel metadata
59 postPatch = ''
60 substituteInPlace setup.py \
61 --replace-fail "ret.append( 'swig')" "pass" \
62 '';
63
64 nativeBuildInputs = [
65 libclang
66 swig
67 psutil
68 setuptools
69 ];
70
71 buildInputs = [
72 freetype
73 harfbuzz
74 openjpeg
75 jbig2dec
76 libjpeg_turbo
77 gumbo
78 ] ++ lib.optionals (stdenv.system == "x86_64-darwin") [ memstreamHook ];
79
80 propagatedBuildInputs = [ mupdf-cxx ];
81
82 env = {
83 # force using system MuPDF (must be defined in environment and empty)
84 PYMUPDF_SETUP_MUPDF_BUILD = "";
85 # Setup the name of the package away from the default 'libclang'
86 PYMUPDF_SETUP_LIBCLANG = "clang";
87 # provide MuPDF paths
88 PYMUPDF_MUPDF_LIB = "${lib.getLib mupdf-cxx}/lib";
89 PYMUPDF_MUPDF_INCLUDE = "${lib.getDev mupdf-cxx}/include";
90 };
91
92 # TODO: manually add mupdf rpath until upstream fixes it
93 postInstall = lib.optionalString stdenv.hostPlatform.isDarwin ''
94 for lib in */*.so $out/${python.sitePackages}/*/*.so; do
95 install_name_tool -add_rpath ${lib.getLib mupdf-cxx}/lib "$lib"
96 done
97 '';
98
99 nativeCheckInputs = [
100 pytestCheckHook
101 ];
102
103 checkInputs = [
104 fonttools
105 pillow
106 pymupdf-fonts
107 ];
108
109 disabledTests = [
110 # Do not lint code
111 "test_codespell"
112 "test_pylint"
113 "test_flake8"
114 # Upstream recommends disabling these when not using bundled MuPDF build
115 "test_color_count"
116 "test_3050"
117 "test_textbox3"
118 ];
119
120 pythonImportsCheck = [
121 "pymupdf"
122 "fitz"
123 ];
124
125 preCheck = ''
126 export PATH="$out/bin:$PATH";
127 '';
128
129 meta = {
130 description = "Python bindings for MuPDF's rendering library";
131 homepage = "https://github.com/pymupdf/PyMuPDF";
132 changelog = "https://github.com/pymupdf/PyMuPDF/releases/tag/${version}";
133 license = lib.licenses.agpl3Only;
134 maintainers = with lib.maintainers; [ teto ];
135 platforms = lib.platforms.unix;
136 };
137}