Source code for jinja2schema.model

# coding: utf-8
"""
jinja2schema.model
~~~~~~~~~~~~~~~~~~
"""
import pprint

from jinja2 import nodes

from . import _compat


[docs]class Variable(object): """A base variable class. .. attribute:: linenos An ordered list of line numbers on which the variable occurs. .. attribute:: label A name of the variable in template. .. attribute:: constant Is true if the variable is defined using a ``{% set %}`` tag before used in the template. .. attribute:: 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 %} .. attribute:: used_with_default Is true if the variable occurs **only** within the ``default`` filter. """ def __init__(self, label=None, linenos=None, constant=False, may_be_defined=False, used_with_default=False): self.label = label self.linenos = linenos if linenos is not None else [] self.constant = constant self.may_be_defined = may_be_defined self.used_with_default = used_with_default def clone(self): cls = type(self) return cls(**self.__dict__) @classmethod def _get_kwargs_from_ast(cls, ast): if isinstance(ast, nodes.Name): label = ast.name else: label = None rv = { 'linenos': [ast.lineno], 'label': label, } return rv @classmethod
[docs] def from_ast(cls, ast, **kwargs): """Constructs a variable extracting information from ``ast`` (such as label and line numbers). :param ast: AST node :type ast: :class:`jinja2.nodes.Node` """ for k, v in kwargs.items(): if v is None: del kwargs[k] kwargs = dict(cls._get_kwargs_from_ast(ast), **kwargs) return cls(**kwargs)
@property def required(self): return not self.may_be_defined and not self.used_with_default def __eq__(self, other): return ( type(self) is type(other) and self.constant == other.constant and self.used_with_default == other.used_with_default and self.required == other.required and self.linenos == other.linenos and self.label == other.label ) def __ne__(self, other): return not self.__eq__(other)
[docs] def to_json_schema(self): """Returns JSON schema of the variable. :rtype: :class:`dict` """ rv = {} if self.label: rv['title'] = self.label return rv
[docs]class Dictionary(Variable): """A dictionary. Implements some methods of Python :class:`dict`. .. automethod:: __setitem__ .. automethod:: __getitem__ .. automethod:: __delitem__ .. automethod:: get .. automethod:: items .. automethod:: iteritems .. automethod:: keys .. automethod:: iterkeys .. automethod:: pop """ def __init__(self, data=None, **kwargs): self.data = data or {} super(Dictionary, self).__init__(**kwargs) def __eq__(self, other): return super(Dictionary, self).__eq__(other) and self.data == other.data def __repr__(self): return pprint.pformat(self.data) def clone(self): rv = super(Dictionary, self).clone() rv.data = {} for k, v in _compat.iteritems(self.data): rv.data[k] = v.clone() return rv @classmethod def from_ast(cls, ast, data=None, **kwargs): kwargs = dict(cls._get_kwargs_from_ast(ast), **kwargs) return cls(data, **kwargs)
[docs] def __setitem__(self, key, value): self.data[key] = value
[docs] def __getitem__(self, key): return self.data[key]
[docs] def __delitem__(self, key): del self.data[key]
def __contains__(self, key): return key in self.data
[docs] def get(self, name, default=None): if name in self: return self[name] else: return default
[docs] def items(self): return self.data.items()
[docs] def iteritems(self): return _compat.iteritems(self.data)
[docs] def keys(self): return self.data.keys()
[docs] def iterkeys(self): return _compat.iterkeys(self.data)
[docs] def pop(self, key, default=None): return self.data.pop(key, default)
def to_json_schema(self): rv = super(Dictionary, self).to_json_schema() rv.update({ 'type': 'object', 'properties': dict((k, v.to_json_schema()) for k, v in self.iteritems()), 'required': [k for k, v in self.iteritems() if v.required], }) return rv
[docs]class List(Variable): """A list which items are of the same type. .. attribute:: item A structure of list items, subclass of :class:`Variable`. """ def __init__(self, item, **kwargs): self.item = item super(List, self).__init__(**kwargs) def __eq__(self, other): return super(List, self).__eq__(other) and self.item == other.item def __repr__(self): return pprint.pformat([self.item]) def clone(self): rv = super(List, self).clone() rv.item = self.item.clone() return rv @classmethod def from_ast(cls, ast, item, **kwargs): kwargs = dict(cls._get_kwargs_from_ast(ast), **kwargs) return cls(item, **kwargs) def to_json_schema(self): rv = super(List, self).to_json_schema() rv.update({ 'type': 'array', 'items': self.item.to_json_schema(), }) return rv
[docs]class Tuple(Variable): """A tuple. .. attribute:: items A :class:`tuple` of :class:`Variable` instances or ``None`` if the tuple items are unknown. """ def __init__(self, items, **kwargs): self.items = tuple(items) if items is not None else None super(Tuple, self).__init__(**kwargs) def __eq__(self, other): return super(Tuple, self).__eq__(other) and self.items == other.items def __repr__(self): return pprint.pformat(self.items) def clone(self): rv = super(Tuple, self).clone() rv.items = tuple(s.clone() for s in self.items) return rv @classmethod def from_ast(cls, ast, items, **kwargs): kwargs = dict(cls._get_kwargs_from_ast(ast), **kwargs) return cls(items, **kwargs) def to_json_schema(self): rv = super(Tuple, self).to_json_schema() rv.update({ 'type': 'array', 'items': [item.to_json_schema() for item in self.items], }) return rv
[docs]class Scalar(Variable): """A scalar. Either string, number, boolean or ``None``.""" def __repr__(self): return '<scalar>' def to_json_schema(self): rv = super(Scalar, self).to_json_schema() rv['anyOf'] = [ {'type': 'boolean'}, {'type': 'null'}, {'type': 'number'}, {'type': 'string'}, ] return rv
[docs]class String(Scalar): """A string.""" def __repr__(self): return '<string>' def to_json_schema(self): rv = Variable.to_json_schema(self) rv['type'] = 'string' return rv
[docs]class Number(Scalar): """A number.""" def __repr__(self): return '<number>' def to_json_schema(self): rv = Variable.to_json_schema(self) rv['type'] = 'number' return rv
[docs]class Boolean(Scalar): """A number.""" def __repr__(self): return '<boolean>' def to_json_schema(self): rv = Variable.to_json_schema(self) rv['type'] = 'boolean' return rv
[docs]class Unknown(Variable): """A variable which type is unknown.""" def __repr__(self): return '<unknown>' def to_json_schema(self): rv = super(Unknown, self).to_json_schema() rv['anyOf'] = [ {'type': 'object'}, {'type': 'array'}, {'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}, ] return rv