nixpkgs/pkgs/development/python-modules/pypdfium2/default.nix
2025-08-22 22:10:55 -04:00

154 lines
4 KiB
Nix

{
stdenv,
lib,
pkgs,
buildPythonPackage,
fetchFromGitHub,
fetchgit,
gitUpdater,
setuptools-scm,
pdfium-binaries,
numpy,
pillow,
pytestCheckHook,
removeReferencesTo,
python,
replaceVars,
}:
let
pdfiumVersion = "${pdfium-binaries.version}";
headers = fetchgit {
url = "https://pdfium.googlesource.com/pdfium";
# The latest revision on the chromium/${pdfiumVersion} branch
rev = "9232d7c94a0007377a8034222f47683fe391d474";
hash = "sha256-dI3jTyVYc0EmMLHTiVjGSf3C2noS9Ru5WijEJFtiSFk=";
sparseCheckout = [
"public"
];
};
# They demand their own fork of ctypesgen
ctypesgen = buildPythonPackage rec {
pname = "ctypesgen";
version = "1.1.1+g${src.rev}"; # the most recent tag + git version
pyproject = true;
src = fetchFromGitHub {
owner = "pypdfium2-team";
repo = "ctypesgen";
rev = "848e9fbb1374f7f58a7ebf5e5da5c33292480b30";
hash = "sha256-3JA7cW/xaEj/DxMHEypROwrKGo7EwUEcipRqALTvydw=";
};
patches = [
(replaceVars ./fix-cc-detection.patch {
cc = "${stdenv.cc.targetPrefix}cc";
})
];
build-system = [
setuptools-scm
];
env.SETUPTOOLS_SCM_PRETEND_VERSION = "${version}";
};
in
buildPythonPackage rec {
pname = "pypdfium2";
version = "4.30.1";
pyproject = true;
src = fetchFromGitHub {
owner = "pypdfium2-team";
repo = "pypdfium2";
tag = version;
hash = "sha256-v8f/XruGJYK3H9z4Q1rLg4fEnPHa8tTOlNTBMVxPEgA=";
};
build-system = [
ctypesgen
setuptools-scm
];
nativeBuildInputs = [
removeReferencesTo
];
propagatedBuildInputs = [
pdfium-binaries
];
# Build system insists on fetching from the internet unless "cached" files
# are prepared. Even then, some code patching needs to happen to make it not
# talk to the internet.
# The project doesn't seem very open to allow for offline building either,
# see: https://github.com/pypdfium2-team/pypdfium2/discussions/274
preBuild =
let
pdfiumLib = lib.makeLibraryPath [ pdfium-binaries ];
inputVersionFile = (pkgs.formats.json { }).generate "version.json" {
version = lib.strings.toInt pdfiumVersion;
source = "generated";
flags = [ ];
run_lds = [ pdfiumLib ];
guard_symbols = false;
};
bindingsDir = "data/bindings";
headersDir = "${bindingsDir}/headers";
versionFile = "${bindingsDir}/version.json";
in
''
# Preseed the headers and version file
mkdir -p ${bindingsDir}
cp -r ${headers}/public ${headersDir}
install -m 644 ${inputVersionFile} ${versionFile}
# Make generated bindings consider pdfium derivation path when loading dynamic libraries
substituteInPlace setupsrc/pypdfium2_setup/emplace.py \
--replace-fail 'build_pdfium_bindings(pdfium_ver, flags=flags, guard_symbols=True, run_lds=[])' \
'build_pdfium_bindings(pdfium_ver, flags=flags, guard_symbols=True, run_lds=["${pdfiumLib}"])'
# Short circuit the version pull from the internet
substituteInPlace setupsrc/pypdfium2_setup/packaging_base.py \
--replace-fail 'PdfiumVer.to_full(build)._asdict()' \
'{"major": 133, "minor": 0, "build": ${pdfiumVersion}, "patch": 1}'
'';
env.PDFIUM_PLATFORM = "system:${pdfiumVersion}";
# Remove references to stdenv in comments.
postInstall = ''
remove-references-to -t ${stdenv.cc.cc} $out/${python.sitePackages}/pypdfium2_raw/bindings.py
'';
nativeCheckInputs = [
numpy
pillow
pytestCheckHook
];
pythonImportsCheck = [
"pypdfium2"
];
passthru = {
updateScript = gitUpdater {
allowedVersions = "^[.0-9]+$";
};
};
meta = {
changelog = "https://github.com/pypdfium2-team/pypdfium2/releases/tag/${version}";
description = "Python bindings to PDFium";
homepage = "https://pypdfium2.readthedocs.io/";
license = with lib.licenses; [
asl20 # or
mit
];
maintainers = with lib.maintainers; [ booxter ];
};
}