---
title: Python SDK Templating
---
Filters can be used when defining [computed attributes](https://docs.infrahub.app/guides/computed-attributes) or [Jinja2 Transforms](https://docs.infrahub.app/guides/jinja2-transform) within Infrahub.

## Execution contexts

Filters are restricted based on the execution context in which a template is rendered:

- **CORE** — Computed attributes evaluated inside the Infrahub API server. Only fully trusted filters (no I/O, no side effects) are allowed.
- **WORKER** — Jinja2 transforms executed on Prefect background workers. Trusted filters and Infrahub client-dependent filters are allowed.
- **LOCAL** — Local CLI rendering and unrestricted usage. All filters are allowed.

The `validate()` method on `Jinja2Template` accepts an optional `context` parameter to enforce these restrictions:

```python
from infrahub_sdk.template import Jinja2Template
from infrahub_sdk.template.filters import ExecutionContext

template = Jinja2Template(template="{{ sid | artifact_content }}")

# Raises JinjaTemplateOperationViolationError — blocked in CORE
template.validate(context=ExecutionContext.CORE)

# Passes — allowed in WORKER
template.validate(context=ExecutionContext.WORKER)
```

For backward compatibility, `validate(restricted=True)` maps to `CORE` and `validate(restricted=False)` maps to `LOCAL`.

## Builtin Jinja2 filters

The following filters are [shipped with Jinja2](https://jinja.palletsprojects.com/en/stable/templates/#list-of-builtin-filters) and enabled within Infrahub.

<!-- vale off -->
| Name | CORE | WORKER | LOCAL |
| ---- | ---- | ------ | ----- |
| abs | ✅ | ✅ | ✅ |
| attr | ❌ | ✅ | ✅ |
| batch | ❌ | ✅ | ✅ |
| capitalize | ✅ | ✅ | ✅ |
| center | ✅ | ✅ | ✅ |
| count | ✅ | ✅ | ✅ |
| d | ✅ | ✅ | ✅ |
| default | ✅ | ✅ | ✅ |
| dictsort | ❌ | ✅ | ✅ |
| e | ✅ | ✅ | ✅ |
| escape | ✅ | ✅ | ✅ |
| filesizeformat | ✅ | ✅ | ✅ |
| first | ✅ | ✅ | ✅ |
| float | ✅ | ✅ | ✅ |
| forceescape | ✅ | ✅ | ✅ |
| format | ✅ | ✅ | ✅ |
| groupby | ❌ | ✅ | ✅ |
| indent | ✅ | ✅ | ✅ |
| int | ✅ | ✅ | ✅ |
| items | ❌ | ✅ | ✅ |
| join | ✅ | ✅ | ✅ |
| last | ✅ | ✅ | ✅ |
| length | ✅ | ✅ | ✅ |
| list | ✅ | ✅ | ✅ |
| lower | ✅ | ✅ | ✅ |
| map | ❌ | ✅ | ✅ |
| max | ✅ | ✅ | ✅ |
| min | ✅ | ✅ | ✅ |
| pprint | ❌ | ✅ | ✅ |
| random | ❌ | ✅ | ✅ |
| reject | ❌ | ✅ | ✅ |
| rejectattr | ❌ | ✅ | ✅ |
| replace | ✅ | ✅ | ✅ |
| reverse | ✅ | ✅ | ✅ |
| round | ✅ | ✅ | ✅ |
| safe | ❌ | ✅ | ✅ |
| select | ❌ | ✅ | ✅ |
| selectattr | ❌ | ✅ | ✅ |
| slice | ✅ | ✅ | ✅ |
| sort | ❌ | ✅ | ✅ |
| string | ✅ | ✅ | ✅ |
| striptags | ✅ | ✅ | ✅ |
| sum | ✅ | ✅ | ✅ |
| title | ✅ | ✅ | ✅ |
| tojson | ❌ | ✅ | ✅ |
| trim | ✅ | ✅ | ✅ |
| truncate | ✅ | ✅ | ✅ |
| unique | ❌ | ✅ | ✅ |
| upper | ✅ | ✅ | ✅ |
| urlencode | ✅ | ✅ | ✅ |
| urlize | ❌ | ✅ | ✅ |
| wordcount | ✅ | ✅ | ✅ |
| wordwrap | ✅ | ✅ | ✅ |
| xmlattr | ❌ | ✅ | ✅ |
<!-- vale on -->

## Netutils filters

The following Jinja2 filters from <a href="https://netutils.readthedocs.io">Netutils</a> are included within Infrahub.

<!-- vale off -->
| Name | CORE | WORKER | LOCAL |
| ---- | ---- | ------ | ----- |
| abbreviated_interface_name | ✅ | ✅ | ✅ |
| abbreviated_interface_name_list | ✅ | ✅ | ✅ |
| asn_to_int | ✅ | ✅ | ✅ |
| bits_to_name | ✅ | ✅ | ✅ |
| bytes_to_name | ✅ | ✅ | ✅ |
| canonical_interface_name | ✅ | ✅ | ✅ |
| canonical_interface_name_list | ✅ | ✅ | ✅ |
| cidr_to_netmask | ✅ | ✅ | ✅ |
| cidr_to_netmaskv6 | ✅ | ✅ | ✅ |
| clean_config | ✅ | ✅ | ✅ |
| compare_version_loose | ✅ | ✅ | ✅ |
| compare_version_strict | ✅ | ✅ | ✅ |
| config_compliance | ✅ | ✅ | ✅ |
| config_section_not_parsed | ✅ | ✅ | ✅ |
| delimiter_change | ✅ | ✅ | ✅ |
| diff_network_config | ✅ | ✅ | ✅ |
| feature_compliance | ✅ | ✅ | ✅ |
| find_unordered_cfg_lines | ✅ | ✅ | ✅ |
| fqdn_to_ip | ❌ | ❌ | ✅ |
| get_all_host | ❌ | ❌ | ✅ |
| get_broadcast_address | ✅ | ✅ | ✅ |
| get_first_usable | ✅ | ✅ | ✅ |
| get_ips_sorted | ✅ | ✅ | ✅ |
| get_nist_urls | ✅ | ✅ | ✅ |
| get_nist_vendor_platform_urls | ✅ | ✅ | ✅ |
| get_oui | ✅ | ✅ | ✅ |
| get_peer_ip | ✅ | ✅ | ✅ |
| get_range_ips | ✅ | ✅ | ✅ |
| get_upgrade_path | ✅ | ✅ | ✅ |
| get_usable_range | ✅ | ✅ | ✅ |
| hash_data | ✅ | ✅ | ✅ |
| int_to_asdot | ✅ | ✅ | ✅ |
| interface_range_compress | ✅ | ✅ | ✅ |
| interface_range_expansion | ✅ | ✅ | ✅ |
| ip_addition | ✅ | ✅ | ✅ |
| ip_subtract | ✅ | ✅ | ✅ |
| ip_to_bin | ✅ | ✅ | ✅ |
| ip_to_hex | ✅ | ✅ | ✅ |
| ipaddress_address | ✅ | ✅ | ✅ |
| ipaddress_interface | ✅ | ✅ | ✅ |
| ipaddress_network | ✅ | ✅ | ✅ |
| is_classful | ✅ | ✅ | ✅ |
| is_fqdn_resolvable | ❌ | ❌ | ✅ |
| is_ip | ✅ | ✅ | ✅ |
| is_ip_range | ✅ | ✅ | ✅ |
| is_ip_within | ✅ | ✅ | ✅ |
| is_netmask | ✅ | ✅ | ✅ |
| is_network | ✅ | ✅ | ✅ |
| is_reversible_wildcardmask | ✅ | ✅ | ✅ |
| is_valid_mac | ✅ | ✅ | ✅ |
| longest_prefix_match | ✅ | ✅ | ✅ |
| mac_normalize | ✅ | ✅ | ✅ |
| mac_to_format | ✅ | ✅ | ✅ |
| mac_to_int | ✅ | ✅ | ✅ |
| mac_type | ✅ | ✅ | ✅ |
| name_to_bits | ✅ | ✅ | ✅ |
| name_to_bytes | ✅ | ✅ | ✅ |
| name_to_name | ✅ | ✅ | ✅ |
| netmask_to_cidr | ✅ | ✅ | ✅ |
| netmask_to_wildcardmask | ✅ | ✅ | ✅ |
| normalise_delimiter_caret_c | ✅ | ✅ | ✅ |
| paloalto_panos_brace_to_set | ✅ | ✅ | ✅ |
| paloalto_panos_clean_newlines | ✅ | ✅ | ✅ |
| regex_findall | ❌ | ❌ | ✅ |
| regex_match | ❌ | ❌ | ✅ |
| regex_search | ❌ | ❌ | ✅ |
| regex_split | ❌ | ❌ | ✅ |
| regex_sub | ❌ | ❌ | ✅ |
| sanitize_config | ✅ | ✅ | ✅ |
| section_config | ✅ | ✅ | ✅ |
| sort_interface_list | ✅ | ✅ | ✅ |
| split_interface | ✅ | ✅ | ✅ |
| uptime_seconds_to_string | ✅ | ✅ | ✅ |
| uptime_string_to_seconds | ✅ | ✅ | ✅ |
| version_metadata | ✅ | ✅ | ✅ |
| vlanconfig_to_list | ✅ | ✅ | ✅ |
| vlanlist_to_config | ✅ | ✅ | ✅ |
| wildcardmask_to_netmask | ✅ | ✅ | ✅ |
<!-- vale on -->

## Infrahub filters

These filters are provided by the Infrahub SDK for artifact and file object content composition.

<!-- vale off -->
| Name | CORE | WORKER | LOCAL |
| ---- | ---- | ------ | ----- |
| `artifact_content` | ❌ | ✅ | ❌ |
| `file_object_content` | ❌ | ✅ | ❌ |
| `file_object_content_by_hfid` | ❌ | ✅ | ❌ |
| `file_object_content_by_id` | ❌ | ✅ | ❌ |
| `from_json` | ✅ | ✅ | ✅ |
| `from_yaml` | ✅ | ✅ | ✅ |
<!-- vale on -->

### Usage examples

**Inline artifact content by `storage_id`:**

```jinja2
{{ artifact.node.storage_id.value | artifact_content }}
```

**Inline file object content:**

```jinja2
{# By storage_id #}
{{ file_object.storage_id.value | file_object_content }}

{# By node UUID #}
{{ file_object.id | file_object_content_by_id }}

{# By Human-Friendly ID #}
{{ hfid_components | file_object_content_by_hfid(kind="NetworkCircuitContract") }}
```

**Parse structured content with chaining:**

```jinja2
{# JSON artifact → access parsed fields #}
{% set config = artifact.node.storage_id.value | artifact_content | from_json %}
interface {{ config.interface_name }}
  ip address {{ config.ip_address }}

{# YAML artifact → iterate parsed data #}
{% set config = artifact.node.storage_id.value | artifact_content | from_yaml %}
{% for route in config.static_routes %}
ip route {{ route.prefix }} {{ route.next_hop }}
{% endfor %}
```

Client-dependent filters (`artifact_content`, `file_object_content`, `file_object_content_by_id`, `file_object_content_by_hfid`) require an `InfrahubClient` to be passed to `Jinja2Template`:

```python
from infrahub_sdk.template import Jinja2Template

# At construction time
template = Jinja2Template(template=my_template, client=client)

# Or via deferred injection
template = Jinja2Template(template=my_template)
template.set_client(client)
```

## Known issues

### Unable to combine the map and sort filters (https://github.com/pallets/jinja/issues/2081)

When using the `map` filter with the `sort` filter, you may encounter the following error:

```python
TypeError: 'async_generator' object is not iterable
```

**As a workaround you can use the `list` filter between `map` and `sort` filter.**