code: def run_step(context):
      
      logger.debug("started")
      context.assert_key_has_value(key='defaults', caller=__name__)
  
      context.set_defaults(context['defaults'])
  
      logger.info(f"set {len(context['defaults'])} context item defaults.")
  
      logger.debug("done")
docs: Set hierarchy into context with substitutions if it doesn't exist yet.
  
      context is a dictionary or dictionary-like.
      context['defaults'] must exist. It's a dictionary.
  
      Will iterate context['defaults'] and add these as new values where
      their keys don't already exist. While it's doing so, it will leave
      all other values in the existing hierarchy untouched.
  
      List merging is purely additive, with no checks for uniqueness or already
      existing list items. E.g context [0,1,2] with contextMerge=[2,3,4]
      will result in [0,1,2,2,3,4]
  
      Keep this in mind especially where complex types like
      dicts nest inside a list - a merge will always add a new dict list item,
      not merge it into whatever dicts might exist on the list already.
  
      For example, say input context is:
          key1: value1
          key2: value2
          key3:
              k31: value31
              k32: value32
          defaults:
              key2: 'aaa_{key1}_zzz'
              key3:
                  k33: value33
              key4: 'bbb_{key2}_yyy'
  
      This will result in return context:
          key1: value1
          key2: value2
          key3:
              k31: value31
              k32: value32
              k33: value33
          key4: bbb_value2_yyy