Giter Site home page Giter Site logo

jupyter's Introduction

An interface to communicate with Jupyter kernels in Emacs.

Table of Contents

What does this package do?

  • Provides REPL and org-mode source block frontends to Jupyter kernels.
  • Kernel interactions integrated with Emacs’s built-in features. For example
    • Inspecting a piece of code under point will display the information for that symbol in the *Help* buffer. You can re-visit inspection requests made to the kernel by calling help-go-back or help-go-forward while in the *Help* buffer.
    • Uses the completion-at-point interface for code completion.
    • Kernel requests for user input entered through the minibuffer.
    • You can search through REPL history using isearch.

How do I install this package?

Using MELPA

NOTE: This package relies on the emacs-zmq package which means your Emacs needs to have been built with module support. See the README of that package for more information.

You can install this package with any package manager that allows you to install MELPA packages. For Emacs’s built-in package manager:

  1. Ensure MELPA is in package-archives
    (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
        
  2. Ensure the latest versions of MELPA packages are available

    M-x package-refresh-contents RET

  3. Install Jupyter

    M-x package-install RET jupyter RET

Manual installation

For a manual installation you can add the repository directory to your load-path and ensure the following dependencies are installed:

markdown-mode (optional)
https://jblevins.org/projects/markdown-mode/
company-mode (optional)
http://company-mode.github.io/
emacs-websocket
https://github.com/ahyatt/emacs-websocket
simple-httpd
https://github.com/skeeto/emacs-web-server
zmq
http://github.com/nnicandro/emacs-zmq
(add-to-list 'load-path "~/path/to/jupyter")
(require 'jupyter)

Building the widget support (EXPERIMENTAL)

There is limited support for interacting with Jupyter widgets through an external browser. In this case, Emacs acts as a relay for passing messages between the kernel and the browser.

To try it out, install node (https://nodejs.org/en/) then run the following shell command from the top-level directory of this project.

make widgets

After, launch Emacs, connect to a kernel (e.g. through a REPL), and run some code that creates a widget.

How do I run the tests?

You must have Cask installed to be able to run the tests. Once Cask is installed, in the top level directory of this project run the following from the command line

# Install all development dependencies via Cask
make dev

Then, to run the tests

# Run the whole set of tests
make test
# Run tests tagged with org
make test TAGS=org
# Run tests tagged with org and babel
make test TAGS=org,babel
# Run tests whose name match a pattern
make test PATTERN=font-lock

Related packages

ob-ipython

The org-mode source block frontend in emacs-jupyter is similar to what is offered by ob-ipython (and also the scimax version).

emacs-ipython-notebook (ein)

ein is a complete Jupyter notebook interface in Emacs with many powerful features for Python kernels. There is some overlap in the features provided by emacs-jupyter and ein, but I have never used ein so I cannot speak very much about any similarities/differences.

How do I use the built-in frontends?

REPL

M-x jupyter-run-repl launches a new local kernel and displays a REPL buffer.

M-x jupyter-connect-repl connects to an existing kernel using the kernel’s connection file, which is supplied by the user, and displays a REPL buffer.

The REPL supports some of the rich output that a kernel may send to a client, e.g. images, LaTeX, and HTML.

Rich kernel output

Below is a table of the supported output mimetypes and their dependencies. If a dependency is not available for a particular mimetype, a mimetype of lower priority gets displayed instead.

For widgets, before attempting to open one, you also need to run the shell command make widgets in the top-level directory of this project to build some JavaScript files.

MimetypeDependencies
application/vnd.jupyter.widget-view+jsonwebsocket, simple-httpd
text/htmlEmacs built with libxml2
text/markdownmarkdown-mode
text/latexorg-mode
image/svg+xmlEmacs built with librsvg2
image/pngnone
text/plainnone

Inspection

To inspect the code around point press M-i.

Completion

Completion is implemented through the completion-at-point interface and should just work.

In addition to completing symbols in the REPL buffer, completion also works in buffers associated with a REPL. For org-mode users, there is even completion in the org-mode buffer when editing the contents of a Jupyter source code block.

REPL history

To navigate the REPL history: M-n and M-p.

To search the REPL history: C-s and C-s C-r.

Associating buffers with a REPL (jupyter-repl-interaction-mode)

M-x jupyter-repl-associate-buffer sets the jupyter-current-client of the current buffer to an existing REPL client and enables jupyter-repl-interaction-mode, allowing you to, for example, send the current line for evaluation by the client’s kernel.

When jupyter-repl-interaction-mode is enabled, the following keybindings are available

Key bindingCommand
C-M-xjupyter-eval-defun
M-ijupyter-inspect-at-point
C-c C-bjupyter-eval-buffer
C-c C-cjupyter-eval-line-or-region
C-c C-ijupyter-repl-interrupt-kernel
C-c C-rjupyter-repl-restart-kernel
C-c C-sjupyter-repl-scratch-buffer
C-c C-ojupyter-eval-remove-overlays
C-c M-:jupyter-eval-string

Integration with emacsclient

If emacsclient is set as the EDITOR and evaluated code opens a file in a major-mode compatible with the client that sent the code, the opened file will automatically be associated with the client and have jupyter-repl-interaction-mode enabled.

This feature probably wont work correctly when there are multiple competing clients sending requests to their underlying kernels that want to open files or if the underlying kernel takes longer than jupyter-long-timeout seconds to open a file.

See jupyter-server-mode-set-client for more details.

jupyter-repl-maximum-size

A variable that determines the maximum number of lines a REPL buffer can have before being truncated.

jupyter-repl-allow-RET-when-busy

A variable that determines whether to allow insertion of newlines in a REPL cell when a kernel is busy or not. See the variable documentation for more details.

jupyter-repl-echo-eval-p

A variable that determines whether code evaluated with the jupyter-eval-* commands gets copied over to a REPL input cell or not. You can set this variable to t if you prefer having the history of all evaluated code visible in the REPL.

org-mode source blocks

To enable support for Jupyter based source code blocks, add jupyter to org-babel-load-languages. Ensure the jupyter entry is added last since loading ob-jupyter depends on the value of variables such as org-src-lang-modes and org-babel-tangle-lang-exts.

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (julia . t)
   (python . t)
   (jupyter . t)))

After loading, source code blocks with names like jupyter-LANG will be available for use. LANG can be any one of the kernel languages found on your system. See jupyter-available-kernelspecs.

  • The :session parameter is required for all Jupyter based source code blocks.
    #+BEGIN_SRC jupyter-python :session py
    x = 'foo'
    y = 'bar'
    x + ' ' + y
    #+END_SRC
        
  • By default, source blocks are executed synchronously. To execute a source block asynchronously set the :async parameter to yes:
    #+BEGIN_SRC jupyter-python :session py :async yes
    x = 'foo'
    y = 'bar'
    x + ' ' + y
    #+END_SRC
        
  • To change the kernel, set the :kernel parameter.
    #+BEGIN_SRC jupyter-python :session py :async yes :kernel python2
    x = 'foo'
    y = 'bar'
    x + ' ' + y
    #+END_SRC
        

    Note, the same session name can be used for different values of :kernel since the underlying REPL buffer’s name is based on both :session and :kernel.

  • Any of the default parameters for a language can be changed by setting org-babel-default-header-args:jupyter-LANG to an appropriate value. For example to change the defaults for the julia kernel, you can set org-babel-default-header-args:jupyter-julia to something like
    (setq org-babel-default-header-args:jupyter-julia '((:async . "yes")
                                                        (:session . "jl")
                                                        (:kernel . "julia-1.0")))
        

Note on the language name provided by a kernelspec

Some kernelspecs use spaces in the name of the kernel language. Those get replaced by dashes in the language name you need to use for the corresponding source blocks, e.g. Wolfram Language has the source block language jupyter-Wolfram-Language.

Integration with ob-async

If you have ob-async installed and are getting errors when your source block specifies the :async header argument, try putting something like the following in your configuration:

(setq ob-async-no-async-languages-alist '("jupyter-python" "jupyter-julia"))

See ob-async-no-async-languages-alist for more details.

Issues with ob-ipython

If both ob-ipython and this package are installed, you may experience issues such as this one, causing Search failed errors. To avoid such errors, remove ipython from org-babel-do-load-languages and restart your Emacs.

Overriding built-in src-block languages

Instead of having to specify jupyter-LANG as a source block name, you can have LANG source blocks use the Jupyter machinery. To do so, place a call to org-babel-jupyter-override-src-block somewhere in your config (after the call to org-babel-do-load-languages).

(org-babel-jupyter-override-src-block "python")

After calling the above function, all python source blocks are effectively aliases of jupyter-python source blocks and the variable org-babel-default-header-args:python will be set to the value of org-babel-default-header-args:jupyter-python.

Note, org-babel-default-header-args:python will not be an alias of org-babel-default-header-args:jupyter-python, the value of the former is merely set to the value of the latter after calling org-babel-jupyter-override-src-block.

You can restore the original behavior by calling org-babel-jupyter-restore-src-block.

(org-babel-jupyter-restore-src-block "python")

Rich kernel output

The supported display mimetypes ordered by priority are:

  • text/org
  • image/svg+xml, image/jpeg, image/png
  • text/html
  • text/markdown
  • text/latex
  • text/plain

A note on using the :results header argument

There are some cases where the normal result insertion mechanism may not be wanted. To control result insertion somewhat, use the :results header argument:

Insert unwrapped LaTeX
Normally LaTeX results are wrapped in a BEGIN_EXPORT block, in order to insert LaTeX unwrapped, specify :results raw.
Suppress table creation
Whenever a result can be converted into an org-mode table, e.g. when it look like [1, 2 , 3], it is automatically converted into a table. To suppress this behavior you can specify :results scalar.

Fixing the file name of images with the :file argument

Whenever an image result is returned, a random image file name is generated and the image is written to org-babel-jupyter-resource-directory. To specify your own file name for the image, set the :file header argument.

If no file extension is specified in the provided :file, then one will be inferred from the returned output. This can be useful in scenarios where the file resulting from the src-block can have different types depeneding on the code, e.g. if the image type returned can be either png or svg depending on certain settings, you can specify :file = output which will be converted into output.png or output.svg depending on the MIME type return by the executed src-block.

Changing the mime-type priority with the :display argument

The priority of mimetypes used to display results can be overwritten using the :display option. If instead of displaying HTML results we’d wish to display plain text, the argument :display text/plain text/html would prioritize plain text results over html ones. The following example displays plain text instead of HTML:

#+BEGIN_SRC jupyter-python :session py :display plain
import pandas as pd
data = [[1, 2], [3, 4]]
pd.DataFrame(data, columns=["Foo", "Bar"])
#+END_SRC

Image output without the :file header argument

For images sent by the kernel, if no :file parameter is provided to the code block, a file name is automatically generated based on the image data and the image is written to file in org-babel-jupyter-resource-directory. This is great for quickly generating throw-away plots while you are working on your code. Once you are happy with your results you can specify the :file parameter to fix the file name.

org-babel-jupyter-resource-directory

This variable is similar to org-preview-latex-image-directory but solely for any files created when Jupyter code blocks are run, e.g. automatically generated image file names.

Deletion of generated image files

Whenever you run a code block multiple times and replace its results, before the results are replaced, any generated files will be deleted to reduce the clutter in org-babel-jupyter-resource-directory.

Convert rich kernel output with the :pandoc header argument

By default html, markdown, and latex results are wrapped in a BEGIN_EXPORT block. If the header argument :pandoc t is set, they are instead converted to org-mode format with pandoc. You can control which outputs get converted with the custom variable jupyter-org-pandoc-convertable.

Editing the contents of a code block

When editing a Jupyter code block’s contents, i.e. by pressing C-c '= when at a code block, =jupyter-repl-interaction-mode is automatically enabled in the edit buffer and the buffer will be associated with the REPL session of the code block (see jupyter-repl-associate-buffer).

You may also bind the command org-babel-jupyter-scratch-buffer to an appropriate key in org-mode to display a scratch buffer in the code block’s major-mode and connected to the code block’s session.

Connecting to an existing kernel

To connect to an existing kernel, pass the kernel’s connection file as the value of the :session parameter. The name of the file must have a .json suffix for this to work.

Remote kernels

If the connection file is a remote file name, i.e. has a prefix like /method:host:, the kernel’s ports are assumed to live on host. Before attempting to connect to the kernel, ssh tunnels for the connection are created. So if you had a remote kernel on a host named ec2 whose connection file is /run/user/1000/jupyter/kernel-julia-0.6.json on that host, you could specify the :session like

#+BEGIN_SRC jupyter-julia :session /ssh:ec2:/run/user/1000/jupyter/kernel-julia-0.6.json
...
#+END_SRC

Note, the kernel on the remote host needs to have the ZMQ socket ports exposed. This means that starting a kernel using

jupyter notebook --no-browser

currently doesn’t work since the notebook server does not allow communication with a kernel using ZMQ sockets. You will have to use the connection file created from using something like

jupyter kernel --kernel=python
Password handling for remote connections

Currently there is no password handling, so if your ssh connection requires a password I suggest you instead use key-based authentication. Or if you are connecting to a server using a pem file add something like

Host ec2
    User <user>
    HostName <host>
    IdentityFile <identity>.pem

to your ~/.ssh/config file.

Starting a remote kernel

If :session is a remote file name that doesn’t end in .json, e.g. /ssh:ec2:jl, then a kernel on the remote host /ssh:ec2: is started using the jupyter kernel command on the host. The local part of the session name serves to distinguish different remote sessions on the same host.

Communicating with kernel (notebook) servers

If :session is a TRAMP file name like /jpy:localhost#8888:NAME it is interpreted as corresponding to a connection to a kernel through a Jupyter notebook server located at http://localhost:8888.

If NAME is a kernel ID corresponding to an existing kernel on a server, e.g. /jpy::161b2318-180c-497a-b4bf-de76176061d9, then a connection to an existing kernel with the corresponding ID will be made. Otherwise, a new kernel will be launched on the server and NAME will be used as an identifier for the session.

When a new kernel is launched, NAME will also be associated with the kernel’s ID, see jupyter-server-kernel-names. This is useful to distinguish Org mode :session kernels from other ones in the buffer shown by jupyter-server-list-kernels.

When connecting to an existing kernel, i.e. when NAME is the ID of a kernel, the :kernel header argument must match the name of the kernel’s kernelspec.

To connect to a kernel behind an HTTPS connection, use a TRAMP file name that looks like /jpys:... instead.

Standard output, displayed data, and code block results

In contrast to non-Jupyter code blocks, the kernel of Jupyter code block can request extra data, other than stdout or a code block’s result, be displayed (see display_data messages).

To account for this, Jupyter code blocks do not go through the normal org-mode result insertion mechanism (see org-babel-insert-result), instead providing its own result insertion. The downside is that, compared to normal org-mode code blocks, only a small subset of the header arguments are supported. The upside is that all forms of results produced by a kernel can be inserted into the buffer similar to a Jupyter notebook.

jupyter-org-interaction-mode

A minor mode that enables completion and custom keybindings when point is inside a Jupyter code block. This mode is enabled by default in org-mode buffers, but only has an effect when point is inside a Jupyter code block.

Custom keybindings inside Jupyter code blocks

You can define new keybindings that are enabled when point is inside a Jupyter code block by using the function jupyter-org-define-key. These bindings are added to jupyter-org-interaction-mode-map and are only active when jupyter-org-interaction-mode is enabled.

By default the following keybindings from jupyter-repl-interaction-mode are available when jupyter-org-interaction-mode is enabled

Key bindingCommand
C-M-xjupyter-eval-defun
M-ijupyter-inspect-at-point
C-x C-ejupyter-eval-line-or-region
C-c C-ijupyter-repl-interrupt-kernel
C-c C-rjupyter-repl-restart-kernel

Disable automatic connections to a source block session

When typing into the region of a Jupyter source block, under certain conditions, an attempt at connecting to the source block’s session is made if not already connected.

This behavior can be suppressed by setting jupyter-org-auto-connect to nil. In this case, a connection is attempted upon executing a source block, for example.

Enable client-side queuing of requests

If the customizable variable jupyter-org-queue-requests is non-nil, then perform client side queuing of source block execute requests. This means that when multiple requests are made, for example by executing a subtree, the requests are queued locally in Emacs instead of sending all the requests immediately to the kernel as would happen when :async yes is specified on all the source blocks. It is only when one request finishes that the next is sent. In addition, if any request fails all the queued requests that are meant to come after it are aborted and do not get sent to the kernel.

Kernel/notebook server

Managing live kernels

The main entry point for working with a kernel server is the jupyter-server-list-kernels command which shows a list of all live kernels from the server URL that you provide when first calling the command. Any subsequent calls to the command will use the same URL as the first call. To change server URLs give a prefix argument, C-u M-x jupyter-server-list-kernels. This will then set the current server URL for future calls to the one you provide. See the jupyter-current-server command for more details.

From the buffer shown by jupyter-server-list-kernels you can launch new kernels (C-RET), connect a REPL to an existing kernel (RET), interrupt a kernel (C-c TAB), kill a kernel (C-c C-d or d), refresh the list of kernels (g) etc. See the jupyter-server-kernel-list-mode for all the available key bindings.

Note, the default-directory of the jupyter-server-kernel-list-mode buffer will be the root directory of the kernel server (so that dired-jump will show a dired listing of the directory). See the section on TRAMP integration below.

Naming kernels

From the jupyter-server-list-kernels buffer one can also name (or rename) a kernel (R) so that it has an identifier other than its ID. Naming a kernel adds the name to the jupyter-server-kernel-names global variable in a form suitable for persisting across Emacs sessions. See its documentation for more details about persisting its value.

TRAMP integration

There is also integration with the Jupyter notebook contents API in the form of a TRAMP backend. This means that reading/writing the contents of directories the notebook server has access to can be done using normal Emacs file operations using file names with TRAMP syntax. Two new TRAMP file name methods are defined, jpy for HTTP connections and jpys for HTTPS connections. So suppose you have a local notebook server at http://localhost:8888, then to access its directory contents you can type

M-x dired RET /jpy:localhost#8888:/

Note localhost is the default host and 8888 is the default port so /jpy:: is equivalent to /jpy:localhost#8888:. You can change the defaults by modifying the jpy or jpys methods in the variable tramp-methods and tramp-default-host-alist.

jupyter-api-authentication-method

Authentication method used for new notebook server connections. By default, when connecting to a new notebook server you will be asked if either a password or a token should be used for authentication. If you only use tokens for authentication you can change this variable to avoid being asked on every new connection.

Customizable variables available for all frontends

jupyter-eval-use-overlays

When non-nil, display the text/plain representation of evaluation results inline using overlays. All other representations are displayed in the usual way. This only works with the jupyter-eval-* commands like jupyter-eval-line-or-region.

You can control the appearance of the overlay, see jupyter-eval-overlay-prefix and the jupyter-eval-overlay face.

To clear all overlays from the buffer, bind jupyter-eval-remove-overlays to some key. Its bound to C-c C-o when jupyter-repl-interaction-mode is enabled. Individual overlays are removed whenever the text in the region that was evaluated is modified.

For multi-line overlays you can fold/unfold the overlay by pressing S-RET when point is inside the region of code that caused the overlay to be created. See jupyter-eval-overlay-keymap.

jupyter-eval-short-result-max-lines

If the number of lines of an evaluation result is smaller than this variable, the function stored in jupyter-eval-short-result-display-function is used to display a result.

jupyter's People

Contributors

ahmed-shariff avatar akirakyle avatar arthurcgusmao avatar astoff avatar cheremin avatar conao3 avatar dakra avatar dangirsh avatar jackkamm avatar jamieforth avatar juergenhoetzel avatar kevinjfoley avatar malb avatar mpereira avatar nnicandro avatar non-jedi avatar rhaps0dy avatar sebastianpech avatar timquelch avatar torfjelde avatar undeadkernel avatar vale981 avatar xor-xor avatar xuning97 avatar xzz53 avatar yevgnen avatar ynakao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jupyter's Issues

Requirement of zeromq with draft API

Hey @dzop,

The library works very well. However, I faced many issues installing libzmq with draft API support. Most distributions do not supply the library with that compilation option enabled. In Arch GNU/Linux, for example, the package zeromq (which supplies libzmq) has to be recompiled from scratch and manually set to enable the draft APIs.

I was thinking that two paths could be taken to make this library easier to install for others:

  1. Only use the non-draft API and detect if it's enabled for optional functionality.
  2. Provide a static local library (of libzmq) and compile it at installation time.

Do you think any of those two are a possibility?

Spacemacs layer and adding to melpa?

Hey,
I tried to write a spacemacs layer for this package (which on my main machine does work as intended but on my main machine the installation of the package from github fails for some reason not obvious to me).
This would be way easier if the package was on melpa, so do you plan on releasing it there?
If you are not to familiar with spacemacs the package installation is just done via quelpa which in turn fails to get the package-desc.

Thanks for the package, I think it will be a great addition to combine emacs with jupyter using this.

;;; packages.el --- emacs-jupyter layer packages file for Spacemacs.
;;
;; Copyright (c) 2012-2018 Sylvain Benner & Contributors
;;
;; Author: Benedikt Tissot <benneti@bennetis-xps>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3

;;; Commentary:

;; See the Spacemacs documentation and FAQs for instructions on how to implement
;; a new layer:
;;
;;   SPC h SPC layers RET
;;
;;
;; Briefly, each package to be installed or configured by this layer should be
;; added to `emacs-jupyter-packages'. Then, for each package PACKAGE:
;;
;; - If PACKAGE is not referenced by any other Spacemacs layer, define a
;;   function `emacs-jupyter/init-PACKAGE' to load and initialize the package.

;; - Otherwise, PACKAGE is already referenced by another Spacemacs layer, so
;;   define the functions `emacs-jupyter/pre-init-PACKAGE' and/or
;;   `emacs-jupyter/post-init-PACKAGE' to customize the package as it is loaded.

;;; Code:

(defconst emacs-jupyter-packages
  '(zmq
    simple-httpd
    websocket
    (emacs-jupyter :location (recipe
                              :fetcher github
                              :repo "dzop/emacs-jupyter"))))

(defun emacs-jupyter/init-zmq ()
  (use-package zmq
    :defer t
    :ensure nil))

(defun emacs-jupyter/init-simple-httpd ()
  (use-package simple-httpd
    :defer t
    :ensure nil))

(defun emacs-jupyter/init-websocket ()
  (use-package websocket
    :defer t
    :ensure nil))

(defun emacs-jupyter/init-emacs-jupyter ()
  (use-package emacs-jupyter
    :defer t
    :ensure nil
    :after '(emacs-zmq websocket simple-httpd)))

;;; packages.el ends here

Send region of code to jupyter-repl with C-c C-c

I use elpy to edit .py files and want to send a region of code to a running jupyter-repl for evaluation. Also it would be nice to launch a REPL if it is not running and C-c C-c is invoked. I suspect the needed command is something like

(setq python-shell-interpreter "jupyter-repl")

error "Buffer *temp* has no process"

Hi dzop,

I happened across this package, and it looked like a very promising and useful thing, so I've spent the past bit trying to get it to work. Initially I was running into a wall because emacs-jupyter isn't compatible with the head of master for emacs-zmq, but I've gotten that bit worked out by using an old commit for emacs-zmq, but the error I'm getting now is a bit beyond me, so I was wondering if you could point me in the right direction. It seems to be caused by the inner workings of your emacs zmq library and possibly multiple processes, and I have to admit it's a bit beyond me. Important-sounding lines from backtrace below (from calling (jupyter-start-kernel "julia-1.0"):

Debugger entered--Lisp error: (zmq-subprocess-error void-function string-trim-right)
  signal(zmq-subprocess-error (void-function string-trim-right))
  zmq--subprocess-filter(#<process zmq> "(error void-function string-trim-right)")
  sleep-for(0.01)
  (while (null (process-get ioloop event)) (sleep-for 0.01))
  jupyter-ioloop-wait-until(:start #<process zmq>)
  jupyter--start-ioloop(#<jupyter-kernel-client jupyter-kernel-client>)
  jupyter-start-channels(#<jupyter-kernel-client jupyter-kernel-client>)
  jupyter-start-new-kernel("julia-1.0")

Appreciate any guidance you can offer.

emacs 100% cpu freeze when editing text in repl buffer

It seems to happen after I paste text from another buffer, or it may be when I go between normal and insert state (using evil) under certain unknown circumstances.

  • it is not another child process, it is emacs itself
  • doesn't trigger debugger, so I can't use that
  • using spacemacs on either mac or linux

info:

- OS: darwin (but happens on linux too)
- Emacs: 26.1
- Spacemacs: 0.300.0
- Spacemacs branch: develop (rev. 4b195ddfc)
- Graphic display: t
- Distribution: spacemacs
- Editing style: vim
- Completion: helm

only killing emacs and restarting works.

jupyter-output and jupyter-error windows not reused

I find the following behavior quite strange, is it intended?

Starting from one window showing a buffer with source code.
When I run a line which causes an error, the current window
is split below (half) and the buffer jupyter-error is
displayed there.
When I then run a line which produces output, the source code window is
split again and the buffer jupyter-output is displayed.
So far so good.
However, when I now run a line which again causes an error the code
window is split again displaying the jupyter-error buffer in two different
windows.
This way alternating output and error creates a bunch of vertically
stacked windows, until the code window reaches a certain height at which
point the window below of the code window is reused.

This also happens with multiple columns (see screenshot).
I think having one dedicated buffer for output and error would really help unclutter the frame.

image

New emacs frame for traceback on error

The current behavior opens a new window when an error occurs. Is it possible to set the default behavior to open a new frame with just the traceback as its content? This would allow the window layout for code editing and evaluation (REPL) to remain undisturbed.

When results are silent, errors could be displayed using a popup

Currently, when setting the results to be silent (i.e., :results silent), tracebacks are displayed on the message buffer. An enhancement would be to display these errors in a popup buffer using emacs' pop-to-buffer. This would enable, among other desired effects, to follow the link to the error printed as [goto error].

Setting up eldoc integration

Inspired by the scimax project, I've been trying to setup eldoc support for jupy code blocks.

The following code kind of works, but when jupyter-inspect is called from eldoc, the variable jupyter-current-client appears to be nil.

If I edebug-defun jupyter-inspect and manually set jupyter-current-client to #<jupyter-org-client jupyter-org-client> (it's the value it has when calling M-i), then eldoc will work fine.

(defun scimax-jupyter-eldoc-advice (orig-func &rest args)
  "Advice function to get eldoc signatures in blocks in org-mode."
  (or (scimax-jupyter-signature) (apply orig-func args)))

(defun scimax-jupyter-signature ()
  "Try to return a function signature for the thing at point."
  (when (and (eql major-mode 'org-mode)
	     (string= (or (get-text-property (point) 'lang) "") "jupy-python"))
    (save-window-excursion
     ;;; Essentially copied from (jupyter-inspect-at-point).
      (cl-destructuring-bind (code pos)
      (jupyter-code-context 'inspect)
    (jupyter-inspect code pos nil 0)) ;; Error: will not find jupyter-current-client
      (when (get-buffer "*Help*")
	(with-current-buffer "*Help*"
	  (goto-char (point-min))
	  (prog1
	      (cond
	       ((re-search-forward "Signature:" nil t 1)
		(buffer-substring (line-beginning-position) (line-end-position)))
	       ((re-search-forward "Docstring:" nil t 1)
		(forward-line)
		(buffer-substring (line-beginning-position) (line-end-position)))
	       (t
		nil))
	    ;; get rid of this so we don't accidently show old results later
	    (with-current-buffer "*Help*"
	      (toggle-read-only)
	      (erase-buffer))))))))

(defun scimax-jupyter-turn-on-eldoc ()
  "Turn on eldoc signatures."
  (interactive)
  (advice-add 'org-eldoc-documentation-function :around #'scimax-jupyter-eldoc-advice))

I was wondering why it's the case that M-i works as expected and eldoc doesn't. Who is setting jupyter-current-client for M-i?!

Can't restart kernel

When I try to do M-x jupyter-repl-restart-kernel I get the following error:

Wrong type argument: jupyter-kernel-client, nil, client

However, C-c C-r does succeed in restarting the kernel.

How to open a repl connected to the same session as my org SRC cells?

Right now, it seems that when opening a REPL I can either associate it with a new session or provide a connection file to associate it with an existing session. I don't know how to find the connection file for the session associate with my org notebook cells.

When opening a new REPL it'd be great if it provided a list of active kernels that I could connect to.

Clarify license of package

Headers of both this package and emacs-zmq state that they are released under GPLv2+. Could you confirm this? If so, the FSF recommends including the license in the repo with the source code I believe. Thanks.

interacting with REPL after jupyter-connect-repl

Long time user of ob-ipython here... I just learned about your package and it looks like everything I hoped ob-ipython would some day become. Good stuff.

After connecting to an already existing kernel via jupyter-connect-repl, when I try to interact with the REPL, I'm getting a Kernel not alive message. Interestingly, sending blocks of code works, and I can inspect the variables by running a separate jupyter console --existing in a terminal window. Thoughts?

Porting scimax's ob-ipython hydra

The ob-ipython version in scimax has a very nice hydra that allows us to interact with an org file as if it was a jupyter notebook. The hydra provides functions to restart the kernel, add new source blocks, split a block, clone a block, run all blocks up to a point and many others. The hydra's doc-string looks like this:

"
        Execute                   Navigate       Edit             Misc
----------------------------------------------------------------------
    _<return>_: current           _i_: previous  _w_: move up     _/_: inspect
  _S-<return>_: current to next   _k_: next      _s_: move down   _l_: clear result
_S-M-<return>_: to point          _g_: visible   _x_: kill        _L_: clear all
  _s-<return>_: Restart/block     _G_: any       _n_: copy        _._: complete
_M-s-<return>_: Restart/to point  ^ ^            _c_: clone
  _H-<return>_: Restart/buffer    ^ ^            _m_: merge
           _r_: Goto repl         ^ ^            _-_: split
           ^ ^                    ^ ^            _+_: insert above
           ^ ^                    ^ ^            _=_: insert below
           ^ ^                    ^ ^            _h_: header"

I have ported all these functions to work with emacs-jupyter.
@dzop, would you be interested in a pull request to add all these functions to jupyter-org-client?

Results output in org-mode

Thanks a lot for creating and maintaining this emacs package!

I am having some difficulties with the different output from ob-jupyter comparing to ob-python. Probably I misunderstand something but I would like to ask for some help.

I have the following document:

#+TITLE: test
#+PROPERTY: header-args :session :exports both

#+BEGIN_SRC jupyter-python
def stringcomposition(k, string):
    composition = []
    for i in range(len(string) - k + 1):
        pattern = string[i : i + k]
        composition.append(pattern)
    return composition

# Test
k = 5
string = "CAATCCAAC"

result = stringcomposition(k, string)

# Sort results
result = sorted(result)
print(result)
#+END_SRC

#+BEGIN_SRC python 
def stringcomposition(k, string):
    composition = []
    for i in range(len(string) - k + 1):
        pattern = string[i : i + k]
        composition.append(pattern)
    return composition

# Test
k = 5
string = "CAATCCAAC"

result = stringcomposition(k, string)

# Sort results
result = sorted(result)
print(result)
#+END_SRC

I understand that the output of the result will depend on the header arguments of the source block and if use print(result) or just result.

python :results output

#+RESULTS:
: ['AATCC', 'ATCCA', 'CAATC', 'CCAAC', 'TCCAA']

jupyter-python

#+RESULTS:
: ['AATCC', 'ATCCA', 'CAATC', 'CCAAC', 'TCCAA']
: 
  • The results are the same, even though jupyter seems to add a newline. Not a huge issue but is there a way to suppress it as it adds an unnecessary newline in the code block when exporting?

python :results output table

#+RESULTS:
| AATCC | ATCCA | CAATC | CCAAC | TCCAA |

jupyter-python :results table

#+RESULTS:
| : ['AATCC', 'ATCCA', 'CAATC', 'CCAAC', 'TCCAA'] |
  • python returns, as expected, a table containing the separate strings (this is my desired ouput here), but jupyter seems not to remove the leading colon which, I think, prevents the tabular output.

Jupyter does print a table if I use result in the source block instead of print(result)
jupyter-python

#+RESULTS:
| AATCC | ATCCA | CAATC | CCAAC | TCCAA |

If I want the output as a list:
python :results output list

#+RESULTS:
: - AATCC
: - ATCCA
: - CAATC
: - CCAAC
: - TCCAA

jupyter-python :results output list

#+RESULTS:
- : AATCC
- : ATCCA
- : CAATC
- : CCAAC
- : TCCAA
- :
  • In jupyter the : and the - are swapped and thus the : will also appear in front of the strings in the exported document, plus the empty newline.

Is there a way to work around these glitches or am I just using it in a wrong way and/or have wrong expectations?

Edit
The following behavior was caused by still having the following snippet from ob-ipython in iPython startup folder.

import IPython
from tabulate import tabulate

class OrgFormatter(IPython.core.formatters.BaseFormatter):
    def __call__(self, obj):
        try:
            return tabulate(obj, headers='keys',
                            tablefmt='orgtbl', showindex='always')
        except:
            return None

ip = get_ipython()
ip.display_formatter.formatters['text/org'] = OrgFormatter()

Jupyter does print a table if I use result in the source block instead of print(result)
jupyter-python

#+RESULTS:
:RESULTS:
|    | 0   | 1   | 2   | 3   | 4   |
|----+-----+-----+-----+-----+-----|
|  0 | A   | A   | T   | C   | C   |
|  1 | A   | T   | C   | C   | A   |
|  2 | C   | A   | A   | T   | C   |
|  3 | C   | C   | A   | A   | C   |
|  4 | T   | C   | C   | A   | A   |
:END:
  • even though it is a table now, the strings have been separated into the single characters
    A similar result is obtained if I select on element of the result list via [result[0]]
#+RESULTS:
:RESULTS:
|    | 0   | 1   | 2   | 3   | 4   |
|----+-----+-----+-----+-----+-----|
|  0 | A   | A   | T   | C   | C   |
:END:

Using [result] instead of result

#+RESULTS:
:RESULTS:
|    | 0     | 1     | 2     | 3     | 4     |
|----+-------+-------+-------+-------+-------|
|  0 | AATCC | ATCCA | CAATC | CCAAC | TCCAA |
:END:
  • this looks good, even though a header row and a row column have been added. Is there a way to remove them or control what they display?

PNG output rather than SVG in IHaskell

From #16 (comment)

For no :option no-svg:

MESSAGE: (:iopub :display-data (:data (:image/png iVBORw0 ...

For :option svg:

MESSAGE: (:iopub :display-data (:data (:text/html <img src="data:image/svg+xml;base64,PD94bWw

Use jupyter prefix instead of jupy for org-mode src-blocks

I haven't yet tried out the org-mode integration because my current setup uses ob-ipython for that; it would be nice if I could use both ob-ipython and emacs-jupyter in the same org document, so I could make the transition slowly, but that isn't currently possible because ob-ipython also uses jupyter-language as language names in SRC blocks. Since it's a more established package, it probably makes sense to change that here if it's going to change. Possible alternatives:

  • language-jupyter
  • jupy-language
  • ejupyter-language
  • jupyter.language
  • jupyter_language
  • ...

Integration with `emacsclient`

Currently when a kernel causes a source code file to be opened via emacsclient, e.g. when using the @edit macro in IJulia, the buffer is not associated with the client connected to the kernel. This means the user has to manually call jupyter-repl-associate-buffer to make the association. It would be useful to do this automatically.

The issue here is that when a file is opened via emacsclient, the buffer current before the file is opened is always the server-buffer and not a buffer associated with the kernel's client. The server-buffer is a buffer used internally by Emacs to handle requests from the server process, e.g. file opening requests.

I have a tentative solution which temporarily binds jupyter-current-client in the server-buffer after sending an execute-request so that any files opened by emacsclient within a timeout period after sending the request will automatically be associated with a client (thanks to
jupyter-repl-persistent-mode). The code can be found on the feature/emacsclient-integration branch.

This temporary binding works for the majority of cases. Certainly when all that is being evaluated is the @edit macro. It would fail if you have a calculation that goes on longer than the timeout and opens a file afterwards. Also this method does not consider sending multiple execute-requests with different clients, any one of which may open a file.

Some questions:

  • How could we make a timeout unnecessary? The issue is that the kernel decides on when to open a file via emacsclient so there is no way of knowing when the file will be opened or even which kernel opened it.
  • How to handle sending execute-requests from multiple clients? With the tentative solution, they would be competing for the chance to set jupyter-current-client in the server-buffer with the result being the client that sent the most recent request wins.

Error trying to run repl

After installing the package on MacOS and emacs 26.1, I tried to do M-x jupyter-run-repl and got the following cryptic error:

helm-M-x: Creating file with prefix: No such file or directory, /bin/bash: jupyter: command not found/emacs-kernel-

Not really sure what went wrong. Any ideas?

Org mode blocks also don't work.

org-mode: Alias for code block identifier

When users want to migrate from their existing org files which use

#+BEGIN_SRC python
1 + 1
#+END_SRC

to

#+BEGIN_SRC jupyter-python
1 + 1
#+END_SRC

the question arose whether it is possible to let org-mode know that a source block identifier python
should really use the machinery of the identifier jupyter-python - so no changes to existing org files are necessary.
For major mode discrimination there is org-src-lang-modes, but is there a similar thing for choosing the eval backend?

Support output streaming

This is more a question rather than an "issue".
One nice feature of using Jupyter Notebooks is that it shows the output of an executing block as it gets processed. That is, in long running blocks of code, printed strings are displayed immediately.
In emacs-jupyter, while running async tasks, print statements are only displayed once code blocks fully complete their execution. I see that there are quite some functions that talk about "result stream". What are these functions meant to do? Is this something that emacs-jupyter could support or is it too far fetched?

Symbol's value as variable is void: zmq-REQ

When I try to install the package, I get this error and the package install fails. I am using the cask method of install. During installation I get several of these errors, and then when I try to use the package, it also reports the same error. On emacs startup it cannot find the zeromq module. It then asks to build it, and fails with this error.

Problems with creating new REPL

I'm on master and Emacs 26.1.

I can successfully connect to existing jupyter kernel with jupyter-connect-repl. The REPL seems to work fine. All commands and plotting works as I'd expect.

However, I cannot start a new REPL using jupyter-run-repl. I get the following error

jupyter-read-kernelspec: No kernel.json file found in /home/tom/src/venv/my-venv-name/lib/python3.5/site-packages/ipykernel/resources

Any tips for solving this? I have also problems with the org integration but I think it might be related to this.

The :file header argument sometimes does not work.

Steps to reproduce:

  1. Open scratch buffer
  2. Create a jupy-python src block with the following contents:
#+begin_src jupy-python :file garbage.png :session foo
import matplotlib.pyplot as plt
plt.plot([1,2,3])
#+end_src
  1. Execute block with C-c C-c
    See results showing up empty:
#+RESULTS:
  1. Press C-c C-c again.
    See file garbage.png showing up.

  2. Change plotting code and re-execute block:

plt.plot([1,4,3])

Image does not update. If I retry executing the block after some time, then the plot will eventually update.

Sometimes during the process I get the following error:

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  expand-file-name(nil)
  (let* ((link-path (org-element-property :path (org-element-context))) (link-dir (expand-file-name (file-name-directory link-path))) (resource-dir (expand-file-name org-babel-jupyter-resource-directory))) (if (and (equal link-dir resource-dir) (file-exists-p link-path)) (progn (delete-file link-path))))
  (while (re-search-forward link-re bound t) (let* ((link-path (org-element-property :path (org-element-context))) (link-dir (expand-file-name (file-name-directory link-path))) (resource-dir (expand-file-name org-babel-jupyter-resource-directory))) (if (and (equal link-dir resource-dir) (file-exists-p link-path)) (progn (delete-file link-path)))))
  (let ((bound (org-babel-result-end))) (while (re-search-forward link-re bound t) (let* ((link-path (org-element-property :path (org-element-context))) (link-dir (expand-file-name (file-name-directory link-path))) (resource-dir (expand-file-name org-babel-jupyter-resource-directory))) (if (and (equal link-dir resource-dir) (file-exists-p link-path)) (progn (delete-file link-path))))))
  (save-excursion (goto-char result-pos) (forward-line) (let ((bound (org-babel-result-end))) (while (re-search-forward link-re bound t) (let* ((link-path (org-element-property :path (org-element-context))) (link-dir (expand-file-name (file-name-directory link-path))) (resource-dir (expand-file-name org-babel-jupyter-resource-directory))) (if (and (equal link-dir resource-dir) (file-exists-p link-path)) (progn (delete-file link-path)))))))
  (if link-re (save-excursion (goto-char result-pos) (forward-line) (let ((bound (org-babel-result-end))) (while (re-search-forward link-re bound t) (let* ((link-path (org-element-property :path (org-element-context))) (link-dir (expand-file-name (file-name-directory link-path))) (resource-dir (expand-file-name org-babel-jupyter-resource-directory))) (if (and (equal link-dir resource-dir) (file-exists-p link-path)) (progn (delete-file link-path))))))))
  (let* ((result-pos (and t (org-babel-where-is-src-block-result))) (link-re (and result-pos (format "^[ \011]*%s[ \011]*$" org-bracket-link-regexp)))) (if link-re (save-excursion (goto-char result-pos) (forward-line) (let ((bound (org-babel-result-end))) (while (re-search-forward link-re bound t) (let* ((link-path (org-element-property :path (org-element-context))) (link-dir (expand-file-name (file-name-directory link-path))) (resource-dir (expand-file-name org-babel-jupyter-resource-directory))) (if (and (equal link-dir resource-dir) (file-exists-p link-path)) (progn (delete-file link-path)))))))))
  org-babel-jupyter-cleanup-file-links()
  (progn (org-babel-jupyter-cleanup-file-links))
  (if (member "replace" (assq :result-params params)) (progn (org-babel-jupyter-cleanup-file-links)))
  (let* ((jupyter-current-client (save-current-buffer (set-buffer (org-babel-jupyter-initiate-session (alist-get :session params) params)) jupyter-current-client)) (kernel-lang (jupyter-kernel-language jupyter-current-client)) (vars (org-babel-variable-assignments:jupyter params kernel-lang)) (code (org-babel-expand-body:jupyter body params vars kernel-lang)) (req (progn (eieio-oset jupyter-current-client 'block-params params) (jupyter-send-execute-request jupyter-current-client :code code)))) (if (member "replace" (assq :result-params params)) (progn (org-babel-jupyter-cleanup-file-links))) (cond ((or (equal (alist-get :async params) "yes") (plist-member params :async)) (if (progn (or (and (memq (type-of req) cl-struct-jupyter-org-request-tags) t) (signal 'wrong-type-argument (list 'jupyter-org-request req))) (aref req 12)) "" (jupyter-org-insert-async-id req))) (t (jupyter-wait-until-idle req most-positive-fixnum) (if (progn (or (and (memq (type-of req) cl-struct-jupyter-org-request-tags) t) (signal 'wrong-type-argument (list 'jupyter-org-request req))) (aref req 12)) (car (progn (or (and (memq (type-of req) cl-struct-jupyter-org-request-tags) t) (signal 'wrong-type-argument (list 'jupyter-org-request req))) (aref req 9))) (prog1 (jupyter-org-sync-results req) (nconc (alist-get :result-params params) (list "raw")))))))
  org-babel-execute:jupy-python("import matplotlib.pyplot as plt\nplt.plot([1,4,3])" ((:colname-names) (:rowname-names) (:result-params "file" "replace") (:result-type . value) (:results . "file replace") (:exports . "both") (:session . "ipython") (:cache . "no") (:kernel . "python3") (:noweb . "no") (:hlines . "no") (:tangle . "no") (:eval . "never-export") (:file . "garbage.png")))
  org-babel-execute-src-block(nil ("jupy-python" "import matplotlib.pyplot as plt\nplt.plot([1,4,3])" ((:colname-names) (:rowname-names) (:result-params "file" "replace") (:result-type . value) (:results . "file replace") (:exports . "both") (:file . "garbage.png") (:eval . "never-export") (:tangle . "no") (:hlines . "no") (:noweb . "no") (:kernel . "python3") (:cache . "no") (:session . "ipython")) "" nil 1 "(ref:%s)"))
  org-ctrl-c-ctrl-c(nil)
  funcall-interactively(org-ctrl-c-ctrl-c nil)
  call-interactively(org-ctrl-c-ctrl-c nil nil)
  command-execute(org-ctrl-c-ctrl-c)

cannot associate a buffer with a remote repl

Error is No REPL for `major-mode' exists. Start one? (y or n)

The repl was started by connecting (jupyter-connect-repl) to an existing remote kernel. The repl is running fine. However, buffers in emacs cannot be associated, I get the error above. Please let me know what information you may need.

Symbol’s value as variable is void: ob-jupyter

If I add jupyter in my init file (using spacemacs) like

(with-eval-after-load 'org
  (setq org-babel-load-languages
        (append org-babel-load-languages
                '((org . t)
                  (latex . t)
                  ;; This always has to be the last element of the list
                  (jupyter . t)
                  ))))

, I sometimes get the error
Symbol’s value as variable is void: ob-jupyter
in the messages buffer and additionally things like elfeed-org stop working.
Do you have any idea what the problem could be?

error in process sentinel: Wrong type argument: jupyter-org-request

Running the x + '_' + y example in the docs I get the following error:

error in process sentinel: Wrong type argument: jupyter-org-request, #s(jupyter-request "336a60fd-ffc7-4ca1-a6de-398c0d291540" (23658 58943 265619 297000) t (:header (message-part "{\"msg_id\":\"23d654f8-28e8e7f8c67d11b5d235d95b\",\"msg_type\":\"status\",\"username\":\"user\",\"session\":\"401554e2-99625c72c9b38ef672d71e97\",\"date\":\"2019-02-18T17:07:11.272461Z\",\"version\":\"5.3\"}" (:msg_id "23d654f8-28e8e7f8c67d11b5d235d95b" :msg_type :status :username "user" :session "401554e2-99625c72c9b38ef672d71e97" :date "2019-02-18T17:07:11.272461Z" :version "5.3")) :msg_id "23d654f8-28e8e7f8c67d11b5d235d95b" :msg_type :status :parent_header (message-part "{\"msg_id\":\"336a60fd-ffc7-4ca1-a6de-398c0d291540\",\"msg_type\":\"execute_request\",\"version\":\"5.3\",\"username\":\"user\",\"session\":\"c65d7238-78a3-4c80-8a98-a779f4a54324\",\"date\":\"2019-02-18T12:07:11.265661-05:00\"}" (:msg_id "336a60fd-ffc7-4ca1-a6de-398c0d291540" :msg_type :execute-request :version "5.3" :username "user" :session "c65d7238-78a3-4c80-8a98-a779f4a54324" :date "2019-02-18T12:07:11.265661-05:00")) :metadata (message-part "{}" nil) :content (message-part "{\"execution_state\":\"idle\"}" (:execution_state "idle")) :buffers nil) nil ((:status . #[257 "��!�
\0��!���!�" [#[257 "���!��\0� �" [jupyter-message-status-idle-p ((:header (message-part "{\"msg_id\":\"23d654f8-28e8e7f8c67d11b5d235d95b\",\"msg_type\":\"status\",\"username\":\"user\",\"session\":\"401554e2-99625c72c9b38ef672d71e97\",\"date\":\"2019-02-18T17:07:11.272461Z\",\"version\":\"5.3\"}" (:msg_id "23d654f8-28e8e7f8c67d11b5d235d95b" :msg_type :status :username "user" :session "401554e2-99625c72c9b38ef672d71e97" :date "2019-02-18T17:07:11.272461Z" :version "5.3")) :msg_id "23d654f8-28e8e7f8c67d11b5d235d95b" :msg_type :status :parent_header (message-part "{\"msg_id\":\"336a60fd-ffc7-4ca1-a6de-398c0d291540\",\"msg_type\":\"execute_request\",\"version\":\"5.3\",\"username\":\"user\",\"session\":\"c65d7238-78a3-4c80-8a98-a779f4a54324\",\"date\":\"2019-02-18T12:07:11.265661-05:00\"}" (:msg_id "336a60fd-ffc7-4ca1-a6de-398c0d291540" :msg_type :execute-request :version "5.3" :username "user" :session "c65d7238-78a3-4c80-8a98-a779f4a54324" :date "2019-02-18T12:07:11.265661-05:00")) :metadata (message-part "{}" nil) :content (message-part "{\"execution_state\":\"idle\"}" (:execution_state "idle")) :buffers nil))] 4 "

(fn M)"] nil functionp] 3 "

(fn MSG)"])))

jupyter-run-repl does work, however.

Location of kernel session for org mode

I have an org session evaluated, e.g.,
#+BEGIN_SRC jupy-python :session py :kernel py36 #+END_SRC

and I'd like to connect a jupyter REPL to it with jupyter-connect-repl, but the connection file is not stored in the standard place, e.g., on Linux, /run/user/1001/jupyter/<file-name>.json

Where is the session connection file stored from org mode? Or can I connect to the kernel in a different way?

no usable prompt/input area when restarting kernel

When restarting the kernel, sometimes I am unable to enter any text.

screen shot 2019-03-01 at 9 30 46 pm

I get errors like this:

Error running timer ‘jupyter-handle-message’: (error "Found end of previous cell")
jupyter-repl-cell-beginning-position: Found end of previous cell [2 times]
funcall-interactively: Text is read-only
Company: An error occurred in auto-begin
Company: backend company-capf error "Found end of previous cell" with args (prefix)
Mark set
jupyter-repl-cell-beginning-position: Found end of previous cell
helm-M-x: Found end of previous cell

error: Channel not started in ioloop subprocess (:shell)

Executing the jupyter-run-repl command will cause this error.

The backtrace log:

Debugger entered--Lisp error: (error "Channel not started in ioloop subprocess (:shell)")
  signal(error ("Channel not started in ioloop subprocess (:shell)"))
  error("Channel not started in ioloop subprocess (%s)" :shell)
  #f(compiled-function (client channel) "Verify that CLIENT's CHANNEL started.\nRaise an error if it did not start within\n`jupyter-default-timeout'." #<bytecode 0x4079f845>)(#<jupyter-repl-client jupyter-repl-client> :shell)
  apply(#f(compiled-function (client channel) "Verify that CLIENT's CHANNEL started.\nRaise an error if it did not start within\n`jupyter-default-timeout'." #<bytecode 0x4079f845>) (#<jupyter-repl-client jupyter-repl-client> :shell))
  #f(compiled-function (&rest args) #<bytecode 0x43fdc151>)(#<jupyter-repl-client jupyter-repl-client> :shell)
  apply(#f(compiled-function (&rest args) #<bytecode 0x43fdc151>) #<jupyter-repl-client jupyter-repl-client> :shell)
  jupyter-start-channel(#<jupyter-repl-client jupyter-repl-client> :shell)
  #f(compiled-function (arg1 &rest rest) "Start the pre-configured channels of CLIENT.\nBefore starting the channels, ensure that the channel subprocess\nresponsible for encoding/decoding messages and sending/receiving\nmessages to/from the kernel is running.\n\nCall `jupyter-start-channel' for every channel whose key has a\nnon-nil value passed to this function.\n\nIf the shell channel is started, send an initial\n`:kernel-info-request' to set the kernel-info slot of CLIENT if\nnecessary." #<bytecode 0x4079f90d>)(#<jupyter-repl-client jupyter-repl-client>)
  apply(#f(compiled-function (arg1 &rest rest) "Start the pre-configured channels of CLIENT.\nBefore starting the channels, ensure that the channel subprocess\nresponsible for encoding/decoding messages and sending/receiving\nmessages to/from the kernel is running.\n\nCall `jupyter-start-channel' for every channel whose key has a\nnon-nil value passed to this function.\n\nIf the shell channel is started, send an initial\n`:kernel-info-request' to set the kernel-info slot of CLIENT if\nnecessary." #<bytecode 0x4079f90d>) #<jupyter-repl-client jupyter-repl-client>)
  #f(compiled-function (&rest args) #<bytecode 0x404b14f1>)(#<jupyter-repl-client jupyter-repl-client>)
  apply(#f(compiled-function (&rest args) #<bytecode 0x404b14f1>) #<jupyter-repl-client jupyter-repl-client> nil)
  jupyter-start-channels(#<jupyter-repl-client jupyter-repl-client>)
  jupyter-start-new-kernel("python3" jupyter-repl-client)
  jupyter-run-repl("python3" nil t nil t)
  funcall-interactively(jupyter-run-repl "python3" nil t nil t)
  #<subr call-interactively>(jupyter-run-repl record nil)
  apply(#<subr call-interactively> jupyter-run-repl (record nil))
  call-interactively@ido-cr+-record-current-command(#<subr call-interactively> jupyter-run-repl record nil)
  apply(call-interactively@ido-cr+-record-current-command #<subr call-interactively> (jupyter-run-repl record nil))
  call-interactively(jupyter-run-repl record nil)
  command-execute(jupyter-run-repl record)
  execute-extended-command(nil "jupyter-run-repl")

Support displaying multiple returned images

How easy would it be to display multiple images returned by the kernel?
I could imagine that, for each image returned, a link to the image could be added just as it is being done with a single image.

Thank you for the amazing work you've done in this package @dzop.

Support javascript output

I'm trying to use hvega which outputs vega-lite plots. The output is a javascript block. However, when running the source block I get no output and a warning: Warning (emacs): No valid mimetype found (:application/javascript). This is when trying the barcode example in https://raw.githubusercontent.com/DougBurke/hvega/master/notebooks/VegaLiteGallery.ipynb
Obviously the interactivity isn't needed, but having it at least print out the javascript string would be beneficial on export. Best case scenario would be to have :file automatically export to .svg and .png.

MESSAGE: (:iopub :display-data (:data (:application/javascript requirejs({paths:{vg:’https://cdn.jsdelivr.net/npm/[email protected]/build/vega.min’,vl:’https://cdn.jsdelivr.net/npm/[email protected]/build/vega-lite.min’,vge:’https://cdn.jsdelivr.net/npm/[email protected]/build/vega-embed.min’},shim:{vge:{deps:[’vg.global’,’vl.global’]},vl:{deps:[’vg’]}}});define(’vg.global’,[’vg’],function(g){window.vega = g;});define(’vl.global’,[’vl’],function(g){window.vl = g;});var ndiv = document.createElement(’div’);ndiv.innerHTML = ’Awesome Vega-Lite visualization to appear here’;element[0].appendChild(ndiv);require([’vge’],function(vegaEmbed){vegaEmbed(ndiv,{"mark":"bar","data":{"values":[{"a":"A","b":28},{"a":"B","b":55},{"a":"C","b":43},{"a":"D","b":91},{"a":"E","b":81},{"a":"F","b":53},{"a":"G","b":19},{"a":"H","b":87},{"a":"I","b":52}]},"$schema":"https://vega.github.io/schema/vega-lite/v2.json","encoding":{"x":{"field":"a","type":"ordinal"},"y":{"field":"b","type":"quantitative"}},"description":"A simple bar chart with embedded data."}).then(function (result) { console.log(result); }).catch(function (error) { ndiv.innerHTML = ’There was an error: ’ + error; });});) :metadata nil))

ipdb and code evaluation

If you evaluate a region of code in the REPL while ipdb is running, emacs locks up. It seems there is no timeout.

can't run jupyter-run-repl

When I run M-x jupyter-run-repl, it can't find any kernels. It just says No kernel found for prefix (nil)

Make widgets fails if cask is not installed

Small issue, but I noticed that make widgets will fail if Cask is not installed, even though cask is not necessary for that particular target. make -C js will work fine, of course.

Thanks for sharing the project, by the way. It's really awesome.

Font used and table alignment for HTML output in the REPL

Not sure whether this is specific to my configuration, and I'm having a hard time finding a consistent way to reproduce this, but sometimes when I print a pandas DataFrame from the REPL, the font used to display the text changes. I'm attaching a screenshot as an example of what I mean, and I doubt this is super helpful, but from what I can tell it's more likely to occur the more rows I try to view.

screen shot 2019-03-05 at 11 04 58 am

Error if /run/user/1000/jupyter doesn't exist yet

Installing this on another computer, I ran into a problem after invoking jupyter-run-repl where it was clear that emacs-jupyter was trying to create a file in /run/user/1000/jupyter but such a directory didn't yet exist as I hadn't previously used jupyter on this system. Problem was fixed by simply running jupyter console once.

text/html displayed too small

Since jupyter--debug doesn't seem to log incoming requests (can't look at the metadata associated with svg myself), I haven't been able to get very far in debugging this myself. You're a julia user, so I'll give repro steps in terms of julia code (and an image to let you see what I'm talking about).

using Pkg; Pkg.add.(("Gadfly", "RDatasets"));
using Gadfly, RDatasets;
df = dataset("datasets", "iris")
plot(df, x=:SepalLength, y=:SepalWidth)

jupyter-emacs-small-svg

Colour in Results block?

Currently, the code shown in the output block is black and white whereas an associated repl session has the proper colours. Is there a way around this?

Here's an example:

Screen Shot 2019-03-11 at 11 18 36 AM

Kernel did not read connection file within timeout

While I have this working on my Arch computer, on an Ubuntu computer I run into a new issue. jupyter-run-repl also does not work (Kernel did not read connection file within timeout).

Evaluate this jupyter-python code block on your system? (y or n) y                                                                                                                                                                              
executing Jupyter-Python code block...                                                                                                                                                                                                          
START: nil                                                                                                                                                                                                                                      
START-CHANNEL: (:shell)                                                                                                                                                                                                                         
START-CHANNEL: (:iopub)                                                                                                                                                                                                                         
START-CHANNEL: (:stdin)                                                                                                                                                                                                                         
Kernel did not read connection file within timeout

I am able to run jupyter, it's in my path, and I can access notebooks from the browser.

Emacs freezing when prompt too large

As mentioned in #38, the following with the IJulia kernel in a jupyter REPL consistently freezes emacs:

]activate ~/repos/ChemicalEngineeringToolbox.jl
]

This is because it tries to cram the current environment, ChemicalEngineeringToolbox, into the margin. In the non-jupyter julia REPL, this works fine since there is no "margin" to overflow. Each prompt is unconstrained and can be whatever length it needs to be.

(v1.1) pkg> activate ~/repos/ChemicalEngineeringToolbox.jl/

(ChemicalEngineeringToolbox) pkg> status
Project ChemicalEngineeringToolbox v0.1.0
    Status `~/repos/ChemicalEngineeringToolbox.jl/Project.toml`
  [a98d9a8b] Interpolations v0.11.0
  [90137ffa] StaticArrays v0.10.2
  [1986cc42] Unitful v0.13.0
  [7dc9378f] UnitfulUS v0.1.0
  [8bb1440f] DelimitedFiles 

julia> println("test")
test

My suggestion would be to either truncate the environment name or omit the information altogether. It isn't that helpful anyway since you could easily have multiple environments named "ChemicalEngineeringToolbox". Another option would be to display the environment name as a sort of header over each cell.

Traceback below:

Debugger entered--Lisp error: (wrong-type-argument wholenump -22)
  make-string(-22 32)
  (concat (make-string (- jupyter-repl-prompt-margin-width (length str)) 32) str)
  (propertize (concat (make-string (- jupyter-repl-prompt-margin-width (length str)) 32) str) 'fontified t 'font-lock-face face)
  (list '(margin left-margin) (propertize (concat (make-string (- jupyter-repl-prompt-margin-width (length str)) 32) str) 'fontified t 'font-lock-face face))
  jupyter-repl--prompt-display-value("(ChemicalEngineeringToolbox) pkg> " ((:foreground "magenta3") jupyter-repl-input-prompt))
  (propertize " " 'display (jupyter-repl--prompt-display-value str (or face 'jupyter-repl-input-prompt)))
  (overlay-put ov 'after-string (propertize " " 'display (jupyter-repl--prompt-display-value str (or face 'jupyter-repl-input-prompt))))
  (progn (overlay-put ov 'after-string (propertize " " 'display (jupyter-repl--prompt-display-value str (or face 'jupyter-repl-input-prompt)))))
  (if ov (progn (overlay-put ov 'after-string (propertize " " 'display (jupyter-repl--prompt-display-value str (or face 'jupyter-repl-input-prompt))))))
  (let ((ov (car (overlays-at (jupyter-repl-cell-beginning-position))))) (if ov (progn (overlay-put ov 'after-string (propertize " " 'display (jupyter-repl--prompt-display-value str (or face 'jupyter-repl-input-prompt)))))))
  jupyter-repl-cell-update-prompt("(ChemicalEngineeringToolbox) pkg> " ((:foreground "magenta3") jupyter-repl-input-prompt))
  jupyter-julia-update-prompt("(ChemicalEngineeringToolbox) pkg> " "magenta3")
  (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))
  (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5))))
  (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))
  (cond ((eql temp '93) (if (and (boundp 'blink-paren-function) blink-paren-function) (progn (setq last-command-event 91))) (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))) ((eql temp '59) (jupyter-julia-update-prompt "shell> " (aref ansi-color-names-vector 1))) ((eql temp '63) (jupyter-julia-update-prompt "help?> " (aref ansi-color-names-vector 3))))
  (let* ((temp (char-after))) (cond ((eql temp '93) (if (and (boundp 'blink-paren-function) blink-paren-function) (progn (setq last-command-event 91))) (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))) ((eql temp '59) (jupyter-julia-update-prompt "shell> " (aref ansi-color-names-vector 1))) ((eql temp '63) (jupyter-julia-update-prompt "help?> " (aref ansi-color-names-vector 3)))))
  (save-excursion (goto-char beg) (let* ((temp (char-after))) (cond ((eql temp '93) (if (and (boundp 'blink-paren-function) blink-paren-function) (progn (setq last-command-event 91))) (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))) ((eql temp '59) (jupyter-julia-update-prompt "shell> " (aref ansi-color-names-vector 1))) ((eql temp '63) (jupyter-julia-update-prompt "help?> " (aref ansi-color-names-vector 3))))))
  (progn (save-excursion (goto-char beg) (let* ((temp (char-after))) (cond ((eql temp '93) (if (and (boundp 'blink-paren-function) blink-paren-function) (progn (setq last-command-event 91))) (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))) ((eql temp '59) (jupyter-julia-update-prompt "shell> " (aref ansi-color-names-vector 1))) ((eql temp '63) (jupyter-julia-update-prompt "help?> " (aref ansi-color-names-vector 3)))))))
  (if (= beg (jupyter-repl-cell-code-beginning-position)) (progn (save-excursion (goto-char beg) (let* ((temp (char-after))) (cond ((eql temp '93) (if (and (boundp 'blink-paren-function) blink-paren-function) (progn (setq last-command-event 91))) (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))) ((eql temp '59) (jupyter-julia-update-prompt "shell> " (aref ansi-color-names-vector 1))) ((eql temp '63) (jupyter-julia-update-prompt "help?> " (aref ansi-color-names-vector 3))))))))
  (progn (if (= beg (jupyter-repl-cell-code-beginning-position)) (progn (save-excursion (goto-char beg) (let* ((temp (char-after))) (cond ((eql temp '93) (if (and (boundp 'blink-paren-function) blink-paren-function) (progn (setq last-command-event 91))) (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))) ((eql temp '59) (jupyter-julia-update-prompt "shell> " (aref ansi-color-names-vector 1))) ((eql temp '63) (jupyter-julia-update-prompt "help?> " (aref ansi-color-names-vector 3)))))))) (funcall cl--cnm))
  (progn (progn (if (= beg (jupyter-repl-cell-code-beginning-position)) (progn (save-excursion (goto-char beg) (let* ((temp (char-after))) (cond ((eql temp '93) (if (and (boundp 'blink-paren-function) blink-paren-function) (progn (setq last-command-event 91))) (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))) ((eql temp '59) (jupyter-julia-update-prompt "shell> " (aref ansi-color-names-vector 1))) ((eql temp '63) (jupyter-julia-update-prompt "help?> " (aref ansi-color-names-vector 3)))))))) (funcall cl--cnm)))
  (closure (t) (cl--cnm _type beg _end) "Change the REPL prompt when a REPL mode is entered." (progn (progn (if (= beg (jupyter-repl-cell-code-beginning-position)) (progn (save-excursion (goto-char beg) (let* ((temp (char-after))) (cond ((eql temp '93) (if (and (boundp 'blink-paren-function) blink-paren-function) (progn (setq last-command-event 91))) (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))) ((eql temp '59) (jupyter-julia-update-prompt "shell> " (aref ansi-color-names-vector 1))) ((eql temp '63) (jupyter-julia-update-prompt "help?> " (aref ansi-color-names-vector 3)))))))) (funcall cl--cnm))))(#f(compiled-function (&rest cnm-args) #<bytecode 0x15ab1f1>) insert 124 125)
  apply((closure (t) (cl--cnm _type beg _end) "Change the REPL prompt when a REPL mode is entered." (progn (progn (if (= beg (jupyter-repl-cell-code-beginning-position)) (progn (save-excursion (goto-char beg) (let* ((temp (char-after))) (cond ((eql temp '93) (if (and (boundp 'blink-paren-function) blink-paren-function) (progn (setq last-command-event 91))) (let* ((jupyter-default-timeout jupyter-long-timeout) (pkg-prompt (jupyter-eval "import Pkg; Pkg.REPLMode.promptf()"))) (if pkg-prompt (progn (jupyter-julia-update-prompt (substring pkg-prompt 1 (1- (length pkg-prompt))) (aref ansi-color-names-vector 5)))))) ((eql temp '59) (jupyter-julia-update-prompt "shell> " (aref ansi-color-names-vector 1))) ((eql temp '63) (jupyter-julia-update-prompt "help?> " (aref ansi-color-names-vector 3)))))))) (funcall cl--cnm)))) #f(compiled-function (&rest cnm-args) #<bytecode 0x15ab1f1>) (insert 124 125))
  #f(compiled-function (&rest args) #<bytecode 0x3548a2d>)(insert 124 125)
  apply(#f(compiled-function (&rest args) #<bytecode 0x3548a2d>) insert (124 125))
  #f(compiled-function (arg &rest args) #<bytecode 0x35488e1>)(insert 124 125)
  apply(#f(compiled-function (arg &rest args) #<bytecode 0x35488e1>) (insert 124 125))
  jupyter-repl-after-change(insert 124 125)
  (cond ((= len 0) (jupyter-repl-after-change 'insert beg end)) ((and (= beg end) (not (= 0 len))) (jupyter-repl-after-change 'delete beg len)) ((= (- end beg) len) (if (and (= len 1) (get-text-property beg 'rear-nonsticky) (= end (jupyter-repl-cell-end-position))) (progn (remove-text-properties beg end '(rear-nonsticky))))))
  (progn (cond ((= len 0) (jupyter-repl-after-change 'insert beg end)) ((and (= beg end) (not (= 0 len))) (jupyter-repl-after-change 'delete beg len)) ((= (- end beg) len) (if (and (= len 1) (get-text-property beg 'rear-nonsticky) (= end (jupyter-repl-cell-end-position))) (progn (remove-text-properties beg end '(rear-nonsticky)))))))
  (if (save-excursion (goto-char beg) (jupyter-repl-cell-line-p)) (progn (cond ((= len 0) (jupyter-repl-after-change 'insert beg end)) ((and (= beg end) (not (= 0 len))) (jupyter-repl-after-change 'delete beg len)) ((= (- end beg) len) (if (and (= len 1) (get-text-property beg 'rear-nonsticky) (= end (jupyter-repl-cell-end-position))) (progn (remove-text-properties beg end '(rear-nonsticky))))))))
  (condition-case err (if (save-excursion (goto-char beg) (jupyter-repl-cell-line-p)) (progn (cond ((= len 0) (jupyter-repl-after-change 'insert beg end)) ((and (= beg end) (not (= 0 len))) (jupyter-repl-after-change 'delete beg len)) ((= (- end beg) len) (if (and (= len 1) (get-text-property beg 'rear-nonsticky) (= end (jupyter-repl-cell-end-position))) (progn (remove-text-properties beg end '(rear-nonsticky)))))))) ((debug error) (message "Jupyter error after buffer change: %S" err) nil))
  (progn (condition-case err (if (save-excursion (goto-char beg) (jupyter-repl-cell-line-p)) (progn (cond ((= len 0) (jupyter-repl-after-change 'insert beg end)) ((and (= beg end) (not (= 0 len))) (jupyter-repl-after-change 'delete beg len)) ((= (- end beg) len) (if (and (= len 1) (get-text-property beg 'rear-nonsticky) (= end (jupyter-repl-cell-end-position))) (progn (remove-text-properties beg end '(rear-nonsticky)))))))) ((debug error) (message "Jupyter error after buffer change: %S" err) nil)))
  (if (eq major-mode 'jupyter-repl-mode) (progn (condition-case err (if (save-excursion (goto-char beg) (jupyter-repl-cell-line-p)) (progn (cond ((= len 0) (jupyter-repl-after-change 'insert beg end)) ((and (= beg end) (not (= 0 len))) (jupyter-repl-after-change 'delete beg len)) ((= (- end beg) len) (if (and (= len 1) (get-text-property beg 'rear-nonsticky) (= end (jupyter-repl-cell-end-position))) (progn (remove-text-properties beg end '(rear-nonsticky)))))))) ((debug error) (message "Jupyter error after buffer change: %S" err) nil))))
  jupyter-repl-do-after-change(124 125 0)
  self-insert-command(1)
  funcall-interactively(self-insert-command 1)
  call-interactively(self-insert-command nil nil)
  command-execute(self-insert-command)

"Modules are not supported" - package load error

Hello,

thanks a lot for this new projects, I can't wait to try it !

Unfortunately I ran quickly into a wall... I get this error message when running (require 'jupyter) :
Modlues are not supported

I didn't enabled widgets at emacs compilation, maybe that's the reason ?

Specifying file doesn't seem to work correctly?

Running the following produces a blank file. Have I misunderstood the functionality of file? If so what is the correct way to do this?

#+BEGIN_SRC jupyter-python :session py :file ./test.png
import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
#+END_SRC

Text results don't appear with :async yes

When async is disabled, all results appear underneath. When async is enabled, images appear, but text results don't. In the first code block, text is produced, but no output appears until async is disabled. The image appears correctly despite async in the third block.

#+BEGIN_SRC jupyter-python :session xx :kernel python3 :async yes :results drawer
x = 'foo'
y = 'bar'
print(x + ' ' + y)
#+END_SRC

#+RESULTS:
:results:
:end:


#+BEGIN_SRC jupyter-python :session xx :kernel python3 :async no :results drawer
x = 'foo'
y = 'bar'
print(x + ' ' + y)
#+END_SRC

#+RESULTS:
: foo bar
:


#+BEGIN_SRC jupyter-python :async yes
import time

import numpy as np
import matplotlib.pyplot as plt


time.sleep(3)
plt.hist(np.random.randn(20000), bins=200)
#+END_SRC

#+RESULTS:
[[file:./.ob-jupyter/cfc8c7633939dad5fe6075720e6bba41d2db9402.png]]

Ubuntu 18.04
Emacs 26.1
Python 3.6.5
emacs-jupyter "v0.7.2-15-gea5ae74"

Consistency of src-block header argument combinations

In particular, consistency with how results are inserted depending on :async
but also consistency with the meaning of the :results header argument in
emacs-jupyter and for regular org-mode source blocks.

Currently there are differences in how the results of a src-block are formatted
when :async yes is specified vs :async no in the presence of other header
arguments. These differences should be removed so that the results are rendered
consistently in both cases.

The differences originate in the use of org-babel-insert-result (which
handles header arguments) for insertion in the :async no case and an
insertion method specific to emacs-jupyter(which ignores most header
arguments) in the :async yes case. The reason for the custom insertion method
in the :async yes case is to support appending results dynamically to the buffer
as they come in and this needs to take into account:

  • Value results (images, latex, html, markdown)
  • Output from stdout
    • Appending to a fixed width element (contiguous lines that start with :)
    • Appending to the end of an example block
    • Converting a fixed width element to an example block (when the number of
      lines exceeds org-babel-min-lines-for-block-output)
  • Wrapping output and value results in a drawer when needed

The simplest solution would be to avoid going through org-babel-insert-result
in the :async no case and use the same insertion method for both cases.
Then, the only difference between the two would be that :async no blocks
Emacs until the src-block is finished. I used org-babel-insert-result for the
:async no case because I eventually wanted to go through org-mode as
much as possible so that all of the header arguments that function handles
would be supported, even in the :async yes case. But it doesn't seem like
this is possible if we are going to support dynamic result insertion.
Is this the only solution?

If we go the route of using the emacs-jupyter specific insertion method for
both :async yes and :async no, it would make sense to support the majority
of the header arguments of regular org-mode blocks. Below is a list of header
arguments that are currently considered in emacs-jupyter:

  • :results raw: Only considered when LaTeX results are returned. Normally
    LaTeX results are wrapped in an export block, when this
    argument is provided, the LaTeX is inserted directly into the
    buffer.
  • :results scalar: Normally when text/plain results are returned the result
    is converted into an Org mode table it it look like one. When this
    argument is provided, the table conversion is suppressed.
  • :file : Normally when image results are returned, the image data is
    written to a file with a file name based on
    org-babel-jupyter-resource-directory and the image data,
    then a link to that file is inserted into the buffer. If this
    argument is provided, the file name used is <path> instead.

I think it would make sense to also support :result list and :results link
and possibly the :post header argument. But are there others that would make
sense?

Some more questions:

  • I think the :file argument has changed in Org 9.2.1 to mean write the
    results to :file. To get the old meaning, in addition to :file, you have
    to specify :results link. This doesn't matter so much since we have a
    custom result insertion method so we can slightly change the meaning of the
    header argument as has already been done. But for the sake of consistency,
    should we keep the semantics of :file the same as org-mode?

  • The above point raises the question: When it comes to header arguments,
    should the general strategy be to always defer to the way that org-mode
    handles them? I don't see why we wouldn't.

  • Currently output is intermixed with value results by default and the result
    of a code block is only suppressed when :result output is specified.
    Jupyter has the notion of display-data messages which can be considered as
    additional value results that come before the final result of the source
    block. Even in the case of :results output, these additional results are
    not suppressed. Would it make sense to stick with the current behavior and
    have :results value mean both output and value results? I did this because
    a Jupyter notebook would insert both stdout and value results by default.

    Would it make sense then for :results output to mean suppress all value
    results, even those from display-data messages and just have the stdout as
    the result? I think so.

  • How would :results list work? Should we just create a list based on stdout
    or the value of the result? Again, Jupyter has the notion of display-data
    messages which act as additional value results.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.