from fastcore.test import *
from basedpl import Array, bpl
from IPython.utils.capture import capture_output
import numpy as npNotebook magics
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.
Rendering output
AplOut preserves BPL spacing. Its HTML representation escapes the output before putting it in a <pre> element.
out = AplOut('1 < 2')
assert '<' in out._repr_html_()
out1 < 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×100 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')
z0 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)
value6ₓ
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 provisionalcompletershell = 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.