@classmethod
  @gen.engine
  def UpdateWithSettings(cls, client, user_dict, settings_dict, callback):
    # Update user profile attributes.
    assert all(attr_name == 'user_id' or attr_name in User._UPDATE_USER_ATTRIBUTES
               for attr_name in user_dict), user_dict

    # If any name attribute is updated, update them all, if only to None. This helps prevent
    # accidental divergence of name from given_name/family_name.
    for attr_name in ['name', 'given_name', 'family_name']:
      if attr_name in user_dict:
        user_dict.setdefault('name', None)
        user_dict.setdefault('given_name', None)
        user_dict.setdefault('family_name', None)
        break

    user = yield gen.Task(User.Query, client, user_dict['user_id'], None)
    user.UpdateFromKeywords(**user_dict)
    yield gen.Task(user.Update, client)

    if settings_dict:
      # Add keys to dict.
      scratch_settings_dict = deepcopy(settings_dict)
      scratch_settings_dict['settings_id'] = AccountSettings.ConstructSettingsId(user_dict['user_id'])
      scratch_settings_dict['group_name'] = AccountSettings.GROUP_NAME
      scratch_settings_dict['user_id'] = user_dict['user_id']

      # Update any user account settings.
      settings = yield gen.Task(AccountSettings.QueryByUser, client, user_dict['user_id'], None, must_exist=False)
      if settings is None:
        settings = AccountSettings.CreateFromKeywords(**scratch_settings_dict)
      else:
        settings.UpdateFromKeywords(**scratch_settings_dict)
      yield gen.Task(settings.Update, client)

    callback()
Update the user's public profile, as well as any account settings specified in
dataset/ETHPy150Open viewfinderco/viewfinder/backend/db/user.py/User.UpdateWithSettings