Source code for jinja2schema.mergers
# coding: utf-8
"""
jinja2schema.mergers
~~~~~~~~~~~~~~~~~~~~
"""
import itertools
from .model import Scalar, Dictionary, List, Unknown, Tuple
from .exceptions import MergeException
[docs]def merge(fst, snd):
"""Merges two variables.
:param fst: first variable
:type fst: :class:`.model.Variable`
:param snd: second variable
:type snd: :class:`.model.Variable`
.. note::
``fst`` must reflect expressions that occur in template **before** the expressions of ``snd``.
"""
assert (not (fst.linenos and snd.linenos) or
max(fst.linenos) <= min(snd.linenos))
if isinstance(fst, Unknown):
result = snd
elif isinstance(snd, Unknown):
result = fst
elif isinstance(fst, Scalar) and isinstance(snd, Scalar):
fst_type = type(fst)
snd_type = type(snd)
if issubclass(fst_type, snd_type):
result = fst_type()
elif issubclass(snd_type, fst_type):
result = snd_type()
else:
raise MergeException(fst, snd)
elif isinstance(fst, Dictionary) and isinstance(snd, Dictionary):
result = Dictionary()
for k in set(itertools.chain(fst.iterkeys(), snd.iterkeys())):
if k in fst and k in snd:
result[k] = merge(fst[k], snd[k])
elif k in fst:
result[k] = fst[k]
elif k in snd:
result[k] = snd[k]
elif isinstance(fst, List) and isinstance(snd, List):
result = List(merge(fst.item, snd.item))
elif isinstance(fst, Tuple) and isinstance(snd, Tuple):
if fst.items is snd.items is None:
result = Tuple(None)
else:
if len(fst.items) != len(snd.items):
raise MergeException(fst, snd)
result = Tuple([merge(a, b) for a, b in zip(fst.items, snd.items)])
else:
raise MergeException(fst, snd)
result.label = fst.label or snd.label
result.linenos = list(sorted(set(fst.linenos + snd.linenos)))
result.constant = fst.constant
result.may_be_defined = fst.may_be_defined
result.used_with_default = fst.used_with_default and snd.used_with_default
return result
def merge_rtypes(fst, snd, operator=None):
if operator in ('+', '-'):
if type(fst) is not type(snd) and not (isinstance(fst, Unknown) or isinstance(snd, Unknown)):
raise MergeException(fst, snd)
return merge(fst, snd)