Skip to content

The API namespace

client.api is a dynamic namespace: attribute access builds a dotted method name, and calling it invokes that middleware method.

client.api.system.info()                       # -> system.info
client.api.pool.dataset.query([["type", "=", "FILESYSTEM"]])   # -> pool.dataset.query

Any method the middleware exposes is reachable this way — there are no per-endpoint wrappers to keep in sync with TrueNAS.

Convenience helpers

On top of the raw methods, each namespace offers helpers (prefixed _) for the patterns you'd otherwise hand-write:

Helper Does
._query(**filters) query with filters built from keyword args
._get(id) / ._get(**filters) one record by id or filter, or None
._create(**fields) create
._update(selector, **fields) update, diffing against current state
._upsert(selector, **fields) create if absent, else update the diff
# Filters from kwargs, with operator helpers:
from pytruenas.utils import query as q
admins = client.api.user._query(uid=q.GT(0), locked=False)

# Fetch-or-None:
root = client.api.user._get(username="root")     # dict, or None if missing

# Create-or-update by a selector field:
client.api.user._upsert("username", username="svc", full_name="Service")

_upsert(selector, ...) resolves the row by the selector field(s); if it exists the changed fields are updated (a no-op diff makes no call), otherwise the record is created. A middleware job returned by a mutating call is waited on by default (wait=True).

Query filters

pytruenas.utils.query provides operator wrappers so kwargs map to middleware filter tuples:

from pytruenas.utils import query as q
q.filter_from_kwargs(username="root", uid=q.GT(0))
# -> [("username", "=", "root"), ("uid", ">", 0)]

Available: EQ, NE, RE, GT, GE, LT, LE, IN, NIN.

See the Namespace API.