@gen.coroutine
def QueryContacts(client, obj_store, user_id, device_id, request):
  """Queries contacts for the current user.
  Note: This does not remove duplicate contact entries.  This isn't practical because multiple
  contacts with the same contact_id may be present across multiple range query results.  Multiple
  contacts with the same contact_id should be very uncommon, but are possible.  Because older
  contact rows are returned first, the client may assume the last contact with the same contact_id
  is the correct one."""
  def _MakeContactDict(contact):
    """Makes a dict for JSON output from the contact."""
    c_dict = {'contact_id': contact.contact_id,
              'contact_source': contact.contact_source}
    util.SetIfNotNone(c_dict, 'name', contact.name)
    util.SetIfNotNone(c_dict, 'given_name', contact.given_name)
    util.SetIfNotNone(c_dict, 'family_name', contact.family_name)
    util.SetIfNotNone(c_dict, 'rank', contact.rank)
    if contact.labels is not None and len(contact.labels) > 0:
      c_dict['labels'] = list(contact.labels)
    identities_list = []
    if contact.identities_properties is not None:
      for identity_properties in contact.identities_properties:
        identity_key = identity_properties[0]
        identity_dict = {'identity': identity_key}
        util.SetIfNotNone(identity_dict, 'description', identity_properties[1])
        util.SetIfNotNone(identity_dict, 'user_id', identity_key_to_user_id_map[Identity.Canonicalize(identity_key)])
        identities_list.append(identity_dict)
      c_dict['identities'] = identities_list
    return c_dict

  start_key = request.get('start_key', None)
  limit = request.get('limit', None)

  contacts = yield gen.Task(Contact.RangeQuery,
                            client,
                            hash_key=user_id,
                            range_desc=None,
                            limit=limit,
                            col_names=None,
                            excl_start_key=start_key,
                            scan_forward=True)

  # Get corresponding identities.
  identity_keys = list({identity for co in contacts for identity in co.identities})
  identity_dbkeys = [db_client.DBKey(identity_key, None) for identity_key in identity_keys]
  identities = yield gen.Task(Identity.BatchQuery, client, identity_dbkeys, None, must_exist=False)
  user_ids = [identity.user_id if identity is not None else None for identity in identities]
  identity_key_to_user_id_map = dict(zip(identity_keys, user_ids))

  # Formulates the contacts list into a dict for JSON output.
  response = {'num_contacts': len(contacts),
              'contacts': [_MakeContactDict(co) for co in contacts]}
  if contacts:
    response['last_key'] = contacts[-1].sort_key

  logging.info('QUERY CONTACTS: user: %d, device: %d, %d contacts, start key %s, last key %s' %
               (user_id, device_id, response['num_contacts'], start_key, response.get('last_key', 'None')))

  raise gen.Return(response)
dataset/ETHPy150Open viewfinderco/viewfinder/backend/www/service.py/QueryContacts/original