Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
substitutions made on x. If input_string was a single expression
(e.g '{field}'), then returns the object with {substitutions} made
for its attributes.
Raises:
KeyNotInContextError: input_string is not a sic string and has
{somekey} where somekey does not exist in
context dictionary.
"""
# arguably, this doesn't really belong here, or at least it makes a
# nonsense of the function name. given how py and strings
# look and feel pretty much like strings from user's perspective, and
# given legacy code back when sic strings were in fact just strings,
# keep in here for backwards compatibility.
if isinstance(input_string, SpecialTagDirective):
return input_string.get_value(self)
else:
# is this a special one field formatstring? i.e "{field}", with
# nothing else?
out = None
is_out_set = False
expr_count = 0
# parse finds field format expressions and/or literals in input
for expression in formatter.parse(input_string):
# parse tuple:
# (literal_text, field_name, format_spec, conversion)
# it's a single '{field}' if no literal_text but field_name
# no literal, field name exists, and no previous expr found
if (not expression[0] and expression[1] and not expr_count):
# get_field tuple: (obj, used_key)
out = formatter.get_field(expression[1], None, self)[0]
"""
yaml_tag = '!py'
def get_value(self, context):
"""Run python eval on the input string."""
if self.value:
return expressions.eval_string(self.value, context)
else:
# Empty input raises cryptic EOF syntax err, this more human
# friendly
raise ValueError('!py string expression is empty. It must be a '
'valid python expression instead.')
class SicString(SpecialTagDirective):
"""Sic strings do not have any processing applied to them.
If a string is NOT to have {substitutions} run on it, it's sic erat
scriptum, i.e literal.
A sic string looks like this:
input_string=!sic <>
For example:
!sic piping {key} the valleys wild
Will return "piping {key} the valleys wild" without attempting to
substitute {key} from context.
"""
"""Walk the current context tree in recursive inner function.
On 1st iteration, current = self (i.e root of context)
On subsequent recursive iterations, current is wherever you're at
in the nested context hierarchy.
Args:
current: dict. Destination of merge.
add_me: dict. Merge this to current.
"""
for k, v in add_me.items():
# key supports interpolation
k = self.get_formatted_string(k)
# str not mergable, so it doesn't matter if it exists in dest
if isinstance(v, (str, SpecialTagDirective)):
# just overwrite dest - str adds/edits indiscriminately
current[k] = self.get_formatted_string(v)
elif isinstance(v, (bytes, bytearray)):
# bytes aren't mergable or formattable
# only here to prevent the elif on enumerables catching it
current[k] = v
# deal with things that are mergable - exists already in dest
elif k in current:
if types.are_all_this_type(Mapping, current[k], v):
# it's dict-y, thus recurse through it to merge since
# it exists in dest
merge_recurse(current[k], v)
elif types.are_all_this_type(list, current[k], v):
# it's list-y. Extend mutates existing list since it
# exists in dest
current[k].extend(
def get_value(self, context=None):
"""Process the input value and return the output.
Derived classes must provide an implementation for this method.
This method is called by the various context get_formatted functions,
where each special tag has its own processing rules about how to format
values for that particular tag.
"""
raise NotImplementedError(
'Implement this to provide the processed value of your custom tag '
'during formatting operations.')
class PyString(SpecialTagDirective):
"""py strings allow you to execute python expressions dynamically.
A py string is defined by custom yaml tag like this:
!py <<>>
For example:
!py key == 3
Will return True if context['key'] is 3.
This provides dynamic python eval of an input expression. The return is
whatever the result of the expression is.
Use with caution: since input_string executes any arbitrary code object
the potential for damage is great.