swarmsim.util.jinja#

Custom modifications to Jinja templating engine.

This module adjusts and extends the behavior of the Jinja2 templating engine.

See also

If you’re looking for how to use Jinja when writing a YAML config, see Writing YAML Configs.

This module is used with our custom YAML loader, swarmsim.yaml, and config system.

It is also used by the swarmsim.metrics.JinjaMetric module and World.stop_at.

class swarmsim.util.jinja.Environment(block_start_string: str = '{%', block_end_string: str = '%}', variable_start_string: str = '{{', variable_end_string: str = '}}', comment_start_string: str = '{#', comment_end_string: str = '#}', line_statement_prefix: str | None = None, line_comment_prefix: str | None = None, trim_blocks: bool = False, lstrip_blocks: bool = False, newline_sequence: te.Literal['\n', '\r\n', '\r'] = '\n', keep_trailing_newline: bool = False, extensions: ~typing.Sequence[str | ~typing.Type[Extension]] = (), optimized: bool = True, undefined: ~typing.Type[~jinja2.runtime.Undefined] = <class 'jinja2.runtime.Undefined'>, finalize: ~typing.Callable[[...], ~typing.Any] | None = None, autoescape: bool | ~typing.Callable[[str | None], bool] = False, loader: BaseLoader | None = None, cache_size: int = 400, auto_reload: bool = True, bytecode_cache: BytecodeCache | None = None, enable_async: bool = False)[source]#

A Jinja environment.

This is based on jinja2.Environment.

Notably, we implement a system which allows an Environment to be pickled even if its globals contain modules. See add_global_module().

Attributes:
global_modules
lexer

The lexer for this environment.

linked_to

Methods

add_extension(extension)

Adds an extension after the environment was created.

add_global_module(name[, modulename])

Add a module to the Environment's globals.

call_filter(name, value[, args, kwargs, ...])

Invoke a filter on a value the same way the compiler does.

call_test(name, value[, args, kwargs, ...])

Invoke a test on a value the same way the compiler does.

compile(-> ~types.CodeType)

Compile a node or template source code.

compile_expression(source[, undefined_to_none])

A handy helper method that returns a callable that accepts keyword arguments that appear as variables in the expression.

compile_templates(target[, extensions, ...])

Finds all the templates the loader can find, compiles them and stores them in target.

concat(iterable, /)

Concatenate any number of strings.

context_class

extend(**attributes)

Add the items to the instance of the environment if they do not exist yet.

from_string(source[, globals, template_class])

Load a template from a source string without using loader.

get_or_select_template(template_name_or_list)

Use select_template() if an iterable of template names is given, or get_template() if one name is given.

get_template(name[, parent, globals])

Load a template by name with loader and return a Template.

getattr(obj, attribute)

Get an item or attribute of an object but prefer the attribute.

getitem(obj, argument)

Get an item or attribute of an object but prefer the item.

handle_exception([source])

Exception handling helper.

iter_extensions()

Iterates over the extensions by priority.

join_path(template, parent)

Join a template with the parent.

lex(source[, name, filename])

Lex the given sourcecode and return a generator that yields tokens as tuples in the form (lineno, token_type, value).

list_templates([extensions, filter_func])

Returns a list of templates for this environment.

make_globals(d)

Make the globals map for a template.

overlay([block_start_string, ...])

Create a new overlay environment that shares all the data with the current environment except for cache and the overridden attributes.

parse(source[, name, filename])

Parse the sourcecode and return the abstract syntax tree.

preprocess(source[, name, filename])

Preprocesses the source with all extensions.

refresh_global_modules()

Re-import all modules in Environment.global_modules.

remove_global_module(name)

Remove a module from the Environment's globals.

select_template(names[, parent, globals])

Like get_template(), but tries loading multiple names.

template_class

code_generator_class

add_global_module(name: str, modulename: str | None = None)[source]#

Add a module to the Environment’s globals.

The standard library pickle cannot handle modules. This function imports a module and tells us how we can reference and restore it when unpickling.

Parameters:
  • name (str) – The name to save the module in Environment.globals.

  • modulename (str | None, optional) – The name of the module to import, i.e. import modulename. If None, the name is used.

compile_expression(source: str, undefined_to_none: bool = True) TemplateExpression[source]#

A handy helper method that returns a callable that accepts keyword arguments that appear as variables in the expression. If called it returns the result of the expression.

See jinja2.Environment.compile_expression() for more details.

global_modules: List[Any] = None[source]#

A list of modules added to the environment’s globals.

refresh_global_modules()[source]#

Re-import all modules in Environment.global_modules.

remove_global_module(name: str)[source]#

Remove a module from the Environment’s globals.

Parameters:

name (str) – The in the Environment’s globals to remove.

template_class[source]#

alias of Template

class swarmsim.util.jinja.Template(source: str | ~jinja2.nodes.Template, block_start_string: str = '{%', block_end_string: str = '%}', variable_start_string: str = '{{', variable_end_string: str = '}}', comment_start_string: str = '{#', comment_end_string: str = '#}', line_statement_prefix: str | None = None, line_comment_prefix: str | None = None, trim_blocks: bool = False, lstrip_blocks: bool = False, newline_sequence: te.Literal['\n', '\r\n', '\r'] = '\n', keep_trailing_newline: bool = False, extensions: ~typing.Sequence[str | ~typing.Type[Extension]] = (), optimized: bool = True, undefined: ~typing.Type[~jinja2.runtime.Undefined] = <class 'jinja2.runtime.Undefined'>, finalize: ~typing.Callable[[...], ~typing.Any] | None = None, autoescape: bool | ~typing.Callable[[str | None], bool] = False, enable_async: bool = False)[source]#

A compiled template that can be rendered.

This is based on jinja2.Template but with some modifications. Unlike jinja2.Template which deletes the context after rendering, we cache the context in _context which allows us to access any exported variables in the template.

Also, unlike jinja2.Template, our template can also be pickled and unpickled. We use cloudpickle to handle pickling of the template’s compiled render function, since standard pickle only supports pickling functions by reference. We also support pickling modules in the template’s global namespace.

Attributes:
debug_info

The debug info mapping.

has_cached_context

Whether this template has a cached context.

is_up_to_date

If this variable is False there is a newer version available.

module

The template as module.

saved_module

Methods

compile_ctxpr(source[, undefined_to_none, ...])

Compile a ContextualExpression which can use exported variables from this template.

environment_class

export_with(*args[, save_module])

Render the template with keyword arguments and save the exported variables.

export_with_context(context[, save_module])

Render the template with injected context and save the exported variables.

from_code(environment, code, globals[, uptodate])

Creates a template object from compiled code and the globals.

from_module_dict(environment, module_dict, ...)

Creates a template object from a module.

generate(*args, **kwargs)

For very large templates it can be useful to not render the whole template at once but evaluate each statement after another and yield piece for piece.

generate_async(*args, **kwargs)

An async version of generate().

get_corresponding_lineno(lineno)

Return the source line number of a line number in the generated bytecode as they are not in sync.

make_module([vars, shared, locals])

This method works like the module attribute when called without arguments but it will evaluate the template on every call rather than caching it.

make_module_async([vars, shared, locals])

As template module creation can invoke template code for asynchronous executions this method must be used instead of the normal make_module() one.

new_context([vars, shared, locals])

Create a new Context for this template.

render(*args, **kwargs)

This method accepts the same arguments as the dict constructor: A dict, a dict subclass or some keyword arguments. If no arguments are given the context will be empty. These two calls do the same::.

render_async(*args, **kwargs)

This works similar to render() but returns a coroutine that when awaited returns the entire rendered template string.

run_get_exports(*args, **kwargs)

Compile and render the template and get exported variables.

stream(*args, **kwargs)

Works exactly like generate() but returns a TemplateStream.

USE_CLOUDPICKLE = True[source]#

If true, use cloudpickle when pickling this template’s render function.

compile_ctxpr(source: str, undefined_to_none: bool = True, update: str = 'raise_undefined')[source]#

Compile a ContextualExpression which can use exported variables from this template.

If update is 'always', the expression will always evaluate this template, and cache the context in this template’s _context attribute. The resulting exported variables are then passed to the expression.

If update is 'run_undefined', the expression will try to use cached context (i.e. from running Template.export_with()). If the context is Undefined, this template will be evaluated at expression call time.

If update is 'raise_undefined' or 'warn_undefined', calling the expression will raise an exception or warning if this template doesn’t have a cached context.

Parameters:
  • source (str) – The expression to compile.

  • undefined_to_none (bool) – If True, any Undefined values will be replaced with None.

  • update (str) – Controls if this template should be evaluated when the expression is called.

Returns:

A callable which inherits context from this template.

Return type:

ContextualExpression

Examples

>>> from swarmsim.util.jinja import make_default_jinja_env
>>> env = make_default_jinja_env()
>>> template = env.from_string("{% set foo = 'bar' %}")
>>> template.compile_ctxpr('foo', update='always')()
'bar'

You can pass variables to the parent template and expression:

>>> template = env.from_string("{% set a = b * 2 %}")
>>> template.compile_ctxpr('a + c', update='always')(b=2, c=1)
5
export_with(*args, save_module=True, **kwargs)[source]#

Render the template with keyword arguments and save the exported variables.

The results are placed in _context and saved_module attributes.

Parameters:
  • *args – Positional arguments to pass to the template.

  • save_module (bool, default=True) – If True, save the module object that was created during the render.

  • **kwargs – Keyword arguments to pass to the template. These become variables that can be accessed in the template.

Return type:

None

export_with_context(context, save_module=True)[source]#

Render the template with injected context and save the exported variables.

The results are placed in _context and saved_module attributes.

Parameters:
  • context (jinja2.runtime.Context) – A context object to run the template with.

  • save_module (bool, default=True) – If True, save the module object that was created during the render.

Return type:

None

property has_cached_context[source]#

Whether this template has a cached context.

Note: This simply checks if self._context is not Undefined.

run_get_exports(*args, **kwargs)[source]#

Compile and render the template and get exported variables.

Parameters:
  • *args – Positional arguments to pass to the template.

  • **kwargs – Keyword arguments to pass to the template. These become variables that can be accessed in the template.

Returns:

Dictionary with names and values of variables set in the template.

Return type:

dict

saved_module = None[source]#

The saved module from Template.export_with().

class swarmsim.util.jinja.ContextualExpression(template: Template, undefined_to_none: bool, parent=None, update='raise_undefined')[source]#

A callable which inherits context from a Template.

An instance of this class is returned by Template.compile_ctxpr().

This is useful if you want to set variables in a template but evaluate a single expression which uses those variables. This way, you get back a Python object rather than a rendered string from a template.

To use this, create a Template and call its Template.compile_ctxpr() method. This returns an instance of this class. Then, call the instance with the arguments you want to pass to the template.

Parameters:
  • template (Template) – The expression template.

  • undefined_to_none (bool) – If True, any Undefined values will be replaced with None.

  • parent (Template) – The template to inherit context from.

  • update (str) – How to handle undefined values. See Template.compile_ctxpr().

Examples

>>> from swarmsim.util.jinja import make_default_jinja_env
>>> env = make_default_jinja_env()
>>> template = env.from_string("{% set foo = 'bar' %}")
>>> template.compile_ctxpr('foo', update='always')()
'bar'

You can pass variables to the parent template and expression:

>>> template = env.from_string("{% set a = b * 2 %}")
>>> template.compile_ctxpr('a + c', update='always')(b=2, c=1)
5

Methods

__call__(*args, **kwargs)

Call self as a function.

class swarmsim.util.jinja.TemplateExpression(template: Template, undefined_to_none: bool)[source]#

The Environment.compile_expression() method returns an instance of this object. It encapsulates the expression-like access to the template with an expression it wraps.

Methods

__call__(*args, **kwargs)

Call self as a function.

swarmsim.util.jinja.make_default_jinja_env(*args, **kwargs)[source]#

Create a new Jinja Environment and add predefined extensions, filters, and modules to it.

Extensions:

Filters:

Modules:

Parameters:
Return type:

Environment

See also

make_template_env(), DEFAULT_EXTENSIONS, DEFAULT_EXTRA_FILTERS, DEFAULT_GLOBAL_MODULES

swarmsim.util.jinja.make_template_env(env: Environment | None = None, **kwargs)[source]#

Get a default Jinja Environment, with alternative block and variable delimiters.

Parameters:
  • env (Environment, optional) – If None, make_default_jinja_env() will be used to create the environment.

  • **kwargs – Additional keyword arguments to pass to make_default_jinja_env().

  • %> (The block delimiters are <% and)

  • %>. (i.e. <% set x = 1)

  • }> (The variable delimiters are <{ and)

  • }>. (i.e. <{ x)

  • #%> (The line statement prefix is)

  • 1. (i.e. #%> set x =)

Return type:

Environment

swarmsim.util.jinja.load_template(path, env=None, **kwargs)[source]#

Load and render a Jinja template from a file path.

Parameters:
  • path (str | os.PathLike) – The path to the template file.

  • env (Environment, optional) – The Jinja environment to use. If None, make_template_env() will be used to create an environment.

  • **kwargs – Keyword arguments to pass to the template.

Returns:

The rendered template.

Return type:

str

swarmsim.util.jinja.load_template_ctx(path, env=None, **kwargs)[source]#

Load and render a Jinja template from a file path and return the rendered template and the context.

Parameters:
  • path (str | os.PathLike) – The path to the template file.

  • env (Environment, optional) – The Jinja environment to use. If None, make_template_env() will be used to create an environment.

  • **kwargs – Keyword arguments to pass to the template.

Returns:

The rendered template and the context object.

Return type:

tuple[str, Context]

Module Attributes

DEFAULT_EXTENSIONS

The default list of extensions to load in make_default_jinja_env().

DEFAULT_EXTRA_FILTERS

The default list of filters to load in make_default_jinja_env().

DEFAULT_GLOBAL_MODULES

The default list of modules to load in make_default_jinja_env().

Functions

load_template(path[, env])

Load and render a Jinja template from a file path.

load_template_ctx(path[, env])

Load and render a Jinja template from a file path and return the rendered template and the context.

make_default_jinja_env(*args, **kwargs)

Create a new Jinja Environment and add predefined extensions, filters, and modules to it.

make_template_env([env])

Get a default Jinja Environment, with alternative block and variable delimiters.

Classes

ContextualExpression(template, undefined_to_none)

A callable which inherits context from a Template.

Environment(block_start_string, ...)

A Jinja environment.

Template(source, block_start_string, ...)

A compiled template that can be rendered.

TemplateExpression(template, undefined_to_none)

The Environment.compile_expression() method returns an instance of this object.