jinja2schema.core

jinja2schema.core.parse(template, jinja2_env=None)[source]

Parses Jinja2 template and returns it’s AST.

Return type:jinja2.nodes.Template
jinja2schema.core.infer_from_ast(ast, ignore_constants=True, config=<jinja2schema.config.Config object at 0x7fd2fbf28850>)[source]

Returns a model.Dictionary which reflects a structure of variables used within ast.

Parameters:
  • ast (jinja2.nodes.Node) – AST
  • ignore_constants – excludes constant variables from a resulting structure
  • config (config.Config) – a config
Return type:

model.Dictionary

Raises:

exceptions.MergeException, exceptions.InvalidExpression, exceptions.UnexpectedExpression

jinja2schema.core.infer(template, config=<jinja2schema.config.Config object at 0x7fd2fbf288d0>)[source]

Returns a model.Dictionary which reflects a structure of the context required by template.

Parameters:
  • template (string) – a template
  • config (config.Config) – a config
Return type:

model.Dictionary

Raises:

exceptions.MergeException, exceptions.InvalidExpression, exceptions.UnexpectedExpression

jinja2schema.config

class jinja2schema.config.Config[source]

Configuration.

TYPE_OF_VARIABLE_INDEXED_WITH_VARIABLE_TYPE = 'dictionary'

Possible values: "dictionary" or "list"".

For example, in the expression xs[a] variable xs may be a list as well as a dictionary. This setting is used to choose between a dictionary and a list when the variable is being indexed with another variable.

TYPE_OF_VARIABLE_INDEXED_WITH_INTEGER_TYPE = 'list'

Possible values: "dictionary" or "list"".

For example, in the expression xs[2] variable xs may be a list as well as a dictionary. This setting is used to choose between a dictionary and a list when the variable is being indexed with an integer.

ALLOW_ONLY_BOOLEAN_VARIABLES_IN_TEST = False

Whether or not to consider conditions in if statements as boolean.

If this variable is not set, xs variable in template {% if xs %}{% endif %} will have unknown structure. If this variable is set, xs will be a boolean.

jinja2schema.model

class jinja2schema.model.Variable(label=None, linenos=None, constant=False, may_be_defined=False, used_with_default=False)[source]

A base variable class.

linenos

An ordered list of line numbers on which the variable occurs.

label

A name of the variable in template.

constant

Is true if the variable is defined using a {% set %} tag before used in the template.

may_be_defined

Is true if the variable would be defined (using a {% set %} expression) if it is missing from the template context. For example, x is may_be_defined in the following template:

{% if x is undefined %} {% set x = 1 %} {% endif %}
used_with_default

Is true if the variable occurs only within the default filter.

classmethod from_ast(ast, **kwargs)[source]

Constructs a variable extracting information from ast (such as label and line numbers).

Parameters:ast (jinja2.nodes.Node) – AST node
to_json_schema()[source]

Returns JSON schema of the variable.

Return type:dict
class jinja2schema.model.Dictionary(data=None, **kwargs)[source]

A dictionary.

Implements some methods of Python dict.

__setitem__(key, value)[source]
__getitem__(key)[source]
__delitem__(key)[source]
get(name, default=None)[source]
items()[source]
iteritems()[source]
keys()[source]
iterkeys()[source]
pop(key, default=None)[source]
class jinja2schema.model.List(item, **kwargs)[source]

A list which items are of the same type.

item

A structure of list items, subclass of Variable.

class jinja2schema.model.Tuple(items, **kwargs)[source]

A tuple.

items

A tuple of Variable instances or None if the tuple items are unknown.

class jinja2schema.model.Scalar(label=None, linenos=None, constant=False, may_be_defined=False, used_with_default=False)[source]

A scalar. Either string, number, boolean or None.

class jinja2schema.model.String(label=None, linenos=None, constant=False, may_be_defined=False, used_with_default=False)[source]

A string.

class jinja2schema.model.Number(label=None, linenos=None, constant=False, may_be_defined=False, used_with_default=False)[source]

A number.

class jinja2schema.model.Boolean(label=None, linenos=None, constant=False, may_be_defined=False, used_with_default=False)[source]

A number.

class jinja2schema.model.Unknown(label=None, linenos=None, constant=False, may_be_defined=False, used_with_default=False)[source]

A variable which type is unknown.

jinja2schema.mergers

jinja2schema.mergers.merge(fst, snd)[source]

Merges two variables.

Parameters:

Note

fst must reflect expressions that occur in template before the expressions of snd.

jinja2schema.exceptions

exception jinja2schema.exceptions.InferException[source]

Base class for jinja2schema exceptions.

exception jinja2schema.exceptions.MergeException(fst, snd)[source]

Conflict of merging two structures.

fst

Variable

snd

Variable

exception jinja2schema.exceptions.UnexpectedExpression(expected_struct, actual_ast, actual_struct)[source]

Raised when a visitor was expecting compatibility with expected_struct, but got actual_ast of structure actual_struct.

Compatibility is checked by merging expected structure with actual one.

expected_struct

expected model.Variable

actual_ast

actual jinja2.nodes.Node

actual_ast

model.Variable described by actual_ast

exception jinja2schema.exceptions.InvalidExpression(ast, message)[source]

Raised when a template uses Jinja2 features that are not supported by the library or when a template contains incorrect expressions (i.e., such as applying divisibleby filter without an argument).

ast

jinja2.nodes.Node caused the exception

jinja2schema.util

jinja2schema.util.debug_repr(var)[source]
Parameters:var – instance of Variable
Returns:a string with detailed representation of var

jinja2schema.visitors.stmt

Statement is an instance of jinja2.nodes.Stmt. Statement visitors return models.Dictionary of structures of variables used within the statement.

jinja2schema.visitors.stmt.visits_stmt(node_cls)[source]

Decorator that registers a function as a visitor for node_cls.

Parameters:node_cls – subclass of jinja2.nodes.Stmt
jinja2schema.visitors.stmt.visit_stmt(ast, config)[source]

Returns a structure of ast.

Parameters:ast – instance of jinja2.nodes.Stmt
Returns:model.Dictionary
jinja2schema.visitors.stmt.visit_for(ast, config)[source]
jinja2schema.visitors.stmt.visit_if(ast, config)[source]
jinja2schema.visitors.stmt.visit_assign(ast, config)[source]
jinja2schema.visitors.stmt.visit_output(ast, config)[source]

jinja2schema.visitors.expr

Expression is an instance of jinja2.nodes.Expr. Expression visitors return a tuple which contains expression type and expression structure.

class jinja2schema.visitors.expr.Context(ctx=None, return_struct_cls=None, predicted_struct=None)[source]

Context is used when parsing expressions.

Suppose there is an expression:

{{ data.field.subfield }}

It has the following AST:

Getattr(
    node=Getattr(
        node=Name(name='data')
        attr='field'
    ),
    attr='subfield'
)

visit_getattr() returns a pair that looks like this:

(
    # return type:
    Scalar(...),
    # structure:
    {
        'data: {
            'field': {
                'subfield': Scalar(...)
            }
        }
    }
}

The return type is defined by the outermost nodes.Getattr node, which in this case is being printed. The structure is build during AST traversal from outer to inners nodes and it is kind of “reversed” in relation to the AST. Context is intended for:

  • capturing a return type and passing it to the innermost expression node;
  • passing a structure “under construction” to the visitors of nested nodes.

Let’s look through an example.

Suppose visit_getattr() is called with the following arguments:

ast = Getattr(node=Getattr(node=Name(name='data'), attr='field'), attr='subfield'))
context = Context(return_struct_cls=Scalar, predicted_struct=Scalar())

It looks to the outermost AST node and based on it’s type (which is nodes.Getattr) and it’s attr field (which equals to "subfield") infers that a variable described by the nested AST node must a dictionary with "subfield" key.

It calls a visitor for inner node and visit_getattr() gets called again, but with different arguments:

ast = Getattr(node=Name(name='data', ctx='load'), attr='field')
ctx = Context(return_struct_cls=Scalar, predicted_struct=Dictionary({subfield: Scalar()}))

visit_getattr() applies the same logic again. The inner node is a nodes.Name, so that it calls visit_name() with the following arguments:

ast = Name(name='data')
ctx = Context(
    return_struct_cls=Scalar,
    predicted_struct=Dictionary({
        field: Dictionary({subfield: Scalar()}))
    })
)

visit_name() does not do much by itself. Based on a context it knows what structure and what type must have a variable described by a given nodes.Name node, so it just returns a pair:

(instance of context.return_struct_cls, Dictionary({data: context.predicted_struct}})
get_predicted_struct(label=None)[source]
meet(actual_struct, actual_ast)[source]
jinja2schema.visitors.expr.visits_expr(node_cls)[source]

Decorator that registers a function as a visitor for node_cls.

Parameters:node_cls – subclass of jinja2.nodes.Expr
jinja2schema.visitors.expr.visit_expr(ast, ctx, config)[source]

Returns a structure of ast.

Parameters:
  • ctxContext
  • ast – instance of jinja2.nodes.Expr
Returns:

a tuple where the first element is an expression type (instance of Variable) and the second element is an expression structure (instance of model.Dictionary)

jinja2schema.visitors.expr.visit_bin_expr(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_unary_expr(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_compare(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_slice(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_name(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_getattr(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_getitem(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_test(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_concat(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_cond_expr(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_call(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_filter(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_template_data(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_const(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_tuple(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_list(ast, ctx, config)[source]
jinja2schema.visitors.expr.visit_dict(ast, ctx, config)[source]

jinja2schema.visitors.util

jinja2schema.visitors.util.visit_many(nodes, config, predicted_struct_cls=<class 'jinja2schema.model.Scalar'>, return_struct_cls=<class 'jinja2schema.model.Unknown'>)[source]

Visits nodes and merges results.

Parameters:
  • nodes – list of jinja2.nodes.Node
  • predicted_struct_clspredicted_struct for expression visitors will be constructed using this class by calling from_ast() method
Returns:

Dictionary