diff --git a/pkgs/applications/office/paperless/default.nix b/pkgs/applications/office/paperless/default.nix new file mode 100644 index 00000000000..0b6ae285bc0 --- /dev/null +++ b/pkgs/applications/office/paperless/default.nix @@ -0,0 +1,170 @@ +{ stdenv +, lib +, fetchFromGitHub +, makeWrapper +, callPackage + +, python3 +, file +, imagemagick7 +, ghostscript +, optipng +, poppler +, tesseract +, unpaper +}: + +## Usage + +# ${paperless}/bin/paperless wraps manage.py + +# ${paperless}/share/paperless/setup-env.sh can be sourced from a +# shell script to setup a Paperless environment + +# paperless.withConfig is a convenience function to setup a +# configured Paperless instance. (See ./withConfig.nix) + +# For WSGI with gunicorn, use a shell script like this: +# let +# pythonEnv = paperless.python.withPackages (ps: paperless.runtimePackages ++ [ ps.gunicorn ]); +# in +# writers.writeBash "run-gunicorn" '' +# source ${paperless}/share/paperless/setup-env.sh +# PYTHONPATH=$paperlessSrc ${pythonEnv}/bin/gunicorn paperless.wsgi +# '' + +let + paperless = stdenv.mkDerivation rec { + name = "paperless-${version}"; + version = "2.7.0"; + + src = fetchFromGitHub { + owner = "the-paperless-project"; + repo = "paperless"; + rev = version; + sha256 = "0pkmyky1crjnsg7r0gfk0fadisfsgzlsq6afpz16wx4hp6yvkkf7"; + }; + + nativeBuildInputs = [ makeWrapper ]; + + doCheck = true; + dontInstall = true; + + pythonEnv = python.withPackages (_: runtimePackages); + pythonCheckEnv = python.withPackages (_: (runtimePackages ++ checkPackages)); + + unpackPhase = '' + srcDir=$out/share/paperless + mkdir -p $srcDir + cp -r --no-preserve=mode $src/src/* $src/LICENSE $srcDir + ''; + + buildPhase = let + # Paperless has explicit runtime checks that expect these binaries to be in PATH + extraBin = lib.makeBinPath [ imagemagick7 ghostscript optipng tesseract unpaper ]; + in '' + ${python.interpreter} -m compileall $srcDir + + makeWrapper $pythonEnv/bin/python $out/bin/paperless \ + --set PATH ${extraBin} --add-flags $out/share/paperless/manage.py + + # A shell snippet that can be sourced to setup a paperless env + cat > $out/share/paperless/setup-env.sh < {}).paperless.withConfig { +# dataDir = /tmp/paperless-data; +# config = { +# PAPERLESS_DISABLE_LOGIN = "true"; +# }; +# }' +# +# Setup DB +# ./paperless migrate +# +# Consume documents in ${dataDir}/consume +# ./paperless document_consumer --oneshot +# +# Start web interface +# ./paperless runserver --noreload localhost:8000 + +{ config ? {}, dataDir ? null, ocrLanguages ? null +, paperlessPkg ? paperless, extraCmds ? "" }: +with lib; +let + paperless = if ocrLanguages == null then + paperlessPkg + else + (paperlessPkg.override { + tesseract = paperlessPkg.tesseract.override { + enableLanguages = ocrLanguages; + }; + }).overrideDerivation (_: { + # `ocrLanguages` might be missing some languages required by the tests. + doCheck = false; + }); + + envVars = (optionalAttrs (dataDir != null) { + PAPERLESS_CONSUMPTION_DIR = "${dataDir}/consume"; + PAPERLESS_MEDIADIR = "${dataDir}/media"; + PAPERLESS_STATICDIR = "${dataDir}/static"; + PAPERLESS_DBDIR = "${dataDir}"; + }) // config; + + envVarDefs = mapAttrsToList (n: v: ''export ${n}="${toString v}"'') envVars; + setupEnvVars = builtins.concatStringsSep "\n" envVarDefs; + + setupEnv = '' + source ${paperless}/share/paperless/setup-env.sh + ${setupEnvVars} + ${optionalString (dataDir != null) '' + mkdir -p "$PAPERLESS_CONSUMPTION_DIR" \ + "$PAPERLESS_MEDIADIR" \ + "$PAPERLESS_STATICDIR" \ + "$PAPERLESS_DBDIR" + ''} + ''; + + runPaperless = writers.writeBash "paperless" '' + set -e + ${setupEnv} + ${extraCmds} + exec python $paperlessSrc/manage.py "$@" + ''; +in + runPaperless // { + inherit paperless setupEnv; + } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index fb1fa5e5ebc..99fa10eb673 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -4952,6 +4952,8 @@ in paper-gtk-theme = callPackage ../misc/themes/paper { }; + paperless = callPackage ../applications/office/paperless { }; + paperwork = callPackage ../applications/office/paperwork { }; papertrail = callPackage ../tools/text/papertrail { };