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; +} +``` 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/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/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/applications/editors/jupyter/lib.nix b/pkgs/applications/editors/jupyter/lib.nix new file mode 100644 index 0000000000000..aa36dcf131795 --- /dev/null +++ b/pkgs/applications/editors/jupyter/lib.nix @@ -0,0 +1,81 @@ +{ 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"; + }; + + 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"; }; + }); + +} 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 26f01082edd50..5160f14623be0 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -9721,14 +9721,7 @@ with pkgs; jupp = callPackage ../applications/editors/jupp { }; jupyter = callPackage ../applications/editors/jupyter { }; - - jupyter-all = jupyter.override { - definitions = { - clojure = clojupyter.definition; - octave = octave-kernel.definition; - # wolfram = wolfram-for-jupyter-kernel.definition; # unfree - }; - }; + jupyterLib = callPackage ../applications/editors/jupyter/lib.nix { }; jupyter-console = callPackage ../applications/editors/jupyter/console.nix { };