def IterFunction(self, client, out_queue, unused_token):
    result = {}
    for attr in self.report_attrs:
      # Do some special formatting for certain fields.
      if attr.name == "subject":
        result[attr.name] = client.Get(attr).Basename()
      elif attr.name == "GRR client":
        c_info = client.Get(attr)
        if not c_info:
          self.broken_subjects.append(client.client_id)
          result[attr.name] = None
          continue

        result[attr.name] = "%s %s" % (c_info.client_name,
                                       str(c_info.client_version))
      else:
        result[attr.name] = client.Get(attr)

    for sub_path, attr in self.extended_report_attrs:
      try:
        client_sub = client.OpenMember(sub_path)
        # TODO(user): Update this to use MultiOpen.
      except IOError:
        # If the path is not found, just continue.
        continue
      # Special case formatting for some attributes.
      if attr.name == "Interfaces":
        interfaces = client_sub.Get(attr)
        if interfaces:
          try:
            result[attr.name] = ",".join(interfaces.GetIPAddresses())
          except AttributeError:
            result[attr.name] = ""
      else:
        result[attr.name] = client_sub.Get(attr)

    out_queue.put(result)
Dynamic attribute access.
dataset/ETHPy150Open google/grr/grr/lib/aff4_objects/reports.py/ClientReportIterator.IterFunction--crossover with--dataset/ETHPy150Open CollabQ/CollabQ/.google_appengine/google/appengine/api/lib_config.py/ConfigHandle.__getattr__