Example #1
0
def recalculateGCIStudentRanking(request, *args, **kwargs):
    """Recalculates GCI Student Ranking for the specified student.
  """

    student = gci_student_logic.getFromKeyName(kwargs['key_name'])
    if not student:
        return responses.terminateTask()

    # find ranking entity for the student and clear it
    filter = {'student': student}
    ranking = gci_student_ranking_logic.getForFields(filter=filter,
                                                     unique=True)
    ranking.points = 0
    ranking.tasks = []
    ranking.put()

    # get all the tasks that the student has completed
    filter = {
        'student': student,
        'status': 'Closed',
    }
    tasks = gci_task_logic.getForFields(filter=filter)

    for task in tasks:
        gci_student_ranking_logic.updateRanking(task)

    return responses.terminateTask()
Example #2
0
def accept_proposals(request, *args, **kwargs):
  """Accept proposals for an organization
  """

  params = request.POST

  # Setup an artifical request deadline
  timelimit = int(params["timelimit"])
  timekeeper = Timekeeper(timelimit)

  # Query proposals based on status
  org = org_logic.getFromKeyName(params["orgkey"])
  proposals = student_proposal_logic.getProposalsToBeAcceptedForOrg(org)

  # Accept proposals
  try:
    for remain, proposal in timekeeper.iterate(proposals):
      logging.info("accept %s %s %s", remain, org.key(), proposal.key())
      accept_proposal(proposal)
      accept_proposal_email(proposal)

  # Requeue this task for continuation
  except DeadlineExceededError:
    taskqueue.add(url=request.path, params=params)
    return responses.terminateTask()

  # Reject remaining proposals
  taskqueue.add(url=params["nextpath"], params=params)
  return responses.terminateTask()
Example #3
0
def recalculateGCIStudentRanking(request, *args, **kwargs):
  """Recalculates GCI Student Ranking for the specified student.
  """

  student = gci_student_logic.getFromKeyName(kwargs['key_name'])
  if not student:
    return responses.terminateTask()

  # find ranking entity for the student and clear it
  filter = {
      'student': student
      }
  ranking = gci_student_ranking_logic.getForFields(filter=filter,
      unique=True)
  ranking.points = 0
  ranking.tasks = []
  ranking.put()

  # get all the tasks that the student has completed
  filter = {
      'student': student,
      'status': 'Closed',
      }
  tasks = gci_task_logic.getForFields(filter=filter)

  for task in tasks:
    gci_student_ranking_logic.updateRanking(task)

  return responses.terminateTask()
Example #4
0
  def recalculateForStudent(self, request, *args, **kwargs):
    """Recalculates GCI Student Ranking for the specified student.

    Args in POST:
      key: The string version of the key for the GCIProfile entity
           representing the student.
    """
    post_dict = request.POST
    key = db.Key(post_dict['key'])
    student = GCIProfile.get(key)

    if not student:
      logging.warning('Enqueued task to recalculate ranking for '
                      'non-existent student %s' %(key))
      return responses.terminateTask()

    # get all the tasks that the student has completed
    q = GCITask.all()
    q.filter('student', student)
    q.filter('status', 'Closed')
    tasks = q.fetch(1000)

    ranking_logic.calculateRankingForStudent(student, tasks)

    return responses.terminateTask()
Example #5
0
    def recalculateForStudent(self, request, *args, **kwargs):
        """Recalculates GCI Student Ranking for the specified student.

    Args in POST:
      key: The string version of the key for the GCIProfile entity
           representing the student.
    """
        post_dict = request.POST
        key = db.Key(post_dict['key'])
        student = GCIProfile.get(key)

        if not student:
            logging.warning(
                'Enqueued task to recalculate ranking for '
                'non-existent student %s', key)
            return responses.terminateTask()

        # get all the tasks that the student has completed
        q = GCITask.all()
        q.filter('student', student)
        q.filter('status', 'Closed')
        tasks = q.fetch(1000)

        score_logic.calculateRankingForStudent(student, tasks)

        return responses.terminateTask()
Example #6
0
def accept_proposals(request, *args, **kwargs):
    """Accept proposals for an organization
  """

    params = request.POST

    # Setup an artifical request deadline
    timelimit = int(params["timelimit"])
    timekeeper = Timekeeper(timelimit)

    # Query proposals based on status
    org = org_logic.getFromKeyName(params["orgkey"])
    proposals = student_proposal_logic.getProposalsToBeAcceptedForOrg(org)

    # Accept proposals
    try:
        for remain, proposal in timekeeper.iterate(proposals):
            logging.info("accept %s %s %s", remain, org.key(), proposal.key())
            accept_proposal(proposal)
            accept_proposal_email(proposal)

    # Requeue this task for continuation
    except DeadlineExceededError:
        taskqueue.add(url=request.path, params=params)
        return responses.terminateTask()

    # Reject remaining proposals
    taskqueue.add(url=params["nextpath"], params=params)
    return responses.terminateTask()
Example #7
0
  def acceptProposals(self, request, *args, **kwargs):
    """Accept proposals for an single organization.

    POST Args:
      org_key: The key of the organization
    """
    params = request.POST

    # Setup an artifical request deadline
    timekeeper = Timekeeper(20000)

    # Query proposals based on status
    org = soc_org_model.SOCOrganization.get_by_id(params['org_key'])
    proposals = proposal_logic.getProposalsToBeAcceptedForOrg(org)

    # Accept proposals
    try:
      for remain, proposal in timekeeper.iterate(proposals):
        logging.info("accept %s %s %s", remain, org.key.id(), proposal.key())
        self.acceptProposal(proposal)
    # Requeue this task for continuation
    except DeadlineExceededError:
      taskqueue.add(url=request.path, params=params)
      return responses.terminateTask()

    # Reject remaining proposals
    taskqueue.add(url='/tasks/gsoc/accept_proposals/reject', params=params)
    return responses.terminateTask()
Example #8
0
  def _startShipmentSync(self, request, *args, **kwargs):
    """Start syncing shipment data.

    POST Args:
      program_key: the key of the program which task is runnig for.
      sheet_content: sheet content data in JSON format.
      sheet_type: 'usa' or 'intl'
      shipment_info_id: id of the shipment info object that task is running 
                        for.
    """
    params = dicts.merge(request.POST, request.GET)
    redirect = RedirectHelper(None, None)

    if 'program_key' not in params:
      logging.error("missing program_key in params: '%s'" % params)
      return responses.terminateTask()

    if 'sheet_content' not in params:
      logging.error("missing sheet_content in params: '%s'" % params)
      return responses.terminateTask()

    if 'sheet_type' not in params:
      logging.error("missing sheet_type in params: '%s'" % params)
      return responses.terminateTask()

    if 'shipment_info_id' not in params:
      logging.error("missing shipment_info_id in params: '%s'" % params)
      return responses.terminateTask()

    self.setProgram(params['program_key'])
    self.setShipmentInfo(int(params['shipment_info_id']))

    self.__shipment_info.status = 'syncing'
    self.__shipment_info.put()

    sheet_content = StringIO.StringIO(
        simplejson.loads(params['sheet_content']))
    sheet_type = params['sheet_type']

    sheet_rows = [row for row in csv.reader(sheet_content)]

    if sheet_type == 'usa':
      column_indexes = self.findColumnIndexes(
          sheet_rows[0], self.USA_EXPECTED_COLUMNS)

    elif sheet_type == 'intl':
      column_indexes = self.findColumnIndexes(
          sheet_rows[0], self.INTL_EXPECTED_COLUMNS)

    params = {
        'program_key': params['program_key'],
        'shipment_info_id': params['shipment_info_id'],
        'column_indexes': simplejson.dumps(column_indexes),
        'sheet_rows': simplejson.dumps(sheet_rows[1:]),
    }

    taskqueue.add(url=redirect.urlOf('shipment_sync_task_continue'),
                  params=params)
    return responses.terminateTask()
Example #9
0
  def _startShipmentSync(self, request, *args, **kwargs):
    """Start syncing shipment data.

    POST Args:
      program_key: the key of the program which task is runnig for.
      sheet_content: sheet content data in JSON format.
      sheet_type: 'usa' or 'intl'
      shipment_info_id: id of the shipment info object that task is running
                        for.
    """
    params = dicts.merge(request.POST, request.GET)

    if 'program_key' not in params:
      logging.error("missing program_key in params: '%s'", params)
      return responses.terminateTask()

    if 'sheet_content' not in params:
      logging.error("missing sheet_content in params: '%s'", params)
      return responses.terminateTask()

    if 'sheet_type' not in params:
      logging.error("missing sheet_type in params: '%s'", params)
      return responses.terminateTask()

    if 'shipment_info_id' not in params:
      logging.error("missing shipment_info_id in params: '%s'", params)
      return responses.terminateTask()

    self.setProgram(params['program_key'])
    self.setShipmentInfo(int(params['shipment_info_id']))

    self.shipment_info.status = 'syncing'
    self.shipment_info.put()

    sheet_content = StringIO.StringIO(
        json.loads(params['sheet_content']))
    sheet_type = params['sheet_type']

    sheet_rows = [row for row in csv.reader(sheet_content)]

    if sheet_type == 'usa':
      column_indexes = self.findColumnIndexes(
          sheet_rows[0], self.USA_EXPECTED_COLUMNS)

    elif sheet_type == 'intl':
      column_indexes = self.findColumnIndexes(
          sheet_rows[0], self.INTL_EXPECTED_COLUMNS)

    params = {
        'program_key': params['program_key'],
        'shipment_info_id': params['shipment_info_id'],
        'column_indexes': json.dumps(column_indexes),
        'sheet_rows': json.dumps(sheet_rows[1:]),
    }

    task_continue_url = links.SOC_LINKER.site(url_names.GSOC_SHIPMENT_TASK_CONTINUE)
    taskqueue.add(url=task_continue_url, params=params)
    return responses.terminateTask()
Example #10
0
    def recalculateGCIRanking(self, request, *args, **kwargs):
        """Recalculates student ranking for the entire program.

    Args in POST dict:
      cursor: Query cursor to figure out where we need to start processing
    """

        key_name = '%s/%s' % (kwargs['sponsor'], kwargs['program'])
        cursor = request.POST.get('cursor')

        program = GCIProgram.get_by_key_name(key_name)
        if not program:
            logging.warning(
                'Enqueued recalculate ranking task for non-existing program: %s',
                key_name)
            return responses.terminateTask()

        # Retrieve the students for the program
        q = GCIProfile.all()
        q.filter('program', program)
        q.filter('is_student', True)

        if cursor:
            q.with_cursor(cursor)

        students = q.fetch(25)

        for student in students:
            # get all the tasks that the student has completed
            task_q = GCITask.all()
            task_q.filter('student', student)
            task_q.filter('status', 'Closed')

            tasks = task_q.fetch(1000)

            # calculate score with all the tasks
            score_logic.calculateScore(student, tasks, program)

            # calculate org score with all the tasks
            db.run_in_transaction(org_score_logic.updateOrgScoresTxn(tasks))

        if students:
            # schedule task to do the rest of the students
            params = {
                'cursor': q.cursor(),
            }
            taskqueue.add(queue_name='gci-update',
                          url=request.path,
                          params=params)

        return responses.terminateTask()
Example #11
0
def updateGCIRanking(request, *args, **kwargs):
    """Updates student ranking based on the task passed as post argument.
  """

    post_dict = request.POST

    task_keyname = post_dict.get('task_keyname')
    if not task_keyname:
        responses.terminateTask()

    task = gci_task_logic.getFromKeyName(str(task_keyname))
    gci_student_ranking_logic.updateRanking(task)

    return responses.terminateTask()
Example #12
0
def updateGCIRanking(request, *args, **kwargs):
  """Updates student ranking based on the task passed as post argument.
  """

  post_dict = request.POST

  task_keyname = post_dict.get('task_keyname')
  if not task_keyname:
    responses.terminateTask()

  task = gci_task_logic.getFromKeyName(str(task_keyname))
  gci_student_ranking_logic.updateRanking(task)

  return responses.terminateTask()
Example #13
0
  def convertProposals(self, request, *args, **kwargs):
    """Start tasks to convert proposals for all organizations.

    POST Args:
      program_key: the key of the program whose proposals should be converted
      org_cursor: the cursor indicating at which org we currently are
    """
    params = dicts.merge(request.POST, request.GET)

    if 'program_key' not in params:
      logging.error("missing program_key in params: '%s'", params)
      return responses.terminateTask()

    program = GSoCProgram.get_by_key_name(params['program_key'])

    if not program:
      logging.error("invalid program_key in params: '%s'", params)
      return responses.terminateTask()

    query = soc_org_model.SOCOrganization.query(
        soc_org_model.SOCOrganization.program ==
            ndb.Key.from_old_key(program.key()),
        soc_org_model.SOCOrganization.status == org_model.Status.ACCEPTED)

    org_cursor = params.get('org_cursor')
    start_cursor = (
        datastore_query.Cursor(urlsafe=urllib.unquote_plus(org_cursor))
        if org_cursor else None)

    # Add a task for a single organization
    organizations, next_cursor, _ = query.fetch_page(
        1, start_cursor=start_cursor)

    if organizations:
      organization = organizations[0]
      logging.info(
          'Enqueing task to accept proposals for %s.', organization.name)
      # Compounded accept/reject taskflow
      taskqueue.add(
        url='/tasks/gsoc/accept_proposals/accept',
        params={
          'org_key': organization.key.id(),
        })

      # Enqueue a new task to do the next organization
      params['org_cursor'] = next_cursor.urlsafe()
      taskqueue.add(url=request.path, params=params)

    # Exit this task successfully
    return responses.terminateTask()
Example #14
0
def reject_proposals(request, *args, **kwargs):
  """Reject proposals for an org_logic
  """

  params = request.POST

  # Setup an artifical request deadline
  timelimit = int(params["timelimit"])
  timekeeper = Timekeeper(timelimit)

  # Query proposals
  org = org_logic.getFromKeyName(params["orgkey"])
  proposals = reject_proposals_query(org)

  # Reject proposals
  try:
    for remain, proposal in timekeeper.iterate(proposals):
      logging.info("reject %s %s %s", remain, org.key(), proposal.key())
      reject_proposal(proposal)
      reject_proposal_email(proposal)

  # Requeue this task for continuation
  except DeadlineExceededError:
    taskqueue.add(url=request.path, params=params)

  # Exit this task successfully
  return responses.terminateTask()
Example #15
0
def recalculateGCIRanking(request, entities, context, *args, **kwargs):
  """Recalculates student ranking for a program with the specified key_name.
  """

  program = gci_program_logic.getFromKeyName(kwargs['key_name'])
  if not program:
    return responses.terminateTask()

  # prefetch all task difficulties
  all_d = gci_task_model.TaskDifficultyTag.all().fetch(100)

  for entity in entities:
    # check if the entity refers to the program in scope
    if entity.scope.key() != program.key():
      continue

    # get all the tasks that the student has completed
    filter = {
        'student': entity,
        'status': 'Closed',
        }
    tasks = gci_task_logic.getForFields(filter=filter)

    # calculate ranking with all the tasks
    gci_student_ranking_logic.calculateRankingForStudent(entity, tasks, all_d)

    # this task should not be repeated after the program is over
    timeline = program.timeline
    if timeline_helper.isAfterEvent(timeline, 'program_end'):
      raise responses.DoNotRepeatException()
Example #16
0
def reject_proposals(request, *args, **kwargs):
    """Reject proposals for an org_logic
  """

    params = request.POST

    # Setup an artifical request deadline
    timelimit = int(params["timelimit"])
    timekeeper = Timekeeper(timelimit)

    # Query proposals
    org = org_logic.getFromKeyName(params["orgkey"])
    proposals = reject_proposals_query(org)

    # Reject proposals
    try:
        for remain, proposal in timekeeper.iterate(proposals):
            logging.info("reject %s %s %s", remain, org.key(), proposal.key())
            reject_proposal(proposal)
            reject_proposal_email(proposal)

    # Requeue this task for continuation
    except DeadlineExceededError:
        taskqueue.add(url=request.path, params=params)

    # Exit this task successfully
    return responses.terminateTask()
Example #17
0
  def rejectProposals(self, request, *args, **kwargs):
    """Reject proposals for an single organization.
    """
    params = request.POST

    # Setup an artifical request deadline
    timekeeper = Timekeeper(20000)

    # Query proposals
    org = soc_org_model.SOCOrganization.get_by_id(params['org_key'])
    q = GSoCProposal.all()
    q.filter('org', org.key.to_old_key())
    q.filter('status', 'pending')

    # Reject proposals
    try:
      for remain, proposal in timekeeper.iterate(q):
        logging.info("reject %s %s %s", remain, org.key.id(), proposal.key())
        self.rejectProposal(proposal)
    # Requeue this task for continuation
    except DeadlineExceededError:
      taskqueue.add(url=request.path, params=params)

    # Exit this task successfully
    return responses.terminateTask()
Example #18
0
def recalculateGCIRanking(request, entities, context, *args, **kwargs):
    """Recalculates student ranking for a program with the specified key_name.
  """

    program = gci_program_logic.getFromKeyName(kwargs['key_name'])
    if not program:
        return responses.terminateTask()

    # prefetch all task difficulties
    all_d = gci_task_model.TaskDifficultyTag.all().fetch(100)

    for entity in entities:
        # check if the entity refers to the program in scope
        if entity.scope.key() != program.key():
            continue

        # get all the tasks that the student has completed
        filter = {
            'student': entity,
            'status': 'Closed',
        }
        tasks = gci_task_logic.getForFields(filter=filter)

        # calculate ranking with all the tasks
        gci_student_ranking_logic.calculateRankingForStudent(
            entity, tasks, all_d)

        # this task should not be repeated after the program is over
        timeline = program.timeline
        if timeline_helper.isAfterEvent(timeline, 'program_end'):
            raise responses.DoNotRepeatException()
Example #19
0
    def collectTask(self,
                    request,
                    access_type,
                    page_name=None,
                    params=None,
                    **kwargs):
        """Task for collecting statistics that will be executed by Task Queue API.
    """

        logic = params['logic']
        link_id = kwargs['link_id']
        scope_path = kwargs['scope_path']

        statistic = self._getStatisticEntity(link_id, scope_path, logic)
        if statistic is None:
            raise task_responses.FatalTaskError

        statistic, completed = logic.collectDispatcher(statistic)

        self._updateCache(statistic, link_id, scope_path, logic)

        if completed:
            self._updateCacheList(statistic, scope_path, logic)
            statistic.put()
        else:
            task_responses.startTask(url=request.path, queue_name='statistic')

        return task_responses.terminateTask()
Example #20
0
  def recalculateGCIRanking(self, request, *args, **kwargs):
    """Recalculates student ranking for the entire program.

    Args in POST dict:
      cursor: Query cursor to figure out where we need to start processing
    """

    key_name = '%s/%s' % (kwargs['sponsor'], kwargs['program'])
    cursor = request.POST.get('cursor')

    program = GCIProgram.get_by_key_name(key_name)
    if not program:
      logging.warning(
          'Enqueued recalculate ranking task for non-existing '
          'program: %s' %key_name)
      return responses.terminateTask()

    # Retrieve the students for the program
    q = GCIProfile.all()
    q.filter('scope', program)
    q.filter('is_student', True)

    if cursor:
      q.with_cursor(cursor)

    students = q.fetch(25)

    for student in students:
      # get all the tasks that the student has completed
      task_q = GCITask.all()
      task_q.filter('student', student)
      task_q.filter('status', 'Closed')

      tasks = task_q.fetch(1000)

      # calculate ranking with all the tasks
     # ranking_logic.calculateRankingForStudent(student, tasks)
      ranking_logic.calculateScore(student, tasks, program)

    if students:
      # schedule task to do the rest of the students
      params = {
          'cursor': q.cursor(),
          }
      taskqueue.add(queue_name='gci-update', url=request.path, params=params)

    return responses.terminateTask()
Example #21
0
    def recalculateGCIRanking(self, request, *args, **kwargs):
        """Recalculates student ranking for the entire program.

    Args in POST dict:
      cursor: Query cursor to figure out where we need to start processing
    """

        key_name = "%s/%s" % (kwargs["sponsor"], kwargs["program"])
        cursor = request.POST.get("cursor")

        program = GCIProgram.get_by_key_name(key_name)
        if not program:
            logging.warning("Enqueued recalculate ranking task for non-existing program: %s", key_name)
            return responses.terminateTask()

        # Retrieve the students for the program
        q = GCIProfile.all()
        q.filter("program", program)
        q.filter("is_student", True)

        if cursor:
            q.with_cursor(cursor)

        students = q.fetch(25)

        for student in students:
            # get all the tasks that the student has completed
            task_q = GCITask.all()
            task_q.filter("student", student)
            task_q.filter("status", "Closed")

            tasks = task_q.fetch(1000)

            # calculate score with all the tasks
            score_logic.calculateScore(student, tasks, program)

            # calculate org score with all the tasks
            db.run_in_transaction(org_score_logic.updateOrgScoresTxn(tasks))

        if students:
            # schedule task to do the rest of the students
            params = {"cursor": q.cursor()}
            taskqueue.add(queue_name="gci-update", url=request.path, params=params)

        return responses.terminateTask()
Example #22
0
def assignSlots(request, *args, **kwargs):
  """Sets the slots attribute for each organization entity

  POST Args:
    slots: an org_key:num_slots JSON dictionary
  """

  # Setup an artifical request deadline
  timelimit = int(request.REQUEST.get("timelimit", 20000))
  timekeeper = Timekeeper(timelimit)

  program_key = request.REQUEST.get("programkey")
  last_key = request.REQUEST.get("lastkey", "")
  program = program_logic.getFromKeyName(program_key)

  # Copy for modification below
  params = request.POST.copy()
  params["timelimit"] = timelimit

  # Parse the JSON org:slots dictionary
  slots = simplejson.loads(program.slots_allocation)
  org_keys = [i for i in sorted(slots.keys()) if i > last_key]
  logging.info(org_keys)

  # Assign slots for each organization
  try:
    for clock, org_key in timekeeper.iterate(org_keys):
      logging.info("%s %s %s", request.path, clock, org_key)

      org_slots = slots[org_key]
      # Get the organization entity
      org = org_logic.getFromKeyFields({
          'link_id': org_key,
          'scope_path': program_key,
      })

      if not org:
        logging.error("no such org '%s'/'%s'" % (program_key, org_key))
        continue

      # Count proposals and mentors
      org.slots = int(org_slots['slots'])
      org.nr_applications, org.nr_mentors = countProposals(org)

      # Update the organization entity
      org.put()

      # Mark the organization as done
      last_key = org_key

  # Requeue this task for continuation
  except DeadlineExceededError:
    params["lastkey"] = last_key
    taskqueue.add(url=request.path, params=params)

  # Exit this task successfully
  return responses.terminateTask()
Example #23
0
  def wrapper(request, *args, **kwargs):
    """Decorator wrapper method
    """

    try:
      return func(request, *args, **kwargs)
    except task_responses.FatalTaskError, error:
      logging.exception(error)
      return task_responses.terminateTask()
Example #24
0
    def wrapper(request, *args, **kwargs):
        """Decorator wrapper method
    """

        try:
            return func(request, *args, **kwargs)
        except task_responses.FatalTaskError, error:
            logging.exception(error)
            return task_responses.terminateTask()
Example #25
0
  def updateRankingWithTask(self, request, *args, **kwargs):
    """Updates student ranking based on the task passed as post argument.

    Args in POST dict:
      id: The (numeric) id of the task to update the ranking for
    """
    post_dict = request.POST

    id = int(post_dict.get('id'))
    task = GCITask.get_by_id(id)

    if not task:
      logging.warning('Ranking update queued for non-existing task: %s' %id)
      responses.terminateTask()

    ranking_logic.updateScore(task)

    logging.info("ranking_update updateRankingWithTask ends")
    return responses.terminateTask()
Example #26
0
    def clearGCIRanking(self, request, *args, **kwargs):
        """Clears student ranking for a program with the specified key_name.
    """
        key_name = "%s/%s" % (kwargs["sponsor"], kwargs["program"])

        program = GCIProgram.get_by_key_name(key_name)
        if not program:
            logging.warning("Enqueued recalculate ranking task for non-existing program: %s", key_name)
            return responses.terminateTask()

        q = GCIScore.all()
        q.filter("program", program)

        rankings = q.fetch(500)
        while rankings:
            db.delete(rankings)
            rankings = q.fetch(500)

        return responses.terminateTask()
Example #27
0
    def updateRankingWithTask(self, request, *args, **kwargs):
        """Updates student ranking based on the task passed as post argument.

    Args in POST dict:
      id: The (numeric) id of the task to update the ranking for
    """
        post_dict = request.POST

        id = int(post_dict.get('id'))
        task = GCITask.get_by_id(id)

        if not task:
            logging.warning('Ranking update queued for non-existing task: %s',
                            id)
            responses.terminateTask()

        score_logic.updateScore(task)

        logging.info("ranking_update updateRankingWithTask ends")
        return responses.terminateTask()
Example #28
0
    def clearGCIRanking(self, request, *args, **kwargs):
        """Clears student ranking for a program with the specified key_name.
    """
        key_name = '%s/%s' % (kwargs['sponsor'], kwargs['program'])

        program = GCIProgram.get_by_key_name(key_name)
        if not program:
            logging.warning(
                'Enqueued recalculate ranking task for non-existing program: %s',
                key_name)
            return responses.terminateTask()

        q = GCIScore.all()
        q.filter('program', program)

        rankings = q.fetch(500)
        while rankings:
            db.delete(rankings)
            rankings = q.fetch(500)

        return responses.terminateTask()
Example #29
0
def studentIterator(student_profile_function, request, **kwargs):
  """Applies a function to every student profile in a program.

  Args:
    student_profile_function: A function that accepts a single
      student profile_model.GCIProfile as an argument.
    request: A RequestData object.
    **kwargs: Keyword arguments associated with the request.

  Returns:
    An HttpResponse object.
  """
  # TODO(nathaniel): Call a utility function for this key_name.
  key_name = '%s/%s' % (kwargs['sponsor'], kwargs['program'])
  cursor = request.POST.get('cursor')

  program = program_model.GCIProgram.get_by_key_name(key_name)
  if not program:
    logging.warning('Enqueued task for nonexistant program %s', key_name)
    return responses.terminateTask()

  # Retrieve the students for the program.
  query = profile_model.GCIProfile.all()
  # TODO(nathaniel): These string literals should be constants somewhere.
  query.filter('program', program)
  query.filter('is_student', True)
  if cursor:
    query.with_cursor(cursor)

  student_profiles = query.fetch(25)

  for student_profile in student_profiles:
    student_profile_function(student_profile)

  if student_profiles:
    # Schedule task to do the rest of the students.
    params = {'cursor': query.cursor()}
    taskqueue.add(queue_name='gci-update', url=request.path, params=params)

  return responses.terminateTask()
Example #30
0
    def manageModelsStatus(request, *args, **kwargs):
        """Sets status of the roles queried by the fields given by POST.
    """

        post_dict = request.POST

        new_status = post_dict.get('new_status')
        if not new_status:
            if not status_retriever or not callable(status_retriever):
                return error_handler.logErrorAndReturnOK(
                    'No valid status can be set by the manageModelStatus.')

        if not 'fields' in post_dict:
            error_handler.logErrorAndReturnOK(
                'No fields to filter on found for manageModelStatus.')

        fields = pickle.loads(str(post_dict['fields']))

        entities = entity_logic.getForFields(fields, limit=BATCH_SIZE)

        for entity in entities:
            if new_status:
                status = new_status
            else:
                status = status_retriever(entity)

            entity.status = status

        db.put(entities)

        if len(entities) == BATCH_SIZE:
            # we might not have exhausted all the roles that can be updated,
            # so start the same task again
            context = post_dict.copy()
            responses.startTask(request.path, context=context)
            return responses.terminateTask()

        # exhausted all the entities the task has been completed
        return responses.terminateTask()
Example #31
0
  def manageModelsStatus(request, *args, **kwargs):
    """Sets status of the roles queried by the fields given by POST.
    """

    post_dict = request.POST

    new_status = post_dict.get('new_status')
    if not new_status:
      if not status_retriever or not callable(status_retriever):
        return error_handler.logErrorAndReturnOK(
          'No valid status can be set by the manageModelStatus.')

    if not 'fields' in post_dict:
      error_handler.logErrorAndReturnOK(
          'No fields to filter on found for manageModelStatus.')

    fields = pickle.loads(str(post_dict['fields']))

    entities = entity_logic.getForFields(fields, limit=BATCH_SIZE)

    for entity in entities:
      if new_status:
        status = new_status
      else:
        status = status_retriever(entity)

      entity.status = status

    db.put(entities)

    if len(entities) == BATCH_SIZE:
      # we might not have exhausted all the roles that can be updated,
      # so start the same task again
      context = post_dict.copy()
      responses.startTask(request.path, context=context)
      return responses.terminateTask()

    # exhausted all the entities the task has been completed
    return responses.terminateTask()
Example #32
0
def sendMail(request):
  """Sends out an email that is stored in the datastore.

  The POST request should contain the following entries:
    mail_key: Datastore key for an Email entity.
  """
  post_dict = request.POST

  mail_key = post_dict.get('mail_key', None)

  if not mail_key:
    return error_handler.logErrorAndReturnOK('No email key specified')

  mail_entity = email.Email.get(mail_key)

  if not mail_entity:
    return error_handler.logErrorAndReturnOK(
        'No email entity found for key %s' %mail_key)

  # construct the EmailMessage from the given context
  loaded_context = simplejson.loads(mail_entity.context)

  context = {}
  for key, value in loaded_context.iteritems():
    # If we don't do this python will complain about kwargs not being
    # strings.
    context[str(key)] = value

  logging.info('Sending %s' %context)
  message = mail.EmailMessage(**context)

  try:
    message.check_initialized()
  except:
    logging.error('This message was not properly initialized')
    mail_entity.delete()
    return responses.terminateTask()

  def txn():
    """Transaction that ensures the deletion of the Email entity only if
    the mail has been successfully sent.
    """
    mail_entity.delete()
    message.send()

  try:
    db.RunInTransaction(txn)
  except mail.Error, exception:
    # shouldn't happen because validate has been called, keeping the Email
    # entity for study purposes.
    return error_handler.logErrorAndReturnOK(exception)
Example #33
0
    def wrapper(func):
        def iterative_wrapped(request, *args, **kwargs):
            """Decorator wrapper method

      Args:
        request: Django HTTP Request object

      request.POST usage:
        fields: a JSON dict for the properties that the entities should have.
          This updates values from the task_default entry.
        start_key: the key of the next entity to fetch

      Returns:
        Standard HTTP Django response
      """

            post_dict = request.POST

            fields = task_default.get('fields', {})
            if 'fields' in post_dict:
                fields.update(pickle.loads(str(post_dict['fields'])))

            start_key = task_default.get('start_key', None)
            if 'start_key' in post_dict:
                # get the key where to start this iteration
                start_key = post_dict['start_key']
            if start_key:
                start_key = db.Key(start_key)

            # get the entities for this iteration
            entities, next_start_key = logic.getBatchOfData(
                filter=fields, start_key=start_key)

            # copy the post_dict so that the wrapped function can edit what it needs
            context = post_dict.copy()

            # when true, the iterative task will not be repeated when completed
            do_not_repeat = False

            try:
                func(request,
                     entities=entities,
                     context=context,
                     *args,
                     **kwargs)
            except task_responses.DoNotRepeatException, exception:
                do_not_repeat = True
            except task_responses.FatalTaskError, error:
                logging.debug(post_dict)
                logging.error(error)
                return task_responses.terminateTask()
Example #34
0
def assignProgramSlots(request, *args, **kwargs):
  """Assign slots for organizations within a program

  Gets the slot assignment data as a JSON string from the program
  and enqueues a task to process the slot assignments

  POST Args:
    programkey: the key of the program to operate upon
  """

  program = None
  params = request.REQUEST

  # Query the program entity
  try:
    program = program_logic.getFromKeyName(params["programkey"])
  except KeyError:
    logging.error("programkey not in params")
    return responses.terminateTask()

  if not program:
    logging.error("no such program '%s'" % params["programkey"])
    return responses.terminateTask()

  if not program.slots_allocation:
    logging.error("empty slots_allocation")
    return responses.terminateTask()

  # Enqueue a task to assign the slots
  taskqueue.add(
    url = "/gsoc/tasks/assignslots/assign",
    params = {
        'programkey': params["programkey"],
    })

  # Return successful
  return responses.terminateTask()
Example #35
0
    def run(self, request, *args, **kwargs):
        """Processes all OrgAppSurveyRecords that are in the pre-accept or
    pre-reject state for the given program.

    Expects the following to be present in the POST dict:
      program_key: Specifies the program key name for which to loop over all
          the OrgAppSurveyRecords for.

    Args:
      request: Django Request object
    """

        # set default batch size
        batch_size = 10

        # retrieve the program_key from POST data
        post_dict = request.POST
        program_key = post_dict.get('program_key')

        if not program_key:
            return error_handler.logErrorAndReturnOK(
                'Not all required fields are present in POST dict %s' %
                post_dict)

        program_entity = self.program_logic.getFromKeyName(program_key)

        if not program_entity:
            return error_handler.logErrorAndReturnOK(
                'No Program exists with keyname: %s' % program_key)

        org_app = self.org_app_logic.getForProgram(program_entity)

        record_logic = self.org_app_logic.getRecordLogic()
        fields = {
            'survey': org_app,
            'status': ['pre-accepted', 'pre-rejected']
        }
        org_app_records = record_logic.getForFields(fields, limit=batch_size)

        for org_app_record in org_app_records:
            record_logic.processRecord(org_app_record)

        if len(org_app_records) == batch_size:
            # start a new task because we might not have exhausted all OrgAppRecords
            context = post_dict.copy()
            responses.startTask(self.path, context=context)

        # return a 200 response that everything has been completed
        return responses.terminateTask()
Example #36
0
  def wrapper(func):
    def iterative_wrapped(request, *args, **kwargs):
      """Decorator wrapper method

      Args:
        request: Django HTTP Request object

      request.POST usage:
        fields: a JSON dict for the properties that the entities should have.
          This updates values from the task_default entry.
        start_key: the key of the next entity to fetch

      Returns:
        Standard HTTP Django response
      """

      post_dict = request.POST

      fields = task_default.get('fields', {})
      if 'fields' in post_dict:
        fields.update(pickle.loads(str(post_dict['fields'])))

      start_key = task_default.get('start_key', None)
      if 'start_key' in post_dict:
        # get the key where to start this iteration
        start_key = post_dict['start_key']
      if start_key:
        start_key = db.Key(start_key)

      # get the entities for this iteration
      entities, next_start_key = logic.getBatchOfData(filter=fields,
                                                      start_key=start_key)

      # copy the post_dict so that the wrapped function can edit what it needs
      context = post_dict.copy()

      # when true, the iterative task will not be repeated when completed
      do_not_repeat = False

      try:
        func(request, entities=entities, context=context, *args, **kwargs)
      except task_responses.DoNotRepeatException, exception:
        do_not_repeat = True
      except task_responses.FatalTaskError, error:
        logging.debug(post_dict)
        logging.error(error)
        return task_responses.terminateTask()
Example #37
0
  def run(self, request, *args, **kwargs):
    """Processes all OrgAppSurveyRecords that are in the pre-accept or
    pre-reject state for the given program.

    Expects the following to be present in the POST dict:
      program_key: Specifies the program key name for which to loop over all
          the OrgAppSurveyRecords for.

    Args:
      request: Django Request object
    """

    # set default batch size
    batch_size = 10

    # retrieve the program_key from POST data
    post_dict = request.POST
    program_key = post_dict.get('program_key')

    if not program_key:
      return error_handler.logErrorAndReturnOK(
          'Not all required fields are present in POST dict %s' % post_dict)

    program_entity = self.program_logic.getFromKeyName(program_key)

    if not program_entity:
      return error_handler.logErrorAndReturnOK(
          'No Program exists with keyname: %s' % program_key)

    org_app = self.org_app_logic.getForProgram(program_entity)

    record_logic = self.org_app_logic.getRecordLogic()
    fields = {'survey': org_app,
              'status': ['pre-accepted', 'pre-rejected']}
    org_app_records = record_logic.getForFields(fields, limit=batch_size)

    for org_app_record in org_app_records:
      record_logic.processRecord(org_app_record)

    if len(org_app_records) == batch_size:
        # start a new task because we might not have exhausted all OrgAppRecords
        context = post_dict.copy()
        responses.startTask(self.path, context=context)

    # return a 200 response that everything has been completed
    return responses.terminateTask()
Example #38
0
def clearGCIRanking(request, entities, context, *args, **kwargs):
    """Clears student ranking for a program with the specified key_name.
  """

    program = gci_program_logic.getFromKeyName(kwargs['key_name'])
    if not program:
        return responses.terminateTask()

    for entity in entities:

        # check if the entity refers to the program in scope
        if entity.scope.key() != program.key():
            continue

        entity.points = 0
        entity.tasks = []

        entity.put()
Example #39
0
def clearGCIRanking(request, entities, context, *args, **kwargs):
  """Clears student ranking for a program with the specified key_name.
  """

  program = gci_program_logic.getFromKeyName(kwargs['key_name'])
  if not program:
    return responses.terminateTask()

  for entity in entities:

    # check if the entity refers to the program in scope
    if entity.scope.key() != program.key():
      continue

    entity.points = 0
    entity.tasks = []

    entity.put()
Example #40
0
  def sendMail(self, request):
    """Sends out an email that is stored in the datastore.

    The POST request should contain the following entries:
      mail_key: Datastore key for an Email entity.
    """
    post_dict = request.POST

    mail_key = post_dict.get('mail_key', None)

    if not mail_key:
      return error_handler.logErrorAndReturnOK('No email key specified')

    mail_entity = db.get(mail_key)

    if not mail_entity:
      return error_handler.logErrorAndReturnOK(
          'No email entity found for key %s' % mail_key)

    # construct the EmailMessage from the given context
    loaded_context = simplejson.loads(mail_entity.context)

    context = {}
    for key, value in loaded_context.iteritems():
      # If we don't do this python will complain about kwargs not being
      # strings.
      context[str(key)] = value

    logging.info('Sending %s' %context)
    message = mail.EmailMessage(**context)

    try:
      message.check_initialized()
    except Exception, e:
      logging.exception(e)
      context['body'] = context.get('body', '')[:10]
      logging.error('This message was not properly initialized: "%s"' % context)
      mail_entity.delete()
      return responses.terminateTask()
Example #41
0
  def collectTask(self, request, access_type, page_name=None,
                      params=None, **kwargs):
    """Task for collecting statistics that will be executed by Task Queue API.
    """

    logic = params['logic']
    link_id = kwargs['link_id']
    scope_path = kwargs['scope_path']

    statistic = self._getStatisticEntity(link_id, scope_path, logic)
    if statistic is None:
      raise task_responses.FatalTaskError

    statistic, completed = logic.collectDispatcher(statistic)

    self._updateCache(statistic, link_id, scope_path, logic)

    if completed:
      self._updateCacheList(statistic, scope_path, logic)
      statistic.put()
    else:
      task_responses.startTask(url=request.path, queue_name='statistic')

    return task_responses.terminateTask()
Example #42
0
  def _continueShipmentSync(self, request, *args, **kwargs):
    """Continue syncing shipment data.

    POST Args:
      program_key: the key of the program which sync is being done for.
      shipment_info_id: id of the shipment info object that task is running
                        for.
      column_indexes: column indexes for specific columns in JSON format.
      sheet_rows: spreadsheets CSV chunk data in JSON format.
    """
    timekeeper = Timekeeper(20000)
    params = dicts.merge(request.POST, request.GET)
    redirect = RedirectHelper(None, None)

    if 'program_key' not in params:
      logging.error("missing program_key in params: '%s'" % params)
      return responses.terminateTask()

    if 'shipment_info_id' not in params:
      logging.error("missing shipment_info_id in params: '%s'" % params)
      return responses.terminateTask()

    self.setProgram(params['program_key'])
    self.setShipmentInfo(int(params['shipment_info_id']))

    if 'sheet_rows' not in params:
      logging.error("missing sheet_rows data in params: '%s'" % params)
      return responses.terminateTask()

    if 'column_indexes' not in params:
      logging.error("missing column_indexes data in params: '%s'" % params)
      return responses.terminateTask()

    column_indexes = simplejson.loads(params['column_indexes'])
    sheet_rows = simplejson.loads(params['sheet_rows'])

    try:
      for remain, row in timekeeper.iterate(sheet_rows):

        if len(row) < len(column_indexes):
          row.extend((len(column_indexes) - len(row)) * [''])
        data = self.getRowData(row, column_indexes)
        link_id = data['link_id']

        q = GSoCProfile.all().filter('scope', self.__program)
        q.filter('link_id', link_id)
        profile = q.get()

        if not profile:
          logging.error("Profile link_id '%s' for program '%s' is not found" %
                        (link_id, self.__program.name))
          continue #continue to next row

        if not profile.is_student:
          logging.error("Profile link_id '%s' is not a student" %
                        link_id)
          continue

        tracking = data['tracking']
        date_shipped = data['date_shipped']
        notes = data['notes']
        full_address = " ".join([
          data['address_1'], data['address_2'], data['city'],
          data.get('state', ''), data.get('zip', ''),
          data.get('zippostal_code', ''), data.get('country', '')
        ])
        self.updateShipmentDataForStudent(
            profile, tracking, date_shipped, notes, full_address)

    except DeadlineExceededError:
      if remain:
        remaining_rows = sheet_rows[(-1 * remain):]
        params = {
            'program_key': params.get('program_key'),
            'sheet_rows': simplejson.dumps(remaining_rows),
            'column_indexes': params.get('column_indexes'),
            'shipment_info_id': params.get('shipment_info_id'),
        }
        taskqueue.add(
            url=redirect.urlOf('shipment_sync_task_continue'), params=params)
        return responses.terminateTask()

    self.finishSync()
    return responses.terminateTask()
Example #43
0
      try:
        func(request, entities=entities, context=context, *args, **kwargs)
      except task_responses.DoNotRepeatException, exception:
        do_not_repeat = True
      except task_responses.FatalTaskError, error:
        logging.debug(post_dict)
        logging.error(error)
        return task_responses.terminateTask()
      except Exception, exception:
        logging.debug(post_dict)
        logging.error(exception)
        return task_responses.repeatTask()

      if next_start_key:
        # set the key to use for the next iteration
        context.update({'start_key': next_start_key})

        task_responses.startTask(url=request.path, context=context)
      elif not do_not_repeat and repeat_in is not None:
        # the task will be executed again after repeat_in seconds
        if 'start_key' in context:
          del context['start_key']

        task_responses.startTask(url=request.path, countdown=repeat_in,
            context=context)

      return task_responses.terminateTask()

    return iterative_wrapped
  return wrapper
Example #44
0
            except task_responses.DoNotRepeatException, exception:
                do_not_repeat = True
            except task_responses.FatalTaskError, error:
                logging.debug(post_dict)
                logging.error(error)
                return task_responses.terminateTask()
            except Exception, exception:
                logging.debug(post_dict)
                logging.error(exception)
                return task_responses.repeatTask()

            if next_start_key:
                # set the key to use for the next iteration
                context.update({'start_key': next_start_key})

                task_responses.startTask(url=request.path, context=context)
            elif not do_not_repeat and repeat_in is not None:
                # the task will be executed again after repeat_in seconds
                if 'start_key' in context:
                    del context['start_key']

                task_responses.startTask(url=request.path,
                                         countdown=repeat_in,
                                         context=context)

            return task_responses.terminateTask()

        return iterative_wrapped

    return wrapper
Example #45
0
def convert_proposals(request, *args, **kwargs):
    """Convert proposals for all organizations.

  POST Args:
    programkey: the key of the program whose proposals should be converted
    orgkey: the organization key to start at
  """

    # Setup an artifical request deadline
    timelimit = 20000
    timekeeper = Timekeeper(timelimit)

    # Copy for modification below
    params = dicts.merge(request.POST, request.GET)

    if "programkey" not in params:
        logging.error("missing programkey in params: '%s'" % params)
        return responses.terminateTask()

    program = program_logic.getFromKeyName(params["programkey"])

    if not program:
        logging.error("invalid programkey in params: '%s'" % params)
        return responses.terminateTask()

    fields = {
        "scope": program,
        "status": "active",
    }

    # Continue from the next organization
    if "orgkey" in params:
        org = org_logic.getFromKeyName(params["orgkey"])

        if not org:
            logging.error("invalid orgkey in params: '%s'" % params)
            return responses.terminateTask()

        fields["__key__ >="] = org

    # Add a task for each organization
    org = None
    try:
        orgs = org_logic.getQueryForFields(filter=fields)

        for remain, org in timekeeper.iterate(orgs):
            logging.info("convert %s %s", remain, org.key())

            # Compound accept/reject taskflow
            taskqueue.add(url="/tasks/accept_proposals/accept",
                          params={
                              "orgkey": org.key().id_or_name(),
                              "timelimit": timelimit,
                              "nextpath": "/tasks/accept_proposals/reject"
                          })

    # Requeue this task for continuation
    except DeadlineExceededError:
        if org:
            params["orgkey"] = org.key().id_or_name()

        taskqueue.add(url=request.path, params=params)

    # Exit this task successfully
    return responses.terminateTask()
Example #46
0
    context[str(key)] = value

  logging.info('Sending %s' %context)
  message = mail.EmailMessage(**context)

  try:
    message.check_initialized()
  except:
    logging.error('This message was not properly initialized')
    mail_entity.delete()
    return responses.terminateTask()

  def txn():
    """Transaction that ensures the deletion of the Email entity only if
    the mail has been successfully sent.
    """
    mail_entity.delete()
    message.send()

  try:
    db.RunInTransaction(txn)
  except mail.Error, exception:
    # shouldn't happen because validate has been called, keeping the Email
    # entity for study purposes.
    return error_handler.logErrorAndReturnOK(exception)
  except OverQuotaError:
    return responses.repeatTask()

  # mail successfully sent
  return responses.terminateTask()
Example #47
0
  def _continueShipmentSync(self, request, *args, **kwargs):
    """Continue syncing shipment data.

    POST Args:
      program_key: the key of the program which sync is being done for.
      shipment_info_id: id of the shipment info object that task is running
                        for.
      column_indexes: column indexes for specific columns in JSON format.
      sheet_rows: spreadsheets CSV chunk data in JSON format.
    """
    timekeeper = Timekeeper(20000)
    params = dicts.merge(request.POST, request.GET)

    if 'program_key' not in params:
      logging.error("missing program_key in params: '%s'", params)
      return responses.terminateTask()

    if 'shipment_info_id' not in params:
      logging.error("missing shipment_info_id in params: '%s'", params)
      return responses.terminateTask()

    self.setProgram(params['program_key'])
    self.setShipmentInfo(int(params['shipment_info_id']))

    if 'sheet_rows' not in params:
      logging.error("missing sheet_rows data in params: '%s'", params)
      return responses.terminateTask()

    if 'column_indexes' not in params:
      logging.error("missing column_indexes data in params: '%s'", params)
      return responses.terminateTask()

    column_indexes = json.loads(params['column_indexes'])
    sheet_rows = json.loads(params['sheet_rows'])

    try:
      for remain, row in timekeeper.iterate(sheet_rows):

        if len(row) < len(column_indexes):
          row.extend((len(column_indexes) - len(row)) * [''])
        data = self.getRowData(row, column_indexes)
        username = data['username']

        profile = profile_logic.getProfileForUsername(username, self.program_key)

        if not profile:
          logging.error("Profile with username '%s' for program '%s' is not found",
                        username, self.ndb_program_key.id())
          continue #continue to next row

        if not profile.is_student:
          logging.error("Profile with username '%s' is not a student", username)
          continue

        tracking = data['tracking']
        self.updateShipmentDataForStudent(profile, tracking)

    except DeadlineExceededError:
      if remain:
        remaining_rows = sheet_rows[(-1 * remain):]
        params = {
            'program_key': params.get('program_key'),
            'sheet_rows': json.dumps(remaining_rows),
            'column_indexes': params.get('column_indexes'),
            'shipment_info_id': params.get('shipment_info_id'),
        }
        task_continue_url = links.SOC_LINKER.site(url_names.GSOC_SHIPMENT_TASK_CONTINUE)
        taskqueue.add(url=task_continue_url, params=params)
        return responses.terminateTask()

    self.finishSync()
    return responses.terminateTask()
Example #48
0
def convert_proposals(request, *args, **kwargs):
  """Convert proposals for all organizations.

  POST Args:
    programkey: the key of the program whose proposals should be converted
    orgkey: the organization key to start at
  """

  # Setup an artifical request deadline
  timelimit = 20000
  timekeeper = Timekeeper(timelimit)

  # Copy for modification below
  params = dicts.merge(request.POST, request.GET)

  if "programkey" not in params:
    logging.error("missing programkey in params: '%s'" % params)
    return responses.terminateTask()

  program = program_logic.getFromKeyName(params["programkey"])

  if not program:
    logging.error("invalid programkey in params: '%s'" % params)
    return responses.terminateTask()

  fields = {
      "scope": program,
      "status": "active",
  }

  # Continue from the next organization
  if "orgkey" in params:
    org = org_logic.getFromKeyName(params["orgkey"])

    if not org:
      logging.error("invalid orgkey in params: '%s'" % params)
      return responses.terminateTask()

    fields["__key__ >="] = org

  # Add a task for each organization
  org = None
  try:
    orgs = org_logic.getQueryForFields(filter=fields)

    for remain, org in timekeeper.iterate(orgs):
      logging.info("convert %s %s", remain, org.key())

      # Compound accept/reject taskflow
      taskqueue.add(
        url = "/tasks/accept_proposals/accept",
        params = {
          "orgkey": org.key().id_or_name(),
          "timelimit": timelimit,
          "nextpath": "/tasks/accept_proposals/reject"
        })

  # Requeue this task for continuation
  except DeadlineExceededError:
    if org:
      params["orgkey"] = org.key().id_or_name()

    taskqueue.add(url=request.path, params=params)

  # Exit this task successfully
  return responses.terminateTask()
Example #49
0
def iterative_task(logic, **task_default):
    """Iterative wrapper method

  Args:
    logic: the Logic instance to get entities for
    task_default: keyword arguments which can contain the following options:
      fields: dictionary to filter the entities on
      start_key: the default key where to start this iterative task
  """
    def wrapper(func):
        def iterative_wrapped(request, *args, **kwargs):
            """Decorator wrapper method

      Args:
        request: Django HTTP Request object

      request.POST usage:
        fields: a JSON dict for the properties that the entities should have.
          This updates values from the task_default entry.
        start_key: the key of the next entity to fetch

      Returns:
        Standard HTTP Django response
      """

            post_dict = request.POST

            fields = task_default.get('fields', {})
            if 'fields' in post_dict:
                fields.update(pickle.loads(str(post_dict['fields'])))

            start_key = task_default.get('start_key', None)
            if 'start_key' in post_dict:
                # get the key where to start this iteration
                start_key = post_dict['start_key']
            if start_key:
                start_key = db.Key(start_key)

            # get the entities for this iteration
            entities, next_start_key = logic.getBatchOfData(
                filter=fields, start_key=start_key)

            # copy the post_dict so that the wrapped function can edit what it needs
            context = post_dict.copy()

            try:
                func(request,
                     entities=entities,
                     context=context,
                     *args,
                     **kwargs)
            except task_responses.FatalTaskError, error:
                logging.debug(post_dict)
                logging.error(error)
                return task_responses.terminateTask()
            except Exception, exception:
                logging.debug(post_dict)
                logging.error(exception)
                return task_responses.repeatTask()

            if next_start_key:
                # set the key to use for the next iteration
                context.update({'start_key': next_start_key})

                task_responses.startTask(url=request.path, context=context)

            return task_responses.terminateTask()
Example #50
0
    def sendMail(self, request):
        """Sends out an email that is stored in the datastore.

    The POST request should contain the following entries:
      mail_key: Datastore key for an Email entity.
    """
        post_dict = request.POST

        mail_key = post_dict.get('mail_key', None)

        if not mail_key:
            return error_handler.logErrorAndReturnOK('No email key specified')

        # TODO(daniel): so ugly...
        try:
            mail_entity = db.get(mail_key)
        except datastore_errors.BadKeyError:
            mail_entity = ndb.Key(urlsafe=mail_key).get()

        if not mail_entity:
            return error_handler.logErrorAndReturnOK(
                'No email entity found for key %s' % mail_key)

        # construct the EmailMessage from the given context
        loaded_context = json.loads(mail_entity.context)

        context = {}
        for key, value in loaded_context.iteritems():
            # If we don't do this python will complain about kwargs not being
            # strings.
            context[str(key)] = value

        logging.info('Sending %s', context)
        message = mail.EmailMessage(**context)

        try:
            message.check_initialized()
        except Exception as e:
            logging.exception(e)
            context['body'] = context.get('body', '')[:10]
            logging.error('This message was not properly initialized: "%s"',
                          context)
            mail_entity.delete()
            return responses.terminateTask()

        def txn():
            """Transaction that ensures the deletion of the Email entity only if
      the mail has been successfully sent.
      """
            mail_entity.delete()
            message.send()

        try:
            db.RunInTransaction(txn)
        except mail.Error as exception:
            # shouldn't happen because validate has been called, keeping the Email
            # entity for study purposes.
            return error_handler.logErrorAndReturnOK(exception)
        except (OverQuotaError, DeadlineExceededError) as e:
            return responses.repeatTask()

        # mail successfully sent
        return responses.terminateTask()