@gen.coroutine
def UpdateViewpoint(client, obj_store, user_id, device_id, request):
  """Updates viewpoint metadata."""
  yield Activity.VerifyActivityId(client, user_id, device_id, request['activity']['activity_id'])

  headers = request.pop('headers')
  activity = request.pop('activity')
  viewpoint_id = request['viewpoint_id']

  # We need to preserve backwards-compatibility with old clients that use update_viewpoint in
  # order to make changes to follower attributes. 
  follower_columns = Follower._table.GetColumnNames()
  viewpoint_columns = Viewpoint._table.GetColumnNames()
  if all(attr in follower_columns for attr in request.keys()):
    request = {'headers': headers,
               'user_id': user_id,
               'follower': request}

    yield gen.Task(Operation.CreateAndExecute,
                   client,
                   user_id,
                   device_id,
                   'UpdateFollowerOperation.Execute',
                   request)
  elif all(attr in viewpoint_columns for attr in request.keys()):
    request = {'headers': headers,
               'user_id': user_id,
               'activity': activity,
               'viewpoint': request}

    yield gen.Task(Operation.CreateAndExecute,
                   client,
                   user_id,
                   device_id,
                   'UpdateViewpointOperation.Execute',
                   request)
  else:
    raise web.HTTPError(400, 'Viewpoint and follower attributes cannot be updated together ' +
                             'in the same call to update_viewpoint.')

  logging.info('UPDATE VIEWPOINT: user: %d, device: %d, viewpoint: %s' %
               (user_id, device_id, viewpoint_id))
  raise gen.Return({})
dataset/ETHPy150Open viewfinderco/viewfinder/backend/www/service.py/UpdateViewpoint/original