baler_fn API
baler_fn is the Python package behind Baler Notebooks. It does three things:
connect()returns a Haystack client for Baler, configured from environment variables.@baler_functionlabels a function so it can be listed.baler_fn.list()lists the functions that installed packages provide.
It comes preinstalled in the notebook image. Outside the image, install it from a Baler checkout
with pip install -e ., which also installs the rest of Baler. For a light install, run
pip install --no-deps -e . && pip install requests pandas: baler_fn itself needs only
requests, plus pandas for the *_df methods. pip then prints an
ERROR: pip's dependency resolver ... message listing Baler's server dependencies (psycopg, rdflib,
...). That message is expected and harmless: baler_fn doesn't use them.
baler_fn runs in your own Python process. Baler never imports or runs it.
Code
connect()
Code
Each argument falls back to an environment variable:
| argument | env var | example | notes |
|---|---|---|---|
url | BALER_URL | http://localhost:8080 | Baler's gateway. In the notebook container: http://gateway. |
api_key | BALER_API_KEY | eyJ... | from POST /auth/api-keys. See Notebooks. |
project | BALER_PROJECT | demo | the /api/<project> segment. Default demo. |
A missing URL or key raises baler_fn.ConfigError, and the message names the variable. connect()
doesn't contact the server. The first call you make does.
BalerClient
A session against <url>/api/<project>. It authenticates every request with
Authorization: Bearer <api key>, and its repr never shows the key.
| method | returns |
|---|---|
about() | the server's about record as a dict (productName, serverTime, ...) |
read(filter, limit=None) | records matching a Haystack filter, as a list of dicts |
read_df(filter, limit=None) | read() as a pandas DataFrame, one row per record |
his_read(id, range="today") | history rows [{"ts": <epoch seconds>, "val": ...}, ...] |
his_read_df(id, range="today") | history as a DataFrame with one column, val, indexed by UTC timestamp (ts) |
his_write(id, items) | sends samples to a point's history and returns how many were sent. Needs an operator key. |
phable() | a phable.HaystackClient on the same URL and key |
haystack | the underlying baler.haystack_client.HaystackClient |
base_url | <url>/api/<project> |
Ids. id is a point's ref as read() returns it, e.g. urn:point:fbf~2Fahu-1~2FanalogValue~2C1.
A leading @ is optional.
Ranges. range is any Haystack hisRead range: "today", "yesterday", "2026-11-01",
"2026-11-01,2026-11-07" (the end date is included), or two dateTimes separated by a comma
("2026-11-07T00:00:00Z UTC,2026-11-08T00:00:00Z UTC"). Baler also accepts Axon span words such as
pastWeek, but other Haystack servers may not.
Values. read and his_read decode Haystack values to plain Python:
| Haystack kind | Python value |
|---|---|
| Marker | True |
| Number | float. The unit is dropped. |
| Ref, Uri | the id or URI as a str |
| DateTime | epoch seconds (float) |
| Str, Bool | str, bool |
| anything else | the raw Haystack JSON dict, e.g. {"_kind": "coord", ...} |
If you need units, typed values or ops that aren't listed above, use client.phable().
Writing. his_write(id, items) accepts any of these:
- a pandas
Seriesindexed by timezone-aware timestamps - a one-column
DataFramewith the same kind of index - an iterable of
(datetime, value)pairs. The datetimes must be timezone-aware. Epoch seconds are also accepted.
Values may be numbers, bools or strings. A naive datetime raises ValueError, and an error grid
from the server raises HaystackError.
Code
Errors.
| error | when |
|---|---|
baler_fn.ConfigError | connect() has no URL or no key |
baler.haystack_client.HaystackAuthError | the key was rejected (401): wrong, revoked or expired |
requests.HTTPError | any other HTTP failure, e.g. 403 when a viewer key calls his_write |
baler.haystack_client.HaystackError | his_write got a Haystack error grid back |
@baler_function
Code
Marks a function as a Baler function. name defaults to the function's own name, and tags is a
list of strings. The decorator returns the same function object, so calling the function,
help(f), inspect and IDEs all work as before. It only adds metadata and doesn't register the
function anywhere: functions are found through the entry points their package declares.
By convention a function takes the client as its first argument. That way the caller decides which Baler it runs against, and with which key.
baler_fn.list()
Code
Lists every function declared in the baler.functions entry-point group by an installed
distribution. It reads the installed packages each time you call it, so the list changes only when
you pip install or uninstall something. You don't need to restart the kernel after an install.
An entry point names either one decorated function ("pkg.module:function") or a module
("pkg.module"). A module means every decorated function defined in that module.
tag="energy" keeps only functions carrying that tag.
A FunctionList is a list of FunctionInfo:
- It prints as a table in a terminal and as an HTML table in Jupyter.
fns["his_stats"]looks a function up by name.fns.names()returns the names.fns.to_frame()returns a DataFrame.fns.errorslists entry points that failed to import, or that point at an undecorated object. One broken package doesn't hide the others, andlist()warns when there are errors.
FunctionInfo fields: name, signature (e.g. "(client, point_id, range='today')"), doc (the
full docstring), summary (its first line), tags, module, package and version (the
distribution that provides it), entry_point, and func. Calling a FunctionInfo calls the
function: fns["his_stats"](client, point_id). For help(), pass the function itself:
help(fns["his_stats"].func).
describe() and is_baler_function()
Code
describe builds a FunctionInfo for any callable, decorated or not. Use it for functions defined
in a notebook cell, which list() doesn't see because they aren't installed.
Manifest API
These parse the baler.toml package manifest:
Code
A file that can't be used raises baler_fn.ManifestError, a ValueError. The message names the
file, the field and what was expected, for example
baler.toml: package.version: 'latest' is not valid (e.g. "0.1.0").
Manifest has the [package] fields as attributes, plus:
entry_points(a dict of name to target)functions(FunctionSpec(name, signature, summary, tags)entries)git_ref(ref, orv<version>whenrefisn't set)install_line(thepip install "git+..."command)
Command line
Run these where your package is installed, because they import it:
Code
check exits with status 1 and prints each difference it finds: version, entry points, functions
that are missing or extra, and mismatched signatures, docstring summaries or tags.

