Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

ggblab

GeoGebra applets in Jupyter notebooks, driven from Python and Julia kernels.

This is version 2 (2.0.0rc2, a release candidate). It is a rewrite, not an upgrade of 1.x: see Relation to version 1.

What it is

  • The applet is mounted by a trusted HTML output of a notebook cell. There is no JupyterLab extension to build or install.
  • The kernel talks to the applet through a mailbox on its own Jupyter server (ggblab.host.relay, a server extension). The kernel is an HTTP client of that server. No comm, no comm target, no ipywidgets.
  • The same mailbox and the same JavaScript serve every kernel language. Python and Julia hosts are included.
  • The interface is a closed set of ten verbs over the GeoGebra Apps API: four writes (eval, new, delete, xml_in), three reads (xml_out, value, kind), one subscription (listen) and two projections (png, svg).
  • Constructions written as text are parsed by a closed-world parser: 28 GeoGebra commands, labels referenced as :label. An unknown command is an error, not a guess.

Install

Python 3.11 or later.

pip install ggblab==2.0.0rc2            # the core: applet host, server extension, parser
pip install "ggblab[extra]==2.0.0rc2"   # plus ggblab_extra: construction I/O, geometry IR, SymPy objects
pip install "ggblab[examples]==2.0.0rc2" # plus what the notebooks in examples/ import (matplotlib, networkx, numpy)

Without a version, pip install ggblab installs 1.8.1 while 2.0.0 is a release candidate.

The server extension is enabled by the installation. Check it, then restart the Jupyter server:

jupyter server extension list        # expect: ggblab.host.relay enabled, OK

Quick start

Python

from ggblab import GeoGebra

g = GeoGebra(appName="suite", showAlgebraInput=True)
g                                   # displaying g mounts the applet in this cell's output
g.command("O = (0, 0)", "c1 = Circle(O, 1)", "A = (1, 0)", "c2 = Circle(A, 1)",
          "l1 = {Intersect(c1, c2)}", "a = Length(l1)")     # one reply entry per command
g.value("a")                        # 2
g.xml()                             # the construction as GeoGebra XML
g.events()                          # what happened in the applet since the last call

A cell magic takes the construction as text:

%load_ext ggblab.ipymagic
%%ggb g
A = (2, 1)
B = (-1, 2)
C = (0, -1)
Polygon(:A, :B, :C)
Circle(:A, 1)

Julia

The Julia host is two files inside the installed Python package. It needs the Julia packages JSON and IJulia; the string macro also needs PythonCall.

host = strip(read(`python -c "import ggblab, pathlib; print(pathlib.Path(ggblab.__file__).parent / 'julia' / 'host')"`, String))
include(joinpath(host, "html_host.jl")); using .GGBLabHost

g = GeoGebra(appName="suite", showAlgebraInput=true)
g
command(g, "O = (0, 0)", "c1 = Circle(O, 1)", "A = (1, 0)", "c2 = Circle(A, 1)", "l1 = {Intersect(c1, c2)}", "a = Length(l1)")
value(g, "a")
include(joinpath(host, "ggb_macro.jl")); using .GGBLabMacro
ggb"""
A = (0, 0)
c = Circle(:A, 1)
"""g

The notebooks in examples/ show more. eg1 and eg2 need no server and no applet.

Documentation: https://ggblab.readthedocs.io/ (choose the version v2.0.0rc2; latest and stable are version 1).

notebook what it shows
eg1, eg2 reading a .ggb file; the construction XML as a Python dict
eg3 the verbs, one by one
eg4 errors
eg5 the construction as a data frame
eg6 the parser
eg7 plotting
eg8, eg10 sliders: the kernel reacts to changes made in the applet
eg9 listeners and events
eg11 a longer construction
julia_host, julia_macro the Julia host and the string macro

Where it runs

Python kernel Julia kernel
JupyterLab yes yes
JupyterHub on Kubernetes yes (checked 2026-09-29) yes (checked 2026-09-29)
VS Code notebooks not yet not yet

Version 1 has an experimental VS Code extension. Version 2 does not support VS Code notebooks yet.

Known limitations

  • Trusted output. The applet is mounted by a script in the cell output. The notebook has to be trusted.
  • One machine. The kernel and the Jupyter server are assumed to run on the same machine or in the same container.
  • A call needs a holder. A box nobody polls answers NoHolderError (a TimeoutError) within holder_grace s instead of waiting out timeout; a request the kernel gave up on is withdrawn and never runs later. g.boxes() shows who holds what.
  • Reply of command. Each entry is one of three things: the labels GeoGebra returned, None when GeoGebra refused the command (see g.errors()), or {"error": …} when the Apps API threw for that command.
  • Commands outside the 28. The parser rejects them. Examples met in course material and not yet supported: IntersectPath, Element, SetCoords. Send such commands with g.command(...).
  • An upper-case label followed by ( is read as a command, for example L1(1). Name the list in lower case.
  • No $ interpolation in the %%ggb cell and in the ggb"…" string.
  • Not among the ten verbs. Showing or hiding a layer (setLayerVisible) and reading the applet state as a file (getBase64). Visibility of one object can be changed by editing the XML (see examples/eg3).
  • The layout of a file is not applied. A GeoGebra document carries, in its <gui> element, the layout it was saved with (which views are open, the input bar). g.set_xml(xml) leaves that element out, so the applet keeps its own layout; g.set_xml(xml, gui=True) sends the document as it is. A file saved with the algebra view closed then closes the side panel, and sending XML again does not reopen it.
  • .ggb files are read, not written. A .ggb file depends on the order of its XML elements and carries the state of the user interface besides the construction. Version 2 works on the construction only.
  • Julia module names (GGBLabHost, GGBLabMacro) may change before 2.0.0.

Tests

The tests read fixtures by paths relative to the repository, so they run in a source tree, not against an installed wheel.

pip install -e ".[extra,test]"
pytest -q tests          # 66 tests; five of them start Julia and are skipped where Julia is absent

Relation to version 1

Version 1 (1.8.1) used a comm and a JupyterLab extension. Version 2 replaces both and has no compatibility layer: await GeoGebra().init(), ggb.function(...) and the implicit applet of the %%ggb magic are gone. Version 1 stays available as it is: pip install "ggblab<2".

License

BSD 3-Clause, see LICENSE.

GeoGebra itself is not part of this package. The applet is loaded from GeoGebra's servers under GeoGebra's own license, which is free for non-commercial use.

How this version was written

Version 2 was written with AI assistance. The author decided the design, the order of the stages and the acceptance criteria, and ruled on every open question. The code, the tests and the documentation were drafted by an AI coding agent (Anthropic Claude, through Claude Code) and accepted only after the example notebooks and the test suite reproduced the recorded results. Version 1 was written by the author, from January 2026 with the help of GitHub Copilot.

Metadata

Release files for ggblab 2.0.0rc2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ggblab 2.0.0rc2
File Size Uploaded
ggblab-2.0.0rc2.tar.gz 187.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ggblab 2.0.0rc2
File Interpreter ABI Platform
ggblab-2.0.0rc2-py3-none-any.whl Python 3 none any Details

Total release size: 288.8 kB

Release files / ggblab-2.0.0rc2.tar.gz

Download URL ggblab-2.0.0rc2.tar.gz
Size 187.7 kB
Tags Source
SHA-256 checksum
How to use checksums
b788c576653b94292ef02768baff0196b35e3eca51c78c04f22cc8103f5f41ef
BLAKE2b-256 checksum
How to use checksums
c4ff61cfe9712821aa57a328bd8cfcba0427933b30d38988fa9ad5b3667ee9f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / ggblab-2.0.0rc2-py3-none-any.whl

Download URL ggblab-2.0.0rc2-py3-none-any.whl
Size 101.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e1ef7ba96249aebece163a2832787a7139280c3e8415712510d1c08b39898c79
BLAKE2b-256 checksum
How to use checksums
8dfb725c587883ede883d16216802536f9c78b9a17a825d2425121a81f7dceb8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

2.0.0rc2 This release

2 release files

1.8.1

2 release files

1.8.0

2 release files

1.7.5

2 release files

1.7.4

2 release files

1.7.3

2 release files

1.7.1

2 release files

1.7.0

2 release files

1.6.0

2 release files

1.5.3

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.4

2 release files

1.3.3

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.4

2 release files

1.2.1

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.0

2 release files

0.9.19

2 release files

0.9.18

2 release files

0.9.17

2 release files

0.9.16

2 release files

0.9.15

2 release files

0.9.14

2 release files

0.9.13

2 release files

0.9.12

2 release files

0.9.11

2 release files

0.9.10

2 release files

0.9.8

2 release files

0.9.6

2 release files

0.9.4

2 release files

0.9.3

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.9

2 release files

0.8.8

2 release files

0.8.7

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page