From 0d302d188bbc2b2f24e1c6906a0bc5629397997b Mon Sep 17 00:00:00 2001 From: Matthieu Coudron <886074+teto@users.noreply.github.com> Date: Mon, 18 Dec 2023 00:26:34 +0100 Subject: [PATCH 1/5] jupyter.lib: init Introduce 2 functions to help with creating a jupyter environment: - mkKernelFromHaskellEnv - mkKernelFromPythonEnv --- pkgs/applications/editors/jupyter/lib.nix | 65 +++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 pkgs/applications/editors/jupyter/lib.nix diff --git a/pkgs/applications/editors/jupyter/lib.nix b/pkgs/applications/editors/jupyter/lib.nix new file mode 100644 index 0000000000000..1388ab90301d6 --- /dev/null +++ b/pkgs/applications/editors/jupyter/lib.nix @@ -0,0 +1,65 @@ +{ jupyter-kernel, python3, lib, ...}: +{ + /* Generates a kernel definition from a haskell environment + + Example: + let ghcEnv = pkgs.haskellPackages.ghcWithPackages (p: [ p.aeson ]); + in mkKernelFromHaskellEnv ghcEnv; + + Type: + mkKernelFromHaskellEnv :: Derivation -> AttrSet + */ + mkKernelFromHaskellEnv = ghcEnv: + let + ghcEnv' = ghcEnv.withPackages (p: [ p.ihaskell ]); + in + + { + displayName = "Haskell"; + argv = [ + "${ghcEnv'}/bin/ihaskell" + "-l" + # the ihaskell flake does `-l $(${env}/bin/ghc --print-libdir` + # we guess the path via hardcoded + # we can't use name else we get the 'with-packages' suffix + "${ghcEnv}/lib/ghc-${ghcEnv.version}" + "kernel" + "{connection_file}" + ]; + language = "haskell"; + logo32 = null; + logo64 = null; + }; + + + /* Generates a kernel definition from a python environment + Example: + let pyEnv = pkgs.python3.withPackages (p: [ p.numpy ]); + in mkKernelFromPythonEnv pyEnv; + + Type: + mkKernelFromPythonEnv :: Derivation -> AttrSet + */ + mkKernelFromPythonEnv = env: let + env' = env.override(prev: { + # fastai + extraLibs = prev.extraLibs ++ [ env.python.pkgs.ipykernel ]; + }); + + in + { + displayName = "Python 3"; + argv = [ + env'.interpreter + "-m" + "ipykernel_launcher" + "-f" + "{connection_file}" + ]; + language = "python"; + logo32 = "${env}/${env.sitePackages}/ipykernel/resources/logo-32x32.png"; + logo64 = "${env}/${env.sitePackages}/ipykernel/resources/logo-64x64.png"; + }; + + +} From bba1535c26ff39622ab533cb95d2fd68fc0a5d99 Mon Sep 17 00:00:00 2001 From: Matthieu Coudron <886074+teto@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:18:09 +0100 Subject: [PATCH 2/5] jupyter-kernel: refactor to use jupyterLib --- pkgs/applications/editors/jupyter/kernel.nix | 18 ++---------------- pkgs/top-level/all-packages.nix | 1 + 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/pkgs/applications/editors/jupyter/kernel.nix b/pkgs/applications/editors/jupyter/kernel.nix index 3640de28e8acc..cc40a2fc3fb2e 100644 --- a/pkgs/applications/editors/jupyter/kernel.nix +++ b/pkgs/applications/editors/jupyter/kernel.nix @@ -1,23 +1,9 @@ -{ lib, stdenv, python3}: +{ lib, stdenv, python3, jupyterLib }: let default = { - python3 = let - env = (python3.withPackages (ps: with ps; [ ipykernel ])); - in { - displayName = "Python 3"; - argv = [ - env.interpreter - "-m" - "ipykernel_launcher" - "-f" - "{connection_file}" - ]; - language = "python"; - logo32 = "${env}/${env.sitePackages}/ipykernel/resources/logo-32x32.png"; - logo64 = "${env}/${env.sitePackages}/ipykernel/resources/logo-64x64.png"; - }; + python3 = jupyterLib.mkKernelFromPythonEnv (python3.withPackages (ps: [])); }; in diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 26f01082edd50..06c0f51944ac0 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -9721,6 +9721,7 @@ with pkgs; jupp = callPackage ../applications/editors/jupp { }; jupyter = callPackage ../applications/editors/jupyter { }; + jupyterLib = callPackage ../applications/editors/jupyter/lib.nix { }; jupyter-all = jupyter.override { definitions = { From cece6357b04448b63720ae12d540813c157aef29 Mon Sep 17 00:00:00 2001 From: Matthieu Coudron <886074+teto@users.noreply.github.com> Date: Tue, 2 Jan 2024 17:33:50 +0100 Subject: [PATCH 3/5] jupyter-all: aliased to jupyter.tests jupyter-all is not really something usable out of the box, mostly something used as a test. This PR moves it to jupyter.tests to reflect that. --- pkgs/applications/editors/jupyter/default.nix | 3 +++ pkgs/applications/editors/jupyter/tests/default.nix | 11 +++++++++++ pkgs/top-level/aliases.nix | 1 + pkgs/top-level/all-packages.nix | 8 -------- 4 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 pkgs/applications/editors/jupyter/tests/default.nix diff --git a/pkgs/applications/editors/jupyter/default.nix b/pkgs/applications/editors/jupyter/default.nix index 57122d173a441..2cd17b712b126 100644 --- a/pkgs/applications/editors/jupyter/default.nix +++ b/pkgs/applications/editors/jupyter/default.nix @@ -3,6 +3,7 @@ { python3 , jupyter-kernel , definitions ? jupyter-kernel.default +, callPackage }: let @@ -12,6 +13,8 @@ let makeWrapperArgs = ["--set JUPYTER_PATH ${jupyterPath}"]; }).overrideAttrs(oldAttrs: { meta = oldAttrs.meta // { mainProgram = "jupyter-notebook"; }; + + passthru.tests = callPackage ./tests {}; }); in diff --git a/pkgs/applications/editors/jupyter/tests/default.nix b/pkgs/applications/editors/jupyter/tests/default.nix new file mode 100644 index 0000000000000..9d5bdd80aa07e --- /dev/null +++ b/pkgs/applications/editors/jupyter/tests/default.nix @@ -0,0 +1,11 @@ +{ pkgs }: +{ + jupyter-all = pkgs.jupyter.override { + definitions = { + clojure = pkgs.clojupyter.definition; + octave = pkgs.octave-kernel.definition; + # wolfram = wolfram-for-jupyter-kernel.definition; # unfree + }; + }; + +} diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix index 79c739e47f894..6b65b3d3f2f4b 100644 --- a/pkgs/top-level/aliases.nix +++ b/pkgs/top-level/aliases.nix @@ -435,6 +435,7 @@ mapAliases ({ jfbview = throw "'jfbview' has been removed, because it depends on an outdated and insecure version of mupdf"; # Added 2023-06-27 jira-cli = throw "jira-cli was removed because it is no longer maintained"; # Added 2023-02-28 join-desktop = throw "'join-desktop' has been removed because it is unmaintained upstream"; # Added 2023-10-04 + jupyter-all = jupyter.tests; # Julia diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 06c0f51944ac0..5160f14623be0 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -9723,14 +9723,6 @@ with pkgs; jupyter = callPackage ../applications/editors/jupyter { }; jupyterLib = callPackage ../applications/editors/jupyter/lib.nix { }; - jupyter-all = jupyter.override { - definitions = { - clojure = clojupyter.definition; - octave = octave-kernel.definition; - # wolfram = wolfram-for-jupyter-kernel.definition; # unfree - }; - }; - jupyter-console = callPackage ../applications/editors/jupyter/console.nix { }; jupyter-kernel = callPackage ../applications/editors/jupyter/kernel.nix { }; From cb1e1c53a2796f644daa37ede2e62d4cf2e49774 Mon Sep 17 00:00:00 2001 From: Matthieu Coudron <886074+teto@users.noreply.github.com> Date: Tue, 2 Jan 2024 17:50:47 +0100 Subject: [PATCH 4/5] jupyter-console.mkConsole: moved to jupyterLib ... though I've let the reference accessible (for now) in jupyter-console. I hope to remove `jupyter-console.mkConsole` in a next PR after more discussions, possibly along with `withSingleKernel` ? --- pkgs/applications/editors/jupyter/console.nix | 26 +++---------------- pkgs/applications/editors/jupyter/lib.nix | 16 ++++++++++++ 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/pkgs/applications/editors/jupyter/console.nix b/pkgs/applications/editors/jupyter/console.nix index 06bc82a1780b4..9b358d3f83eb4 100644 --- a/pkgs/applications/editors/jupyter/console.nix +++ b/pkgs/applications/editors/jupyter/console.nix @@ -1,36 +1,16 @@ { python3 , jupyter-kernel +, jupyterLib , lib }: - -let - mkConsole = { - definitions ? jupyter-kernel.default - , kernel ? null - }: - (python3.buildEnv.override { - extraLibs = [ python3.pkgs.jupyter-console ]; - makeWrapperArgs = [ - "--set JUPYTER_PATH ${jupyter-kernel.create { inherit definitions; }}" - ] ++ lib.optionals (kernel != null) [ - "--add-flags --kernel" - "--add-flags ${kernel}" - ]; - }).overrideAttrs (oldAttrs: { - # To facilitate running nix run .#jupyter-console - meta = oldAttrs.meta // { mainProgram = "jupyter-console"; }; - }); - -in - { # Build a console derivation with an arbitrary set of definitions, and an optional kernel to use. # If the kernel argument is not supplied, Jupyter console will pick a kernel to run from the ones # available on the system. - inherit mkConsole; + inherit (jupyterLib) mkConsole; # An ergonomic way to start a console with a single kernel. - withSingleKernel = definition: mkConsole { + withSingleKernel = definition: jupyterLib.mkConsole { definitions = lib.listToAttrs [(lib.nameValuePair definition.language definition)]; kernel = definition.language; }; diff --git a/pkgs/applications/editors/jupyter/lib.nix b/pkgs/applications/editors/jupyter/lib.nix index 1388ab90301d6..aa36dcf131795 100644 --- a/pkgs/applications/editors/jupyter/lib.nix +++ b/pkgs/applications/editors/jupyter/lib.nix @@ -61,5 +61,21 @@ logo64 = "${env}/${env.sitePackages}/ipykernel/resources/logo-64x64.png"; }; + mkConsole = { + definitions ? jupyter-kernel.default + , kernel ? null + }: + (python3.buildEnv.override { + extraLibs = [ python3.pkgs.jupyter-console ]; + makeWrapperArgs = [ + "--set JUPYTER_PATH ${jupyter-kernel.create { inherit definitions; }}" + ] ++ lib.optionals (kernel != null) [ + "--add-flags --kernel" + "--add-flags ${kernel}" + ]; + }).overrideAttrs (oldAttrs: { + # To facilitate running nix run .#jupyter-console + meta = oldAttrs.meta // { mainProgram = "jupyter-console"; }; + }); } From ff1bd4acae2d4d3d72779da98e66e90a0ded573c Mon Sep 17 00:00:00 2001 From: Matthieu Coudron <886074+teto@users.noreply.github.com> Date: Tue, 2 Jan 2024 18:04:24 +0100 Subject: [PATCH 5/5] doc: add a jupyter section we have many kernels available and nixpkgs should be a good way to configure software as complex as jupyter. Right now our API is not straightforward and thus needs documenting. This is not the final doc, it's an initial PR to bootstrap the effort and refine the nixpkgs API for jupyter. future work: document how to wrap jupyter-notebook --- doc/packages/index.md | 1 + doc/packages/jupyter.section.md | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 doc/packages/jupyter.section.md diff --git a/doc/packages/index.md b/doc/packages/index.md index 1f45018ffc4a0..3b50f72f9b9fa 100644 --- a/doc/packages/index.md +++ b/doc/packages/index.md @@ -13,6 +13,7 @@ firefox.section.md fish.section.md fuse.section.md ibus.section.md +jupyter.section.md kakoune.section.md linux.section.md locales.section.md diff --git a/doc/packages/jupyter.section.md b/doc/packages/jupyter.section.md new file mode 100644 index 0000000000000..562a356d9e5ae --- /dev/null +++ b/doc/packages/jupyter.section.md @@ -0,0 +1,32 @@ +# jupyter {#sec-jupyter} + +Jupyter has different frontends that can be configured: jupyter-console and +jupyter-notebook. The approach is the same: +1. create a folder that contains all the jupyter kernels +2. wrap the executables + +```nix +let + definitions = { + python = jupyterLib.mkKernelFromPythonEnv (python3.withPackages(ps: [ + ps.numpy ]); + haskell = jupyterLib.mkKernelFromHaskellEnv (pkgs.haskellPackages.ghcWithPackages(hs: [ hs.aeson + ]); + # ... and all other kernels you are interested in + }; + myKernels = jupyter-kernel.create { + inherit definitions; + }; +in + # pseudocode, real code in next sections + jupyter frontend wrapped with JUPYTER_PATH=myKernels +``` + + +## How to run jupyter-console with arbitrary kernels ? {#sec-jupyter-console} + +```nix +myJupyterConsole = jupyter-console.mkConsole { + inherit definitions; +} +```