Customizing one instance#
@Renderer.register(...) changes a renderer class and every instance created from it.
To change one renderer object only, call register_handler on the instance. It takes the
same classifiers as register.
"""Per-instance customization: one MarkdownRenderer that hides import lines."""
from handcalcs.renderers import MarkdownRenderer
def hide_import(renderer, node, base_context):
return ""
def make_renderer():
renderer = MarkdownRenderer()
renderer.register_handler("import", hide_import)
return renderer
import math
a = 2
b = math.sqrt(a)
$$\begin{aligned} a &= 2 \\ b &= \sqrt{a} = \sqrt{2} = 1.4142 \end{aligned}$$
Other MarkdownRenderer objects still show imports.
When to use it#
Quick experiments in a notebook, without defining a class.
Per-request settings in an application, where each request builds its own renderer.
Tests, where a handler must not leak into other tests.
For anything you reuse, a subclass is clearer: it has a name, can be selected in Jupyter, and can be imported from your own package.
How it works#
Each renderer instance copies its class’s handler and rule tables when it is created, and
register_handler adds to the copies. Registering a bare node type ("import") replaces
that node’s handler; registering a rule ("import:post") appends to that node’s rule list.
Instances created before a class-level register call keep the old tables.
Next: the cookbook, for complete recipes.