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})
  • Last run time (configurable via :last-executed {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
  • Open the session in another buffer (Keybindings bind it to SPC o s)
  • Variable inspector (Keybindings bind it to SPC o v)
  • Limit output with :max-lines (POSITIVE-INTEGER) – useful because very long output can crash org babel, so it’s useful to set this to :max-lines 1000 or similar and just inspect the shell (easily accessible with SPC o s).

Bare bones LSP features

  • ob-python-extras/python-help-clean

This calls the python REPL’s help on the current symbol (obtained from (python-info-current-symbol)). The defaults bind it to K (lookup/documentation)

images/org-download/Overview:/_20250225_190929screenshot.png

  • ob-python-extras/goto-definition

    Similarly, this uses pythons inspect to find the path for the object at point, then travels there. Default bound to gd.

  • Completion at point

    Gets completion at point via the python process corresponding to a cell, and feeds them into capf.

    images/org-download/Overview:/_20250225_190659screenshot.png

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.

Variable Renamer Utility

Tooling to safely rename variables in an org file across all python blocks that have valid python syntax. (python blocks with invalid syntax will be skipped.)

To use, create a renamer.json in the same folder as your .org file, mark both with dired, and then run ob-python-extras/dired-rename-python-vars.

By default this runs a python via “nix-shell –pure -p black –run ‘python …’” , set the variable alternative-python-binary to a different python binary if not using nix.

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.

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")))

Setup:

Keybindings:

If you want my keybindings, run:

(ob-python-extras-load-keybindings)

No keybindings are set otherwise, to prevent conflicts with users configs.

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.

Autoformatter

Auto formats source blocks using black. Configurable with

(setq ob-python-extras/auto-format 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.

On the other hand, getting emacs-jupyter set up seems difficult to many people, including me, so having a simpler package that makes python babel cells more powerful is also useful.

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