sphinx-pyrepl-web

Sphinx extension to embed pyrepl-web in documentation.

Install

pip install sphinx-pyrepl-web

Usage

Add the extension to the target project’s conf.py module:

extensions = [
    "sphinx_pyrepl_web",
]

Embed a REPL with the py-repl directive:

.. py-repl::

.. py-repl::
   :theme: catppuccin-latte
   :no-header:

.. py-repl::
   :src: setup.py
   :packages: numpy

.. py-repl::
   :no-header:

   >>> import math
   >>> math.sqrt(16)

Directive options

All options drive pyrepl-web’s attributes:

Option

Description

:theme:

Color theme (catppuccin-mocha, catppuccin-latte)

:packages:

Comma-separated PyPI packages, URLs or relative wheel paths

:repl-title:

Title in the REPL header

:src:

Path to a Python startup script

:replay:

Replay :src: with interactive prompts instead of silent load

:no-header:

Hide the header bar

:no-buttons:

Hide copy/clear buttons

:readonly:

Disable input

:no-banner:

Hide the Python version banner

Sphinx options

Enable doctest style examples conversion into pre-configured interactive REPLs with:

pyrepl_doctest_blocks:

Value

Outcome

False (default)

Don’t convert doctest blocks

"autodoc"

Convert doctest blocks from autodoc

"all"

Convert all doctest blocks

pyrepl_autodoc_packages:

Value

Outcome

None (default)

Replay doctest input without preloading packages

Wheel path / PyPI names

Install the package and import the documented object before replay

Local wheels

Unreleased package wheels can be available in the REPL by building them under Sphinx’s html_static_path.

All options combined:

extensions = [
    "sphinx.ext.autodoc",
    "sphinx_pyrepl_web",
]

html_static_path = ["_static"]

pyrepl_doctest_blocks = "autodoc"
pyrepl_autodoc_packages = "_static/wheels/my_package-1.0.0-py3-none-any.whl"

Examples

Basic REPL

.. py-repl::

Light theme, minimal

.. py-repl::
   :theme: catppuccin-latte
   :no-header:
   :no-banner:

Startup script

The :src: option loads a Python script into the REPL namespace. If the script defines a setup() function, its output is shown when the REPL starts.

Startup script:

message = "Hello from the startup script!"


def setup():
    print(message)
    print("Try: message")

RST content:

.. py-repl::
   :src: _static/setup.py

Rendered result:

Replay session

Inline content should follow doctest-style (>>> / ...) and is used as replay prompts.

.. py-repl::
   :no-header:
   :no-banner:

   >>> x = 2 + 2
   >>> print(f"{x=}")
   >>> x * 10
   >>> class Foo:
   ...     x = 1
   ...
   >>> Foo()

Combine a startup script with a visible replay body:

.. py-repl::
   :src: _static/setup.py
   :no-header:

   >>> print(message)

Use :replay: on :src: to source a file as replay.

Source script:

greeting = "Hello from replay mode"
print(greeting)
greeting.upper()

RST content:

.. py-repl::
   :src: _static/replay_demo.py
   :replay:
   :no-header:
   :no-banner:

Rendered result:

Local packages

Use static local wheel packages on .. py-repl:: directives:

.. py-repl::
   :packages: _static/wheels/pyrepl_test_pkg-1.0.0-py3-none-any.whl
   :no-header:
   :no-banner:

   >>> import pyrepl_test_pkg
   >>> pyrepl_test_pkg.ping()

Autodoc

Use pyrepl_doctest_blocks = "autodoc" to turn docstrings from autodoc into interactive REPL examples.

Set pyrepl_autodoc_packages to install the documented package and automatically import the documented object before replay:

# conf.py
html_static_path = ["_static"]
pyrepl_doctest_blocks = "autodoc"
pyrepl_autodoc_packages = "_static/wheels/pyrepl_test_pkg-1.0.0-py3-none-any.whl"

Source module:

"""Demo module for autodoc doctest REPL integration."""


def example_generator(n):
    """Generators yield values useful for iteration.

    Example:

        >>> print([i for i in example_generator(4)])
        [0, 1, 2, 3]

    """
    yield from range(n)

RST content:

.. autofunction:: pyrepl_test_pkg.demo.example_generator

Rendered result:

pyrepl_test_pkg.demo.example_generator(n)

Generators yield values useful for iteration.

Example

Development

Setup

Clone the repository, then install in editable mode with test and docs dependencies:

pip install -e ".[test,docs]"

The [docs] extra pulls in doc build dependencies and the pyrepl_test_pkg fixture used in the examples.

Build and preview docs

Build HTML output from the docs/ directory:

python -m sphinx -b html docs docs/_build

REPLs load JavaScript, replay scripts, and wheels with fetch, so they do not work when opening index.html directly from disk (file:// URLs). Serve the build output over HTTP instead:

python -m http.server --directory docs/_build

Then open http://localhost:8000/ in a browser.

Build-time behavior

Python code within a .. py-repl:: directive is written to _static/pyrepl/ at build time and emitted as replay-src.

File paths identifiers in :packages:, :src:, replay-src, and pyrepl_autodoc_packages are rewritten to page-relative URLs so REPLs work on nested pages (for example docs/api/...). PyPI package names, absolute URLs, and paths written as root-absolute (/_static/...) are left unchanged.

pyrepl_js (default: "../pyrepl.js") sets the loader script Sphinx injects on REPL pages. The extension vendors and copies pyrepl-web automatically; override this only when pointing at a custom loader path or CDN.

Static wheels

Wheel packages must be Pyodide compatible (pure-python packages work out of the box). For CPython extensions, visit pyodide-build.

Wheels under _static/ are copied into the HTML output when _static is listed in html_static_path. At runtime, pyrepl-web resolves site-relative wheel paths to absolute URLs before calling micropip.install().

Paths must use the wheel’s actual PyPI-compliant filename (for example myext-1.2.3-py3-none-any.whl). micropip rejects other names.

Ensure the web server serves .whl files with MIME type application/zip (Read the Docs does this by default).

Updating pyrepl-web

This extension vendors JavaScript from pyrepl-web’s fork for easier distribution. To refresh the vendored assets:

python scripts/vendor_repl.py

The grill branch is used by default. Pass --branch to vendor from another branch:

python scripts/vendor_repl.py --branch custom/feature-branch

This requires git and Bun.