Skip to content

modifications to ob-python for a more jupyter notebook like workflow

License

Notifications You must be signed in to change notification settings

ElleNajt/ob-python-extras

Repository files navigation

Readme

https://github.com/ElleNajt/ob-python-extras/actions/workflows/org_babel_tests.yml/badge.svg

This package adds additional features to ob-python that I found lacking when trying to use it as a replacement for jupyter notebooks. I’ve been using it instead of jupyter notebooks for about a year now, slowly accumulating fixes to things that I miss from jupyter, or things that seem cool that jupyter doesn’t support but emacs makes easy.

Features:

Enhanced cell output

  • Mix image and text output in the same cell, by mocking matplotlib to save images and return references.
  • Print pandas dataframes as org tables always, by overwriting the __repr__ method. Uses tabulate if available.
  • Press C-c C-c over an image for a full-size view

    For example:

import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({"x": [1, 2, 3, 4, 5,6,7,], "y": [10, 11, 12, 13, 14,15,16]})
print(df)
df.plot(x="x", y="y", kind="line")
plt.show()
print("...tada!")
idxxy
0110
1211
2312
3413
4514
5615
6716

plots/Readme/plot_20241208_122132_1950748.png …tada!

Cell behavior features

  • Cell timers (configurable via :timer-show {yes/no})
  • Cell interruption with C-c C-k
  • Capturing tracebacks in the results (with the option to use rich tracebacks via :errors “rich no-locals frames 3 extra 5”)
  • Alerts on long running cells, using libnotify for system alerts and pop ups inside of doom

Gptel integrations:

  • Functions to send a block and the results (e.g. the traceback) to a gptel buffer, get a patch, view the diff, and optionally apply it.
  • Ability to trigger this automatically when a cell fails.

Pandoc scripts:

Configured scripts for converting org files in a directory to ipynb files, or ipynb files to org files. These rely on pandoc.

These commands are intended to be called from dired buffers.

run-ipynb-to-org-conversion-script
Convert all .ipynb files in current directory to .org (removes various artifacts that pandoc creates also, cleaning can be disabled by removing the -c flag)
run-ipynb-to-org-conversion-script-recursively
Convert all .ipynb files in current directory and subdirectories to .org
run-org-to-ipynb-conversion-script
Convert all .org files in current directory to .ipynb

Also includes a git precommit hook that’s useful for automatically converting org to ipynb.

Better LSP integration

  • Special mode inherits the same python interpreter as specified for the cell, giving access to documentation and completion. (Requires eglot.) Activate with
    (ob-python-extras/add-org-edit-special-advice)
        

Probably this is better:

https://github.com/karthink/org-src-context

Dependencies

  • Python packages: Rich, tabulate (optional, but recommended), matplotlib
  • System: Libnotify (for alerts), Pandoc (For conversions)
  • Emacs: Gptel (For the gptel extensions), Doom (for now required for alerts), Eglot (for lsp integrations), Dired (For the conversion scripts)

Installation

With straight.el

(package! ob-python-extras
  :recipe (:host github
           :repo "ElleNajt/ob-python-extras"
           :files ("*.el" "python" "bashscripts")))
(after! ob-python-extras
  (ob-python-extras/map-suggested-keyindings))

Setup:

Keybindings:

If you want my keybindings, run:

(ob-python-extras/map-suggested-keyindings)

Setting up gptel integrations

(after! ob-python-extras
(ob-python-extras-load-gptel-integration))

This requires gptel-default-mode to be set to org-mode to work, since it expects an org block in the response.

(gptel-default-mode 'org-mode)

The conversation happens in the CELL ERRORS buffer.

KeyCommandDescription
SPC o c ssend-block-to-gptelSend block to GPTel, and ask for a fix.
SPC o c ppatch-gptel-blocksApply the fix
SPC o c fgptel-fix-blockDo the two things at once

If you set:

(setq ob-python-extras/auto-send-on-traceback t)

Then blocks will be sent automatically when a traceback is detected in the response. This can rack up a bill with API calls!

Setting up alert integrations

(after! ob-python-extras
  (ob-python-extras-load-alerts))

Matplotlib image transparency

Matplotlib is configured to save and display images without transparency by default. The default can be changed with (setq ob-python-extras/transparent-images t). This default, in turn, can be overridden at the org-src-block level with :transparent nil or :transparent t.

Examples:

See this org file for examples of the different functionality and configurations.

Other notes:

In my personal config I use the following keybindings as well, based on a vendored version guilt-dolphin’s org-evil with keybindings stripped. These make it easier to manipulate source blocks:

(org-evil--define-key 'motion 'org-evil-motion-mode
                      "[[" 'org-evil-motion-backward-block-begin
                      "]]" 'org-evil-motion-forward-block-begin)

(add-hook! 'org-mode-hook 'org-evil-mode)

(undefine-key! evil-motion-state-map "[ s" "] s")

(map! (:mode org-mode
       :n "] r" #'org-babel-goto-src-block-results
       :n "[ s" 'org-evil-block-beginning-of-block
       :n "] s" 'org-evil-block-end-of-block))

(org-evil--define-key 'motion 'org-evil-block-mode
                      "[ s" 'org-evil-block-beginning-of-block
                      "] s" 'org-evil-block-end-of-block)

(dolist (mode '(operator visual))
  (org-evil--define-key mode 'org-evil-block-mode
                        "ib" 'org-evil-block-inner-block
                        "ab" 'org-evil-block-a-block))

Credit:

  • Aspen for teaching me a bunch about emacs and suggesting mocking out matplotlib
  • Claude for writing most of the code ^^

Related packages:

Emacs jupyter

https://github.com/emacs-jupyter/jupyter This package provides some overlapping functionality, and as far as I understand it does it by connecting to jupyter kernels and providing a front end in org mode for the kernel. I have not used this myself yet. It may ultimately make more sense for this project to be refactored to extend emacs-jupyter instead of ob-python, e.g. by adding the gptel integrations or other features that emacs-jupyter lacks.

Scimax also uses emacs jupyter

ob-ipython

EIN

https://github.com/millejoh/emacs-ipython-notebook Similar to Emacs-Jupyter. No longer maintained.

About

modifications to ob-python for a more jupyter notebook like workflow

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published