def _is_template(template_str): template_str = to_unicode(template_str) template = Template(template_str) try: return template_str != template.render({}) except exceptions.UndefinedError: return True
def _process(G, name, value): ''' Determines whether parameter is a template or a value. Adds graph nodes and edges accordingly. ''' # Jinja defaults to ascii parser in python 2.x unless you set utf-8 support on per module level # Instead we're just assuming every string to be a unicode string if isinstance(value, str): value = to_unicode(value) complex_value_str = None if isinstance(value, list) or isinstance(value, dict): complex_value_str = str(value) is_jinja_expr = (jinja_utils.is_jinja_expression(value) or jinja_utils.is_jinja_expression(complex_value_str)) if is_jinja_expr: G.add_node(name, template=value) template_ast = ENV.parse(value) LOG.debug('Template ast: %s', template_ast) # Dependencies of the node represent jinja variables used in the template # We're connecting nodes with an edge for every depencency to traverse them # in the right order and also make sure that we don't have missing or cyclic # dependencies upfront. dependencies = meta.find_undeclared_variables(template_ast) LOG.debug('Dependencies: %s', dependencies) if dependencies: for dependency in dependencies: G.add_edge(dependency, name) else: G.add_node(name, value=value)
def render_values(mapping=None, context=None, allow_undefined=False): """ Render an incoming mapping using context provided in context using Jinja2. Returns a dict containing rendered mapping. :param mapping: Input as a dictionary of key value pairs. :type mapping: ``dict`` :param context: Context to be used for dictionary. :type context: ``dict`` :rtype: ``dict`` """ if not context or not mapping: return mapping # Add in special __context variable that provides an easy way to get access to entire context. # This mean __context is a reserve key word although backwards compat is preserved by making # sure that real context is updated later and therefore will override the __context value. super_context = {} super_context['__context'] = context super_context.update(context) env = get_jinja_environment(allow_undefined=allow_undefined) rendered_mapping = {} for k, v in six.iteritems(mapping): # jinja2 works with string so transform list and dict to strings. reverse_json_dumps = False if isinstance(v, dict) or isinstance(v, list): v = json.dumps(v) reverse_json_dumps = True else: # Special case for text type to handle unicode if isinstance(v, six.string_types): v = to_unicode(v) else: # Other types (e.g. boolean, etc.) v = str(v) try: LOG.info('Rendering string %s. Super context=%s', v, super_context) rendered_v = env.from_string(v).render(super_context) except Exception as e: # Attach key and value which failed the rendering e.key = k e.value = v raise e # no change therefore no templatization so pick params from original to retain # original type if rendered_v == v: rendered_mapping[k] = mapping[k] continue if reverse_json_dumps: rendered_v = json.loads(rendered_v) rendered_mapping[k] = rendered_v LOG.info('Mapping: %s, rendered_mapping: %s, context: %s', mapping, rendered_mapping, context) return rendered_mapping
def _process(G, name, value): ''' Determines whether parameter is a template or a value. Adds graph nodes and edges accordingly. ''' # Jinja defaults to ascii parser in python 2.x unless you set utf-8 support on per module level # Instead we're just assuming every string to be a unicode string if isinstance(value, str): value = to_unicode(value) complex_value_str = None if isinstance(value, list) or isinstance(value, dict): complex_value_str = str(value) is_jinja_expr = ( jinja_utils.is_jinja_expression(value) or jinja_utils.is_jinja_expression( complex_value_str ) ) if is_jinja_expr: G.add_node(name, template=value) template_ast = ENV.parse(value) LOG.debug('Template ast: %s', template_ast) # Dependencies of the node represent jinja variables used in the template # We're connecting nodes with an edge for every depencency to traverse them # in the right order and also make sure that we don't have missing or cyclic # dependencies upfront. dependencies = meta.find_undeclared_variables(template_ast) LOG.debug('Dependencies: %s', dependencies) if dependencies: for dependency in dependencies: G.add_edge(dependency, name) else: G.add_node(name, value=value)
def _cast_string(x): if x is None: # Preserve None as-is return x if not isinstance(x, six.string_types): value_type = type(x).__name__ msg = 'Value "%s" must either be a string or None. Got "%s".' % (x, value_type) raise ValueError(msg) x = to_unicode(x) x = _cast_none(x) return x
def _process(G, name, value): ''' Determines whether parameter is a template or a value. Adds graph nodes and edges accordingly. ''' # Jinja defaults to ascii parser in python 2.x unless you set utf-8 support on per module level # Instead we're just assuming every string to be a unicode string if isinstance(value, str): value = to_unicode(value) template_ast = ENV.parse(value) # Dependencies of the node represent jinja variables used in the template # We're connecting nodes with an edge for every depencency to traverse them in the right order # and also make sure that we don't have missing or cyclic dependencies upfront. dependencies = meta.find_undeclared_variables(template_ast) if dependencies: G.add_node(name, template=value) for dependency in dependencies: G.add_edge(dependency, name) else: G.add_node(name, value=value)
def _cast_string(x): x = to_unicode(x) x = _cast_none(x) return x