Functions: @handcalc#

The @handcalc decorator turns a calculation function into one that returns both its result and its rendered calculation.

from handcalcs import handcalc
from handcalcs.renderers import MarkdownRenderer

@handcalc(MarkdownRenderer())
def moment(w, L):
    M = w * L**2 / 8  # Simply supported, uniform load
    return M

value, markdown = moment(5, 6)
# value == 22.5

The function runs normally. handcalcs captures the values of its local variables (with innerscope), then renders the function body with those values.

Signature#

handcalc(renderer=None, render_context=None)

renderer

A renderer instance. If it is omitted, the renderer named by the default_renderer option is used (the ASCII renderer unless you change it), as for HandCalcs. @handcalc() and a bare @handcalc both work.

render_context

A dictionary of render context fields for every call, for example {"format_code": ".2f"}. These override the global configuration.

The decorated function returns a tuple (return_value, rendered). The type of rendered depends on the renderer, as for HandCalcs.

What is rendered#

The body of the function (its lines between the def line and the return), with the values from that call. Arguments, local variables, closure variables and globals can all be used. Comment commands work as usual. An early return ends the rendered calculation where the function returned: the lines after it did not run, so they are not shown.

from math import sqrt

@handcalc(MarkdownRenderer(), render_context={"format_code": ".3g"})
def shear_capacity(b_w, d, f_c):
    ## Concrete shear resistance
    phi_c = 0.65
    beta = 0.18
    V_c = phi_c * beta * sqrt(f_c) * b_w * d / 1000  # kN
    return V_c

Using it in Jupyter#

The decorator returns the rendered output; it does not display it. Display it with the class that matches the renderer:

from IPython.display import Markdown, display

value, markdown = shear_capacity(300, 540, 30)
display(Markdown(markdown))

Source#

src/handcalcs/interfaces/decorator.py