Extensions
Custom Filters
A filter is simply a function that transforms and returns its first argument.
Custom filters are both extremely powerful and extremely easy to implement.
They're registered using the @ibis.filters.register
decorator.
Let's start with a simple example. Imagine we want a filter to round a floating-point number to 2 decimal places:
@ibis.filters.register("fmt_float") def format_float(value): return "{:.2f}".format(value)
We can use our custom filter like this:
template = ibis.Template("{{ value|fmt_float }}") assert template.render(value=123.456789) == "123.46"
More generally, our custom filter can take a format_string
argument to format any kind of value:
@ibis.filters.register("fmt_value") def format_value(value, format_string): return format_string.format(value)
We can use this custom filter like this:
template = ibis.Template("{{ value|fmt_value('{.2f}') }}") assert template.render(value=123.456789) == "123.46"
Filter functions can take multiple arguments and support arguments with default values. As an example, we can register a filter to convert datetime objects into formatted strings:
@ibis.filters.register('dtformat') def format_datetime(dt, format_string='%Y-%m-%d'): return dt.strftime(format_string)
This gives us a dtformat
filter with an optional format_string
argument that we can call on any datetime
object, including the built-in now()
function which returns a datetime object representing the current time:
{{ now()|dtformat }} {{ now()|dtformat('%Y') }}
As it happens, dtformat
already exists as a built-in filter. Re-registering the dtformat
name would simply override the built-in filter with our own custom version.
Custom Instruction Tags
You can register custom instruction tags to supplement or override the built-in ones. Creating custom tags is more complicated than creating custom filters as you'll need to understand some of the internal details of how Ibis compiles template strings into trees of Node
objects.
Every instruction tag corresponds to a subclass of the ibis.nodes.Node
type. To create a new
instruction tag, register a subclass using the @nodes.register
decorator:
@ibis.nodes.register('foo')
You can give your new tag block scope by specifying an end word:
@ibis.nodes.register('foo', 'endfoo')
You'll need to turn to the source code itself for further details — see the ibis/nodes.py
file for lots of examples to work from.
Custom Builtins
You can assign custom variables and functions to the ibis.context.builtins
dictionary to make them
available in all templates.
Custom Tag Syntax
You can customize Ibis's tag delimiter syntax to suit your own taste. The default tag delimiters are shown below:
ibis.compiler.comment_start = '{#' ibis.compiler.comment_end = '#}' ibis.compiler.print_start = '{{' ibis.compiler.print_end = '}}' ibis.compiler.eprint_start = '{$' ibis.compiler.eprint_end = '$}' ibis.compiler.instruction_start = '{%' ibis.compiler.instruction_end = '%}'
All you need to do is assign new delimiter strings to the above variables.