# helpers

URL: /kida/api/template/helpers/
Section: template
Description: Pure runtime helper functions injected into the template namespace.

These functions are called by compiled template code at render time.
None of them close over Environment state — they are pure functions
that use only their parameters and deferred imports.

Thread-Safety:
All functions are stateless and safe for concurrent use.

---

> For a complete page index, fetch /kida/llms.txt.

Open LLM text
(/kida/api/template/helpers/index.txt)

Share with AI

Ask Claude
(https://claude.ai/new?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Ftemplate%2Fhelpers%2Findex.txt)

Ask ChatGPT
(https://chatgpt.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Ftemplate%2Fhelpers%2Findex.txt)

Ask Gemini
(https://gemini.google.com/app?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Ftemplate%2Fhelpers%2Findex.txt)

Ask Copilot
(https://copilot.microsoft.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Ftemplate%2Fhelpers%2Findex.txt)

Module

#
`template.helpers`

Pure runtime helper functions injected into the template namespace.

These functions are called by compiled template code at render time.
None of them close over Environment state — they are pure functions
that use only their parameters and deferred imports.

Thread-Safety:
All functions are stateless and safe for concurrent use.

1Class21Functions

## Classes

`_Undefined`

11

▼

Sentinel for failed attribute access on objects.

- ``str(_Undefined())`` returns ``""`` (template …

Sentinel for failed attribute access on objects.

- `str(_Undefined())` returns `""`(template output unchanged)

- `bool(_Undefined())` returns `False`(falsy guard works)

- `is_defined()`recognises it as "not defined"

#### Methods

`get`

2

`object`

▼

Return default for any key; enables obj.missing.get('x', 'fb') pattern.

If ``d…

`def get(self, key: str, default: object | None = _no_default) -> object`

Return default for any key; enables obj.missing.get('x', 'fb') pattern.

If`default`is provided, return it unchanged (including an explicit
`None`). If `default` is omitted, return `UNDEFINED`so Kida can
distinguish an omitted default from an explicit`None`.

##### Parameters

Name
Type
Description

`key`
`—`

`default`
`—`

Default:`_no_default`

##### Returns

`object`

`keys`

0

`list[str]`

▼

Empty keys; enables {% for k in missing.keys() %} without error.

`def keys(self) -> list[str]`

##### Returns

`list[str]`

`values`

0

`list[object]`

▼

Empty values; enables {% for v in missing.values() %} without error.

`def values(self) -> list[object]`

##### Returns

`list[object]`

`items`

0

`list[tuple[str, object]]`

▼

Empty items; enables {% for k, v in missing.items() %} without error.

`def items(self) -> list[tuple[str, object]]`

##### Returns

`list[tuple[str, object]]`

Internal Methods
7

▼

`__str__`

0

`str`

▼

`def __str__(self) -> str`

##### Returns

`str`

`__repr__`

0

`str`

▼

`def __repr__(self) -> str`

##### Returns

`str`

`__bool__`

0

`bool`

▼

`def __bool__(self) -> bool`

##### Returns

`bool`

`__eq__`

1

`bool`

▼

`def __eq__(self, other: object) -> bool`

##### Parameters

Name
Type
Description

`other`
`—`

##### Returns

`bool`

`__hash__`

0

`int`

▼

`def __hash__(self) -> int`

##### Returns

`int`

`__iter__`

0

▼

Empty iterator so ``{% for x in missing %}`` silently yields nothing.

`def __iter__(self)`

`__len__`

0

`int`

▼

`def __len__(self) -> int`

##### Returns

`int`

## Functions

`safe_getattr`

2

`object`

▼

Get attribute with dict fallback and None-safe handling.

Resolution order:
- D…

`def safe_getattr(obj: object, name: str) -> object`

Get attribute with dict fallback and None-safe handling.

Resolution order:

- Dicts: subscript first (user data), getattr fallback (methods).
This prevents dict method names like`items`, `keys`,
`values`, `get`from shadowing user data keys.

- Objects: getattr first, subscript fallback.

None Handling (like Hugo/Go templates):

- If obj is None, returns UNDEFINED (prevents crashes)

- If attribute value is None, returns "" (normalizes output)

Not-Found Handling:

- Returns the`UNDEFINED`sentinel when the attribute/key is
not found.`UNDEFINED` stringifies as `""`(so template
output is unchanged) but`is_defined()`recognises it as
not defined, fixing`x.missing is defined`→ False.

Complexity: O(1)

##### Parameters

Name
Type
Description

`obj`
`object`

`name`
`str`

##### Returns

`object`

`getattr_preserve_none`

2

`object`

▼

Get attribute with mapping fallback, preserving None values.

Like safe_getattr…

`def getattr_preserve_none(obj: object, name: str) -> object`

Get attribute with mapping fallback, preserving None values.

Like safe_getattr but preserves None values instead of converting
to empty string. Used for optional chaining (?.) so that null
coalescing (??) can work correctly.

Resolution order matches safe_getattr: Mappings try subscript first.

Complexity: O(1)

##### Parameters

Name
Type
Description

`obj`
`object`

`name`
`str`

##### Returns

`object`

`getitem_preserve_none`

2

`object`

▼

Optional subscript with Mapping fallback, preserving None values.

Used by `?[k…

`def getitem_preserve_none(obj: object, key: object) -> object`

Optional subscript with Mapping fallback, preserving None values.

Used by`?[key]` in lenient mode. Mapping receivers return `None`for
missing keys (mirroring`dict.get(key)`); other subscriptable receivers
return`None` on `KeyError`/`IndexError`/`TypeError`.

Complexity: O(1)

##### Parameters

Name
Type
Description

`obj`
`object`

`key`
`object`

##### Returns

`object`

`_raise_undefined_attr`

3

`Any`

▼

Raise UndefinedError for missing attribute/key access.

`def _raise_undefined_attr(obj: object, name: str, *, preserve_none: bool = False) -> Any`

##### Parameters

Name
Type
Description

`obj`
`object`

`name`
`str`

`preserve_none`
`bool`

Default:`False`

##### Returns

`Any`

`strict_getattr`

2

`object`

▼

Like safe_getattr but raises UndefinedError on missing attributes.

Used when E…

`def strict_getattr(obj: object, name: str) -> object`

Like safe_getattr but raises UndefinedError on missing attributes.

Used when Environment(strict_undefined=True) to catch typos in attribute
access at render time.

##### Parameters

Name
Type
Description

`obj`
`object`

`name`
`str`

##### Returns

`object`

`strict_getattr_preserve_none`

2

`object`

▼

Like getattr_preserve_none but raises UndefinedError on missing object attrs.

…

`def strict_getattr_preserve_none(obj: object, name: str) -> object`

Like getattr_preserve_none but raises UndefinedError on missing object attrs.

Semantics (v0.8.0+):

- Mapping receivers (`dict` and `collections.abc.Mapping`subclasses):
missing keys short-circuit to`None`, mirroring `dict.get(key)`.
Used by`?.`on config/JSON/kwargs-style data where the schema is open.

- Object receivers (non-Mapping): missing attributes still raise
`UndefinedError`to catch template typos against an object's schema.

##### Parameters

Name
Type
Description

`obj`
`object`

`name`
`str`

##### Returns

`object`

`strict_getitem_preserve_none`

2

`object`

▼

Like getitem_preserve_none but strict on non-Mapping subscript misses.

Semanti…

`def strict_getitem_preserve_none(obj: object, key: object) -> object`

Like getitem_preserve_none but strict on non-Mapping subscript misses.

Semantics (v0.8.0+):

- Mapping receivers: missing keys short-circuit to`None`.

- Sequence / other subscriptable receivers: out-of-range or invalid-key
access raises`UndefinedError`. Off-by-one on a list is almost always
a bug, so strict mode preserves typo detection there.

##### Parameters

Name
Type
Description

`obj`
`object`

`key`
`object`

##### Returns

`object`

`markup_concat`

2

`str`

▼

Concatenate for ~ operator, preserving Markup safety.

If either operand is Mar…

`def markup_concat(left: Any, right: Any) -> str`

Concatenate for ~ operator, preserving Markup safety.

If either operand is Markup, the result is Markup and the non-Markup
operand is HTML-escaped via Markup.add/radd. If neither is
Markup, both are converted to plain strings.

##### Parameters

Name
Type
Description

`left`
`Any`

`right`
`Any`

##### Returns

`str`

`record_filter_usage`

3

`Any`

▼

Record filter usage for profiling, returning the result unchanged.

Called by c…

`def record_filter_usage(acc: RenderAccumulator | None, name: str, result: Any) -> Any`

Record filter usage for profiling, returning the result unchanged.

Called by compiled code for every filter invocation. When profiling
is disabled (acc is None), the cost is a single falsy check + return.

##### Parameters

Name
Type
Description

`acc`
`RenderAccumulator | None`

RenderAccumulator instance, or None when profiling is off

`name`
`str`

Filter name for recording

`result`
`Any`

The filter's return value (passed through unchanged)

##### Returns

`Any`

`record_macro_usage`

3

`Any`

▼

Record macro ({% def %}) call for profiling, returning the result unchanged.

C…

`def record_macro_usage(acc: RenderAccumulator | None, name: str, result: Any) -> Any`

Record macro ({% def %}) call for profiling, returning the result unchanged.

Called by compiled code for every macro invocation. When profiling
is disabled (acc is None), the cost is a single falsy check + return.

##### Parameters

Name
Type
Description

`acc`
`RenderAccumulator | None`

RenderAccumulator instance, or None when profiling is off

`name`
`str`

Macro/def name for recording

`result`
`Any`

The macro's return value (passed through unchanged)

##### Returns

`Any`

`lookup`

2

`Any`

▼

Look up a variable in strict mode.

In strict mode, undefined variables raise U…

`def lookup(ctx: dict[str, Any], var_name: str) -> Any`

Look up a variable in strict mode.

In strict mode, undefined variables raise UndefinedError instead
of silently returning None. This catches typos and missing variables
early, improving debugging experience.

Performance:

- Fast path (defined var): O(1) dict lookup, no imports

- Error path: Raises UndefinedError with template context

##### Parameters

Name
Type
Description

`ctx`
`dict[str, Any]`

`var_name`
`str`

##### Returns

`Any`

`lookup_scope`

3

`Any`

▼

Lookup variable in scope stack (top to bottom), then ctx.

Checks scopes from i…

`def lookup_scope(ctx: dict[str, Any], scope_stack: list[dict[str, Any]], var_name: str) -> Any`

Lookup variable in scope stack (top to bottom), then ctx.

Checks scopes from innermost to outermost, then falls back to ctx.
Raises UndefinedError if not found (strict mode).

##### Parameters

Name
Type
Description

`ctx`
`dict[str, Any]`

`scope_stack`
`list[dict[str, Any]]`

`var_name`
`str`

##### Returns

`Any`

`default_safe`

3

`Any`

▼

Safe default filter that works with strict mode.

In strict mode, the value exp…

`def default_safe(value_fn: Callable[[], Any], default_value: Any = '', boolean: bool = False) -> Any`

Safe default filter that works with strict mode.

In strict mode, the value expression might raise UndefinedError.
This helper catches that and returns the default value.

##### Parameters

Name
Type
Description

`value_fn`
`Callable[[], Any]`

A lambda that evaluates the value expression

`default_value`
`Any`

The fallback value if undefined or None/falsy

Default:`''`

`boolean`
`bool`

If True, check for falsy values; if False, check for None only

Default:`False`

##### Returns

`Any`

`is_defined`

1

`bool`

▼

Check if a value is defined in strict mode.

In strict mode, we need to catch U…

`def is_defined(value_fn: Callable[[], Any]) -> bool`

Check if a value is defined in strict mode.

In strict mode, we need to catch UndefinedError to determine
if a variable is defined.

A value is considered undefined when:

- The variable doesn't exist (raises UndefinedError)

- The value is`None`

- The value is the`_Undefined`sentinel (failed attribute access)

This means`obj.missing_attr is defined`correctly returns False
even when`obj` itself exists, because `_safe_getattr`returns
the`UNDEFINED`sentinel for missing attributes.

##### Parameters

Name
Type
Description

`value_fn`
`Callable[[], Any]`

A lambda that evaluates the value expression

##### Returns

`bool`

`null_coalesce`

2

`Any`

▼

Safe null coalescing that handles undefined variables.

In strict mode, the lef…

`def null_coalesce(left_fn: Callable[[], Any], right_fn: Callable[[], Any]) -> Any`

Safe null coalescing that handles undefined variables.

In strict mode, the left expression might raise UndefinedError.
This helper catches that and returns the right value.

Unlike the default filter:

- Returns right ONLY if left is None or undefined

- Does NOT treat falsy values (0, '', False, []) as needing replacement

##### Parameters

Name
Type
Description

`left_fn`
`Callable[[], Any]`

A lambda that evaluates the left expression

`right_fn`
`Callable[[], Any]`

A lambda that evaluates the right expression (lazy)

##### Returns

`Any`

`spaceless`

1

`str`

▼

Remove whitespace between HTML tags.

RFC: kida-modern-syntax-features

`def spaceless(html: str) -> str`

##### Parameters

Name
Type
Description

`html`
`str`

##### Returns

`str`

`add_polymorphic`

2

`str`

▼

Polymorphic + operator with safe string-concatenation fallback.

**Goals:**
- K…

`def add_polymorphic(left: Any, right: Any) -> str`

Polymorphic + operator with safe string-concatenation fallback.

Goals:

- Keep natural Python behavior for compatible operand types (`list + list`,
`tuple + tuple`, etc.).

- Support Jinja-style string ergonomics (`count + " items"`).

- Avoid silently stringifying collection arithmetic, which can explode output.

##### Parameters

Name
Type
Description

`left`
`Any`

Left operand

`right`
`Any`

Right operand

##### Returns

`str`

`coerce_numeric`

1

`int | float`

▼

Coerce value to numeric type for arithmetic operations.

Handles Markup objects…

`def coerce_numeric(value: Any) -> int | float`

Coerce value to numeric type for arithmetic operations.

Handles Markup objects (from macros) and strings that represent numbers.
This prevents string multiplication when doing arithmetic with macro results.

##### Parameters

Name
Type
Description

`value`
`Any`

Any value, typically Markup from macro or filter result

##### Returns

`int | float`

`str_safe`

1

`str`

▼

Convert value to string, treating None as empty string.

This is used for templ…

`def str_safe(value: Any) -> str`

Convert value to string, treating None as empty string.

This is used for template output so that optional chaining
expressions that evaluate to None produce empty output rather
than the literal string 'None'.

Preserves Markup instances (and objects with html) so that
the escape function can detect them and avoid double-escaping.

RFC: kida-modern-syntax-features — needed for optional chaining.

##### Parameters

Name
Type
Description

`value`
`Any`

##### Returns

`str`

`consume`

2

`Any`

▼

Read a value from the nearest ``{% provide %}`` ancestor.

Template-level funct…

`def consume(key: str, default: Any = None) -> Any`

Read a value from the nearest`{% provide %}`ancestor.

Template-level function that reads from the RenderContext provider
stack. Returns default if no provider is active for key.

Example::

```
{% provide color = "red" %}
    {{ consume("color") }}  {# outputs: red #}
{% end %}
```

##### Parameters

Name
Type
Description

`key`
`str`

`default`
`Any`

Default:`None`

##### Returns

`Any`

`optional_call`

3

`Any`

▼

Call callee only if it is not None or UNDEFINED.

Used for obj?.method() so tha…

`def optional_call(callee: Any, *args: object, **kwargs: object) -> Any`

Call callee only if it is not None or UNDEFINED.

Used for obj?.method() so that when obj is None or obj.attr is UNDEFINED,
the call short-circuits and returns UNDEFINED (outputs as "").

##### Parameters

Name
Type
Description

`callee`
`Any`

`*args`
`object`

`**kwargs`
`object`

##### Returns

`Any`
