docs: def apply_parameters(self, parameters):
          """Recursively apply dictionary entries in 'parameters' to {item}s in recipe
          structure, leaving undefined {item}s as they are. A special case is a
          {$REPLACE:item}, which replaces the string with a copy of the referenced
          parameter item.
  
          Examples:
  
          parameters = { 'x':'5' }
          apply_parameters( { '{x}': '{y}' }, parameters )
             => { '5': '{y}' }
  
          parameters = { 'y':'5' }
          apply_parameters( { '{x}': '{y}' }, parameters )
             => { '{x}': '5' }
  
          parameters = { 'x':'3', 'y':'5' }
          apply_parameters( { '{x}': '{y}' }, parameters )
             => { '3': '5' }
  
          parameters = { 'l': [ 1, 2 ] }
          apply_parameters( { 'x': '{$REPLACE:l}' }, parameters )
             => { 'x': [ 1, 2 ] }
          """
  
          class SafeString(object):
              def __init__(self, s):
                  self.string = s
  
              def __repr__(self):
                  return "{" + self.string + "}"
  
              def __str__(self):
                  return "{" + self.string + "}"
  
              def __getitem__(self, item):
                  return SafeString(self.string + "[" + item + "]")
  
          class SafeDict(dict):
              """A dictionary that returns undefined keys as {keyname}.
              This can be used to selectively replace variables in datastructures."""
  
              def __missing__(self, key):
                  return SafeString(key)
  
          # By default the python formatter class is used to resolve {item} references
          formatter = string.Formatter()
  
          # Special format strings "{$REPLACE:(...)}" use this data structure
          # formatter to return the referenced data structure rather than a formatted
          # string.
          ds_formatter = string.Formatter()
  
          def ds_format_field(value, spec):
              ds_format_field.last = value
              return ""
  
          ds_formatter.format_field = ds_format_field
  
          params = SafeDict(parameters)
  
          def _recursive_apply(item):
              """Helper function to recursively apply replacements."""
              if isinstance(item, basestring):
                  if item.startswith("{$REPLACE") and item.endswith("}"):
                      try:
                          ds_formatter.vformat("{" + item[10:-1] + "}", (), parameters)
                      except KeyError:
                          return None
                      return copy.deepcopy(ds_formatter.format_field.last)
                  else:
                      return formatter.vformat(item, (), params)
              if isinstance(item, dict):
                  return {
                      _recursive_apply(key): _recursive_apply(value)
                      for key, value in item.items()
                  }
              if isinstance(item, tuple):
                  return tuple(_recursive_apply(list(item)))
              if isinstance(item, list):
                  return [_recursive_apply(x) for x in item]
              return item
  
          self.recipe = _recursive_apply(self.recipe)