summaryrefslogtreecommitdiff
path: root/pkgs/development/interpreters/python/wrap-python.nix
blob: 0bc93d600ea78ccf3af6e5fc3471e22f9ccabd12 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
{
  lib,
  python,
  makePythonHook,
  makeWrapper,
}:

makePythonHook {
  name = "wrap-python-hook";
  propagatedBuildInputs = [ makeWrapper ];
  substitutions.sitePackages = python.sitePackages;
  substitutions.executable = python.interpreter;
  substitutions.python = python.pythonOnBuildForHost;
  substitutions.pythonHost = python;
  substitutions.magicalSedExpression =
    let
      # Looks weird? Of course, it's between single quoted shell strings.
      # NOTE: Order DOES matter here, so single character quotes need to be
      #       at the last position.
      quoteVariants = [
        "'\"'''\"'"
        "\"\"\""
        "\""
        "'\"'\"'"
      ]; # hey Vim: ''

      mkStringSkipper =
        labelNum: quote:
        let
          label = "q${toString labelNum}";
          isSingle = lib.elem quote [
            "\""
            "'\"'\"'"
          ];
          endQuote = if isSingle then "[^\\\\]${quote}" else quote;
        in
        ''
          /^[a-z]?${quote}/ {
            /${quote}${quote}|${quote}.*${endQuote}/{n;br}
            :${label}; n; /^${quote}/{n;br}; /${endQuote}/{n;br}; b${label}
          }
        '';

      # This preamble does two things:
      # * Sets argv[0] to the original application's name; otherwise it would be .foo-wrapped.
      #   Python doesn't support `exec -a`.
      # * Adds all required libraries to sys.path via `site.addsitedir`. It also handles *.pth files.
      preamble = ''
        import sys
        import site
        import functools
        sys.argv[0] = '"'$(readlink -f "$f")'"'
        functools.reduce(lambda k, p: site.addsitedir(p, k), ['"$([ -n "$program_PYTHONPATH" ] && (echo "'$program_PYTHONPATH'" | sed "s|:|','|g") || true)"'], site._init_pathinfo())
      '';

    in
    ''
      1 {
        :r
        /\\$|,$/{N;br}
        /__future__|^ |^ *(#.*)?$/{n;br}
        ${lib.concatImapStrings mkStringSkipper quoteVariants}
        /^[^# ]/i ${lib.replaceStrings [ "\n" ] [ ";" ] preamble}
      }
    '';
} ./wrap.sh