Commit 1da53a23 authored by Ludovic Courtès's avatar Ludovic Courtès
Browse files

Add support for a built-in Guile kernel.

* jupyter/kernels.scm (jupyter-kernel-path, kernel-specs): Export.
* jupyter/guile.scm (guile-kernel-specs, available-kernel-specs-files):
New procedures.
* guix-jupyter-kernel.scm (create-environment): Use
'available-kernel-specs' instead of 'available-kernel-specs-files' and
adjust accordingly.
(start-container)[spawn]: Likewise.
* guix-kernel-demo.ipynb: Add example.
parent 2aa7a9fd
......@@ -42,6 +42,7 @@
(jupyter messages)
(jupyter kernels)
(jupyter servers)
(jupyter guile)
(guix jupyter containers)
(guix jupyter logging)
(guix jupyter proxy)
......@@ -171,15 +172,14 @@ to KERNEL as a reply to MESSAGE, and return STATE suitably adjusted."
(mbegin %store-monad
(built-derivations (list drv)) ;XXX: somewhat ugly
(return drv))))))
(match (available-kernel-specs-files
(list (string-append (derivation->output-path profile)
"/share/jupyter")))
((specs-file)
(match (available-kernel-specs (derivation->output-path profile)
(list (string-append
(derivation->output-path profile)
"/share/jupyter")))
((specs)
(let* ((container (run-with-store store
(start-container container-context
name profile)))
(specs (call-with-input-file specs-file
json->kernel-specs))
(state (register-proxied name container state)))
(monitor-client container)
(reply-for-environment-kernel kernel message
......@@ -204,9 +204,7 @@ to KERNEL as a reply to MESSAGE, and return STATE suitably adjusted."
" kernels in environment "
(code ,name) ":")
(ul ,@(map (lambda (file)
(let ((specs (call-with-input-file file
json->kernel-specs)))
`(li ,(kernel-specs-display-name specs))))
`(li ,(kernel-specs-display-name specs)))
lst))
"Which one should we use? Please create an "
"environment containing exactly one kernel."))
......@@ -418,12 +416,14 @@ that container."
(with-imported-modules (source-module-closure
'((guix profiles)
(guix search-paths)
(jupyter kernels))
(jupyter kernels)
(jupyter guile))
#:select? module-to-import?)
#~(begin
(use-modules (guix profiles)
(guix search-paths)
(jupyter kernels) ;json->connection
(jupyter guile)
(ice-9 match))
;; (set-network-interface-up "lo") ;up lo interface
......@@ -443,14 +443,15 @@ that container."
(profile-search-paths #$profile))
(let ((str #$(scm->json-string (connection->json connection))))
(match (available-kernel-specs-files)
((specs-file)
(match (available-kernel-specs #$profile
(list (getenv "JUPYTER_PATH")))
((specs)
(format (current-error-port)
"starting kernel from '~a'...~%"
specs-file)
(let ((specs (call-with-input-file specs-file
json->kernel-specs)))
(exec-kernel specs (json->connection str))))))))))
"starting kernel for '~a'...~%"
(kernel-specs-display-name specs))
(exec-kernel specs (json->connection str)))
(()
#f)))))))
(define-values (connection kernel)
(allocate-connection context "tcp" "127.0.0.1"
......
%% Cell type:markdown id: tags:
# Demo Guix Jupyter kernel
Project source code: [Guix-kernel](https://gitlab.inria.fr/guix-hpc/guix-kernel).
![Guix-Jupyter](logo.png)
---
## Getting Started
The `;;guix environment` _magic command_ allows you to create an execution environment containing a Jupyter kernel, or to run code in a previously-created environment.
---
%% Cell type:markdown id: tags:
### Evaluating Code in a Jupyter Kernel
Create an environment called `guile-kernel` containing the Guile kernel for Jupyter:
%% Cell type:code id: tags:
``` scheme
;;guix environment guile-kernel-env <- jupyter-guile-kernel
```
%% Cell type:markdown id: tags:
Run code in guile kernel:
%% Cell type:code id: tags:
``` scheme
;;guix environment guile-kernel-env
(define (list-environ env)
(for-each (lambda (variable)
(display variable)
(newline))
(environ)))
```
%% Cell type:code id: tags:
``` scheme
;; Here we don't repeat "guix environment", so we use the
;; same environment as the previous cell.
(list-environ (environ))
```
%% Cell type:code id: tags:
``` scheme
(define (random-art num)
(define (new-char)
(if (eq? (random 10) 5)
(display "+")
(display "."))
(random-art (- num 1)))
(if (not (zero? num))
(new-char)))
```
%% Cell type:markdown id: tags:
Call the previously-defined function in the Guile kernel:
%% Cell type:code id: tags:
``` scheme
(random-art 3000)
```
%% Cell type:markdown id: tags:
---
## Using IPython
### Create an environment with IPython
%% Cell type:code id: tags:
``` scheme
;;guix environment my-ipython <- python-ipython python-ipykernel
```
%% Cell type:markdown id: tags:
---
### Run code in the IPython kernel
%% Cell type:code id: tags:
``` scheme
;;guix environment my-ipython
# This is python lang !
def hello ():
print ("Hello Jupyter !")
hello ()
```
%% Cell type:code id: tags:
``` scheme
;;guix environment my-ipython
import os
os.getcwd()
```
%% Cell type:code id: tags:
``` scheme
os.getuid()
```
%% Cell type:code id: tags:
``` scheme
os.getpid()
```
%% Cell type:code id: tags:
``` scheme
os.listdir('/')
```
%% Cell type:markdown id: tags:
## A Matplotlib environment
%% Cell type:code id: tags:
``` scheme
;;guix environment matplotlib-env <- python-ipython python-ipykernel python-ipywidgets python-matplotlib
```
%% Cell type:code id: tags:
``` scheme
;;guix environment matplotlib-env
%matplotlib inline
from matplotlib import pyplot as plt
from matplotlib import style
import random
x = random.sample(range(1, 5000), 1000)
num_bins = 100
n, bins, patches = plt.hist(x, num_bins, facecolor='green', alpha=0.5)
plt.title('Histogram Example')
plt.xlabel('Values')
plt.xlabel('Counts')
plt.show()
```
%% Cell type:code id: tags:
``` scheme
;;guix environment R <- r-irkernel r
;;guix environment R <- r r-irkernel
```
%% Cell type:code id: tags:
``` scheme
;;guix environment R
version
```
%% Cell type:markdown id: tags:
### Using the built-in kernel for [GNU Guile](https://gnu.org/s/guile)
%% Cell type:code id: tags:
``` scheme
;;guix environment guile <- guile
```
%% Cell type:code id: tags:
``` scheme
2+2
(version)
```
%% Cell type:markdown id: tags:
---
`guix-kernel-demo.ipynb` for guix-kernel.
_Version 0.0.1_
......
......@@ -24,7 +24,8 @@
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-71)
#:use-module (ice-9 match)
#:export (run-guile-kernel))
#:export (run-guile-kernel
available-kernel-specs))
;;; Commentary:
;;;
......@@ -225,3 +226,57 @@ Return the kernel's state upon receiving a 'shutdown' request."
0)))
(close-kernel kernel)
result)))
(define (guile-kernel-specs guile)
"Return a <kernel-specs> record running the built-in Guile kernel with
GUILE, the file name of the 'guile' executable."
(define (directory path file)
(fold (lambda (_ file)
(dirname file))
(search-path path file)
(string-tokenize file (char-set-complement (char-set #\/)))))
(kernel-specs
(display-name "GNU Guile")
(language "Guile Scheme")
(arguments `(,guile
;; This beautiful hack allows us to get our dependencies.
"-L" ,(directory %load-path "jupyter/guile.scm")
"-L" ,(directory %load-path "gcrypt/mac.scm")
"-L" ,(directory %load-path "json.scm")
"-L" ,(directory %load-path "simple-zmq.scm")
"-C" ,(directory %load-compiled-path "jupyter/guile.go")
"-C" ,(directory %load-compiled-path "gcrypt/mac.go")
"-C" ,(directory %load-compiled-path "json/builder.go")
"-C" ,(directory %load-compiled-path "simple-zmq.go")
"-c"
,(object->string
'(begin
(use-modules (jupyter guile)
(jupyter kernels))
(call-with-input-file (car (last-pair (command-line)))
(compose run-guile-kernel json->connection))))
"--"
"{connection_file}"))))
(define* (available-kernel-specs profile
#:optional (path (jupyter-kernel-path)))
"Return the list of <kernel-specs> found in PATH, or a spec for the
built-in Guile kernel if PROFILE contains a 'guile' executable, or #f."
(define specs
(map (lambda (file)
(call-with-input-file file json->kernel-specs))
(available-kernel-specs-files path)))
(match specs
(()
(let ((guile (string-append profile "/bin/guile")))
(if (file-exists? guile)
(list (guile-kernel-specs guile))
'())))
(specs
specs)))
......@@ -32,7 +32,8 @@
#:use-module (srfi srfi-9 gnu)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-71)
#:export (find-kernel-specs
#:export (jupyter-kernel-path
find-kernel-specs
find-kernel-specs-file
available-kernel-specs-files
exec-kernel
......@@ -40,6 +41,7 @@
run-kernel
kernel-specs?
kernel-specs
kernel-specs-arguments
kernel-specs-display-name
kernel-specs-language
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment