Package pyxb :: Package utils :: Module templates |
[hide private]
[frames] | no frames]

# Source Code for Module pyxb.utils.templates

      1  # -*- coding: utf-8 -*-
      2  # Copyright 2009-2013, Peter A. Bigot
      3  #
      4  # Licensed under the Apache License, Version 2.0 (the "License"); you may
      5  # not use this file except in compliance with the License. You may obtain a
      6  # copy of the License at:
      7  #
      8  #            http://www.apache.org/licenses/LICENSE-2.0
      9  #
     10  # Unless required by applicable law or agreed to in writing, software
     11  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     12  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  # License for the specific language governing permissions and limitations
     14  # under the License.
     15
     16  """Functions that aid with generating text from templates and maps."""
     17
     18  import re
     19
     20  # POSIX shell variable syntax:
     21  #  Expansions with unset var
     22  #  ${var}=
     23  #  ${var+WORD}=
     24  #  ${var:+WORD}=
     25  #  ${var-WORD}=WORD
     26  #  ${var:-WORD}=WORD
     27  #  Expansions with empty var
     28  #  ${var}=
     29  #  ${var+WORD}=WORD
     30  #  ${var:+WORD}=
     31  #  ${var-WORD}=
     32  #  ${var:-WORD}=WORD
     33  #  Expansions with var=SET
     34  #  ${var}=SET
     35  #  ${var+WORD}=WORD
     36  #  ${var:+WORD}=WORD
     37  #  ${var-WORD}=SET
     38  #  ${var:-WORD}=SET
     39
     40  # This expression replaces markers in template text with the value
     41  # obtained by looking up the marker in a dictionary.
     42  # %{id} = value
     43  _substIdPattern = re.compile("%{(?P<id>\w+)}")
     44
     45  # This expression performs conditional substitution: if the expression
     46  # provided evaluates to true in a given context, then one value is
     47  # substituted, otherwise the alternative value is substituted.
     48  # %{?<cond>??<true>?:<false>?}
     49  # %{?1 == 2??true?:false?}
     50  _substConditionalPattern = re.compile("%{\?(?P<expr>.+?)\?\?(?P<true>.*?)(\?:(?P<false>.*?))?\?}", re.MULTILINE + re.DOTALL)
     51
     52  # This expression tests whether an identifier is defined to a non-None
     53  # value in the context; if so, it replaces the marker with template
     54  # text.  In that replacement text, the value ?@ is replaced by the
     55  # test expression.  Contrast POSIX shell ${ID+subst}${ID-subst}
     56  # Note: NOT by the value of the test expression.  If no replacement
     57  # text is given, the replacement '%{?@}' is used, which replaces it
     58  # with the value of the test expression.
     59  # %{?<id>?+<yessubst>?-?<nosubst>}}
     60  # %{?maybe_text?+?@ is defined to be %{?@}?}
     61  _substIfDefinedPattern = re.compile("%{\?(?P<id>\w+)(\?\+(?P<repl>.*?))?(\?\-(?P<ndrepl>.*?))?\?}", re.MULTILINE + re.DOTALL)
     62
     63  # The pattern which, if present in the body of a IfDefined block, is
     64  # replaced by the test expression.
     65  _substDefinedBodyPattern = re.compile("\?@")
     66
     67 -def _bodyIfDefinedPattern (match_object, dictionary):
     68      global _substDefinedBodyPattern
     69      id = match_object.group('id')
     70      repl = match_object.group('repl')
     71      ndrepl = match_object.group('ndrepl')
     72      value = dictionary.get(id)
     73      if value is not None:
     74          if repl:
     75              return _substDefinedBodyPattern.sub(id, repl)
     76          if ndrepl:
     77              return ''
     78          return _substDefinedBodyPattern.sub(id, '%{?@}')
     79      else:
     80          if ndrepl:
     81              return _substDefinedBodyPattern.sub(id, ndrepl)
     82          return ''
     83
     84 -def _bodyConditionalPattern (match_object, dictionary):
     85      global _substDefinedBodyPattern
     86      expr = match_object.group('expr')
     87      true = match_object.group('true')
     88      false = match_object.group('false')
     89      value = None
     90      try:
     91          value = eval(expr, dictionary)
     92      except Exception as e:
     93          return '%%{EXCEPTION: %s}' % (e,)
     94      if value:
     95          return _substDefinedBodyPattern.sub(expr, true)
     96      if false is not None:
     97          return _substDefinedBodyPattern.sub(expr, false)
     98      return ''
     99
    100 -def replaceInText (text, **dictionary):
    101      global _substIfDefinedPattern
    102      global _substConditionalPattern
    103      global _substIdPattern
    104      global _substDefinedBodyPattern
    105      rv = text
    106      rv = _substIfDefinedPattern.sub(lambda _x: _bodyIfDefinedPattern(_x, dictionary), rv)
    107      rv = _substConditionalPattern.sub(lambda _x: _bodyConditionalPattern(_x, dictionary), rv)
    108      rv =  _substIdPattern.sub(
    109          lambda _x,_map=dictionary:
    110             _map.get(_x.group('id'), '%%{MISSING:%s}' % (_x.group('id'),))
    111          , rv)
    112      return rv
    113