Notebook magics

BPL magics and BPL output display for Jupyter and IPython

BPL adds %bpl and %%bpl magics to IPython. Both evaluate in basedpl.bpl, the same workspace as Python calls through bpl.

The line magic returns a native array or function. The cell magic displays what the BPL prompt would show, including implicit expression results.

from fastcore.test import *
from basedpl import Array, bpl
from IPython.utils.capture import capture_output
import numpy as np

Rendering output

AplOut preserves BPL spacing. Its HTML representation escapes the output before putting it in a <pre> element.

out = AplOut('1 < 2')
assert '&lt;' in out._repr_html_()
out
1 < 2

The magics

The language bar and the font stylesheet, fonts.css, are loaded once for each magic instance.

Cell output comes from bpl(code, 'repl'), which includes implicit expression results. Line output comes from bpl(code, 'explicit'), which captures explicit output and returns native values. A trailing ; suppresses all cell display without skipping execution. Output produced before an error is displayed before the error is raised.

Tab completes user and system names in BPL input. Completion reads the workspace without evaluating anything.

The cell magic displays each expression. Assignments remain silent.

%%bpl
m←2 3⍴⍳6
m×10
 0 10 20
30 40 50

The line magic returns a native basedpl.Array. Use .np or .py for conversion. BPL parses comments itself. A ⍝ inside a quoted string doesn’t start a comment.

z = %bpl m ⍝ a matrix
test_is(type(z), Array)
np.testing.assert_array_equal(z.np, [[0, 1, 2], [3, 4, 5]])
test_eq(magic.bpl('"a⍝b" ⍝ comment').py, 'a⍝b')
z
0 1 2
3 4 5

Python values bound through bpl are visible to the magics. Python integers stay exact.

bpl(x=np.arange(1, 4))
value = %bpl +/x
test_eq(value.py, 6)
test_is(type(value.py), int)
value
6ₓ

BPL’s display commands also work in a cell.

%%bpl
]Display [[1 2] "ab"]
┌→───────────┐
│ ┌→──┐ ┌→─┐ │
│ │1 2│ │ab│ │
│ └~──┘ └──┘ │
└∊───────────┘

A suppressed cell still updates the workspace.

%%bpl
quiet←7;

SVG elements and custom MIME renderers display in cell magics and as Python values.

%%bpl
circle←•element "circle"
•svg ["cx":50 "cy":50 "r":30 "fill":"orange"] circle ""

Names and help

Use ]help name for help and ]help name -source for source, in either magic. Leading definition comments supply help. Inspecting a function doesn’t call it.

%%bpl
double←{⍝ Double the argument
⎕←"called" ⋄ ⍵×2}
with capture_output() as cap: magic.bpl(']help double')
assert 'Double the argument' in cap.outputs[0].data['text/markdown']
with capture_output() as cap: magic.bpl('', ']help double -source')
assert '⎕←"called"' in cap.outputs[0].data['text/markdown']
test_eq(len(cap.outputs), 1)

Completion follows the magic’s workspace, including names defined after registration. Quoted text and comments stay literal.

from IPython.core.completer import provisionalcompleter
shell = get_ipython()
for text, expected in [('%bpl dou', 'double'), ('v = %bpl dou', 'double'), ('%%bpl\n1+•sr', '•src'), ("%%bpl\n''' dou", 'double')]:
    with provisionalcompleter(): matches = list(shell.Completer.completions(text, len(text)))
    assert expected in [m.text for m in matches]
for text in ['%%bpl\n"dou', '%%bpl\n⍝ dou', 'ordinary_python']:
    with provisionalcompleter(): matches = list(shell.Completer.completions(text, len(text)))
    assert not any(m.type == 'BPL name' for m in matches)

Errors and workspace state

Errors retain source locations and leave completed assignments in the workspace. Incomplete input raises a syntax error and leaves the workspace unchanged.

with capture_output() as cap: test_fail(lambda: magic.bpl('', '⎕←42 ⋄ 1÷"a"'), contains='DOMAIN ERROR')
assert '42' in cap.outputs[0].data['text/html']
test_fail(lambda: magic.bpl('', '{⍵+1'), contains='SYNTAX ERROR')
test_eq(magic.bpl('quiet').py, 9)

Set bpl.timeout to a per-evaluation deadline in seconds. Ctrl-C interrupts the evaluation. Output captured before cancellation is displayed. The workspace keeps its names after cancellation. Native-library calls and individual BigInt operations can delay cancellation.

Installation

%load_ext basedpl.notebooks registers the magics in the current kernel. bpl-install-magic adds the extension to the default IPython profile. Registration does not start a BPL worker.

Symbol input

The magics load BPL’s browser input method for typing glyphs. Using BPL notebooks explains the input method.