<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def InterpolateKbAttributes(pattern, knowledge_base, ignore_errors=False):
 """Interpolate all knowledgebase attributes in pattern. Args: pattern: A string with potential interpolation markers. For example: "/home/%%users.username%%/Downloads/" knowledge_base: The knowledge_base to interpolate parameters from. ignore_errors: Set this to true to log errors instead of raising. Raises: KnowledgeBaseInterpolationError: If there are any interpolation problems and the `ignore_errors` flag is not set. Yields: All unique strings generated by expanding the pattern. """

  # TODO(hanuszczak): Control flow feels a bit awkward here because of error
  # handling that tries not to break any functionality. With the new utilities
  # it should be possible to improve the code, changing the behaviour to a more
  # sane one.
  missing_attr_names = set()

  interpolator = interpolation.Interpolator(pattern)

  for vid in interpolator.Vars():
    attr_name = str(vid).lower()

    value = getattr(knowledge_base, attr_name, None)
    if not value:
      missing_attr_names.add(attr_name)
      continue

    interpolator.BindVar(attr_name, value)

  for scope_id in interpolator.Scopes():
    scope_name = str(scope_id).lower()

    kb_structs = getattr(knowledge_base, scope_name, None)
    if not kb_structs:
      missing_attr_names.add(scope_name)
      continue

    bound = False

    for kb_struct in kb_structs:
      bindings = {}

      for var_id in interpolator.ScopeVars(scope_id):
        attr_name = str(var_id).lower()

        value = getattr(kb_struct, attr_name, None)
        if value:
          bindings[var_id] = value

      if len(bindings) == len(interpolator.ScopeVars(scope_id)):
        interpolator.BindScope(scope_id, bindings)
        bound = True

    if not bound:
      missing_attr_names.add(scope_name)

  if missing_attr_names:
    message = "Some attributes could not be located in the knowledgebase: {}"
    message = message.format(", ".join(missing_attr_names))
    if not ignore_errors:
      raise KnowledgeBaseInterpolationError(message)
    else:
      logging.error(message)
      return

  for result in interpolator.Interpolate():
    yield result