Ejemplo n.º 1
0
        def update_score_trx():
            delta = 0

            # update score entity
            score = query.get()
            if not score:
                if not value:
                    return
                old_value = 0
                score = GSoCScore(parent=data.url_proposal,
                                  author=data.ndb_profile.key.to_old_key(),
                                  value=value)
                score.put()
                delta = 1
            else:
                old_value = score.value
                if not value:
                    delta = -1
                    score.delete()
                else:
                    score.value = value
                    score.put()

            # update total score for the proposal
            proposal = db.get(data.url_proposal.key())
            proposal.score += value - old_value
            proposal.nr_scores += delta
            proposal.put()
Ejemplo n.º 2
0
        def update_score_trx():
            delta = 0

            # update score entity
            score = query.get()
            if not score:
                if not value:
                    return
                old_value = 0
                score = GSoCScore(parent=self.data.proposal, author=self.data.profile, value=value)
                score.put()
                delta = 1
            else:
                old_value = score.value
                if not value:
                    delta = -1
                    score.delete()
                else:
                    score.value = value
                    score.put()

            # update total score for the proposal
            proposal = db.get(self.data.proposal.key())
            proposal.score += value - old_value
            proposal.nr_scores += delta
            proposal.put()
Ejemplo n.º 3
0
  def createOrUpdateScore(self, value):
    """Creates a new score or updates a score if there is already one
    posted by the current user.

    If the value passed in is 0 then the Score of the user will be removed and
    None will be returned.

    Args:
      value: The value of the score the user gave as an integer.

    Returns:
      The score entity that was created/updated or None if value is 0.
    """
    assert isSet(self.data.proposal)

    query = db.Query(GSoCScore)
    query.filter('author = ', self.data.profile)
    query.ancestor(self.data.proposal)

    score = query.get()

    if not score:
      score = GSoCScore(
          parent=self.data.proposal,
          author=self.data.profile,
          value=value)
    else:
      score.value = value

    proposal_key = self.data.proposal.key()
    def update_score_trx(score):
      if score and not score.value:
        score.delete()
      else:
        score.put()
      # update total score for the proposal
      proposal = db.get(proposal_key)
      proposal.score += (value - (score.value if score else 0))
      proposal.put()

    db.run_in_transaction(update_score_trx, score)
Ejemplo n.º 4
0
    def createOrUpdateScore(self, value):
        """Creates a new score or updates a score if there is already one
    posted by the current user.

    If the value passed in is 0 then the Score of the user will be removed and
    None will be returned.

    Args:
      value: The value of the score the user gave as an integer.

    Returns:
      The score entity that was created/updated or None if value is 0.
    """
        assert isSet(self.data.proposal)

        query = db.Query(GSoCScore)
        query.filter('author = ', self.data.profile)
        query.ancestor(self.data.proposal)

        score = query.get()

        if not score:
            score = GSoCScore(parent=self.data.proposal,
                              author=self.data.profile,
                              value=value)
        else:
            score.value = value

        proposal_key = self.data.proposal.key()

        def update_score_trx(score):
            if score and not score.value:
                score.delete()
            else:
                score.put()
            # update total score for the proposal
            proposal = db.get(proposal_key)
            proposal.score += (value - (score.value if score else 0))
            proposal.put()

        db.run_in_transaction(update_score_trx, score)
Ejemplo n.º 5
0
  def testSubmitProposal(self):
    self.data.createStudent()
    self.timeline.studentSignup()
    url = '/gsoc/proposal/submit/' + self.org.key().name()
    response = self.client.get(url)
    self.assertProposalTemplatesUsed(response)

    # test proposal POST
    override = {'program': self.gsoc, 'score': 0, 'mentor': None, 'org': self.org, 'status': 'new'}
    response, properties = self.modelPost(url, GSoCProposal, override)
    self.assertResponseRedirect(response)

    proposal = GSoCProposal.all().get()
    self.assertPropertiesEqual(properties, proposal)

    suffix = "%s/%s/%d" % (
        self.gsoc.key().name(),
        self.data.user.key().name(),
        proposal.key().id())

    # test review GET
    url = '/gsoc/proposal/review/' + suffix
    response = self.client.get(url)
    self.assertReviewTemplateUsed(response)

    # test comment POST
    from soc.modules.gsoc.models.comment import GSoCComment
    url = '/gsoc/proposal/comment/' + suffix
    override = {'author': self.data.profile, 'is_private': False}
    response, properties = self.modelPost(url, GSoCComment, override)
    self.assertResponseRedirect(response)

    comment = GSoCComment.all().get()
    self.assertPropertiesEqual(properties, comment)

    # Hacky
    self.data.createMentor(self.org)

    # test score POST
    from soc.modules.gsoc.models.score import GSoCScore
    url = '/gsoc/proposal/score/' + suffix
    override = {'author': self.data.profile, 'parent': proposal}
    response, properties = self.modelPost(url, GSoCScore, override)
    self.assertResponseOK(response)

    score = GSoCScore.all().get()
    self.assertPropertiesEqual(properties, score)
Ejemplo n.º 6
0
    def testSubmitProposal(self):
        self.data.createStudent()
        self.timeline.studentSignup()
        url = "/gsoc/proposal/submit/" + self.org.key().name()
        response = self.client.get(url)
        self.assertProposalTemplatesUsed(response)

        # test proposal POST
        override = {"program": self.gsoc, "score": 0, "mentor": None, "org": self.org, "status": "new"}
        response, properties = self.modelPost(url, GSoCProposal, override)
        self.assertResponseRedirect(response)

        proposal = GSoCProposal.all().get()
        self.assertPropertiesEqual(properties, proposal)

        suffix = "%s/%s/%d" % (self.gsoc.key().name(), self.data.user.key().name(), proposal.key().id())

        # test review GET
        url = "/gsoc/proposal/review/" + suffix
        response = self.client.get(url)
        self.assertReviewTemplateUsed(response)

        # test comment POST
        from soc.modules.gsoc.models.comment import GSoCComment

        url = "/gsoc/proposal/comment/" + suffix
        override = {"author": self.data.profile, "is_private": False}
        response, properties = self.modelPost(url, GSoCComment, override)
        self.assertResponseRedirect(response)

        comment = GSoCComment.all().get()
        self.assertPropertiesEqual(properties, comment)

        # Hacky
        self.data.createMentor(self.org)

        # test score POST
        from soc.modules.gsoc.models.score import GSoCScore

        url = "/gsoc/proposal/score/" + suffix
        override = {"author": self.data.profile, "parent": proposal}
        response, properties = self.modelPost(url, GSoCScore, override)
        self.assertResponseOK(response)

        score = GSoCScore.all().get()
        self.assertPropertiesEqual(properties, score)
Ejemplo n.º 7
0
  def testReviewProposal(self):
    mentor = self.createMentorWithSettings('*****@*****.**',
        {'new_proposals' :True, 'public_comments': True,
         'private_comments' :True})

    self.data.createStudent()
    self.data.notificationSettings()
    self.timeline.studentSignup()

    proposal = self.createProposal({'scope': self.data.profile,
                                    'parent': self.data.profile})

    suffix = "%s/%s/%d" % (
        self.gsoc.key().name(),
        self.data.user.key().name(),
        proposal.key().id())

    # test review GET
    url = '/gsoc/proposal/review/' + suffix
    response = self.get(url)
    self.assertReviewTemplateUsed(response)

    self.assertNotContains(
        response,
        '<p class="status"><strong>Status:</strong> Pending</p>')

    # test comment POST
    from soc.modules.gsoc.models.comment import GSoCComment
    url = '/gsoc/proposal/comment/' + suffix
    override = {'author': self.data.profile, 'is_private': False}
    response, properties = self.modelPost(url, GSoCComment, override)
    self.assertResponseRedirect(response)

    comment = GSoCComment.all().get()
    self.assertPropertiesEqual(properties, comment)

    self.assertEmailSent(to=mentor.profile.email, n=1)
    self.assertEmailNotSent(to=self.data.profile.email)

    self.data.deleteProfile()
    self.data.createMentor(self.org)

    # test score POST
    from soc.modules.gsoc.models.score import GSoCScore
    url = '/gsoc/proposal/score/' + suffix
    override = {'author': self.data.profile, 'parent': proposal, 'value': 1}
    response, properties = self.modelPost(url, GSoCScore, override)
    self.assertResponseOK(response)

    score = GSoCScore.all().get()
    self.assertPropertiesEqual(properties, score)

    proposal = GSoCProposal.all().get()
    self.assertEqual(1, proposal.score)
    self.assertEqual(1, proposal.nr_scores)

    # test updating score
    override['value'] = 4
    response, properties = self.modelPost(url, GSoCScore, override)
    self.assertResponseOK(response)

    proposal = GSoCProposal.all().get()
    self.assertEqual(4, proposal.score)
    self.assertEqual(1, proposal.nr_scores)

    # test removing score
    override['value'] = 0
    response, properties = self.modelPost(url, GSoCScore, override)
    self.assertResponseOK(response)

    proposal = GSoCProposal.all().get()
    self.assertEqual(0, proposal.score)
    self.assertEqual(0, proposal.nr_scores)
Ejemplo n.º 8
0
    def testReviewProposal(self):
        mentor = self.createMentorWithSettings(
            '*****@*****.**', {
                'new_proposals': True,
                'public_comments': True,
                'private_comments': True
            })

        self.data.createStudent()
        self.data.notificationSettings()
        self.timeline.studentSignup()

        proposal = self.createProposal({
            'scope': self.data.profile,
            'parent': self.data.profile
        })

        suffix = "%s/%s/%d" % (self.gsoc.key().name(),
                               self.data.user.key().name(),
                               proposal.key().id())

        # test review GET
        url = '/gsoc/proposal/review/' + suffix
        response = self.get(url)
        self.assertReviewTemplateUsed(response)

        self.assertNotContains(
            response, '<p class="status"><strong>Status:</strong> Pending</p>')

        # test comment POST
        from soc.modules.gsoc.models.comment import GSoCComment
        url = '/gsoc/proposal/comment/' + suffix
        override = {'author': self.data.profile, 'is_private': False}
        response, properties = self.modelPost(url, GSoCComment, override)
        self.assertResponseRedirect(response)

        comment = GSoCComment.all().get()
        self.assertPropertiesEqual(properties, comment)

        self.assertEmailSent(to=mentor.profile.email, n=1)
        self.assertEmailNotSent(to=self.data.profile.email)

        self.data.deleteProfile()
        self.data.createMentor(self.org)

        # test score POST
        from soc.modules.gsoc.models.score import GSoCScore
        url = '/gsoc/proposal/score/' + suffix
        override = {
            'author': self.data.profile,
            'parent': proposal,
            'value': 1
        }
        response, properties = self.modelPost(url, GSoCScore, override)
        self.assertResponseOK(response)

        score = GSoCScore.all().get()
        self.assertPropertiesEqual(properties, score)

        proposal = GSoCProposal.all().get()
        self.assertEqual(1, proposal.score)
        self.assertEqual(1, proposal.nr_scores)

        # test updating score
        override['value'] = 4
        response, properties = self.modelPost(url, GSoCScore, override)
        self.assertResponseOK(response)

        proposal = GSoCProposal.all().get()
        self.assertEqual(4, proposal.score)
        self.assertEqual(1, proposal.nr_scores)

        # test removing score
        override['value'] = 0
        response, properties = self.modelPost(url, GSoCScore, override)
        self.assertResponseOK(response)

        proposal = GSoCProposal.all().get()
        self.assertEqual(0, proposal.score)
        self.assertEqual(0, proposal.nr_scores)
Ejemplo n.º 9
0
def convertGSoCProfileDBEntityGroup(profile_key):
  """Converts DB based part of entity group associated with the specified
  profile.

  Args:
    profile_key: db.Key of the profile to process
  """
  # map that associate old keys with new ones which are created during
  # the conversion
  conversion_map = {}
  to_delete = []
  do_put = True

  proposals = GSoCProposal.all().ancestor(profile_key).fetch(1000)
  for proposal in proposals:
    # update GSoCProposal.parent
    new_proposal = _convertParent(proposal)

    # update GSoCProposal.possible_mentors
    new_proposal.possible_mentors = _convertListProperty(
        GSoCProposal.possible_mentors, new_proposal)

    # update GSoCProposal.mentor
    new_proposal.mentor = _convertReferenceProperty(
        GSoCProposal.mentor, new_proposal)
    to_delete.append(proposal)
    if do_put:
      new_proposal.put()
      conversion_map[proposal.key()] = new_proposal.key()

    comments = GSoCComment.all().ancestor(proposal).fetch(1000)
    for comment in comments:
      # update GSoCComment.parent
      new_comment = _convertParent(comment, parent=new_proposal.key())

      # update GSoCComment.author
      new_comment.author = _convertReferenceProperty(
          GSoCComment.author, new_comment)
      if do_put:
        new_comment.put()
      to_delete.append(comment)

    scores = GSoCScore.all().ancestor(proposal).fetch(1000)
    for score in scores:
      # update GSoCScore.parent
      new_score = _convertParent(score, parent=new_proposal.key())

      # update GSoCScore.author
      new_score.author = _convertReferenceProperty(GSoCScore.author, new_score)
      if do_put:
        new_score.put()
      to_delete.append(score)

  projects = GSoCProject.all().ancestor(profile_key).fetch(1000)
  for project in projects:
    # update GSoCProject.parent
    new_project = _convertParent(project)

    # update GSoCProject.mentors
    new_project.mentors = _convertListProperty(GSoCProject.mentors, new_project)

    # update GSoCProject.proposal
    proposal_key = GSoCProject.proposal.get_value_for_datastore(project)
    if proposal_key:
      new_project.proposal = conversion_map.get(
          GSoCProject.proposal.get_value_for_datastore(project))

    if do_put:
      new_project.put()
      conversion_map[project.key()] = new_project.key()
    to_delete.append(project)

    grading_records = GSoCGradingRecord.all().ancestor(project.key())
    for grading_record in grading_records:
      # update GSoCGradingProjectSurveyRecord.project
      # this is another entity group, but XG transaction does the thing
      grading_project_survey_record_key = (
          GSoCGradingRecord.mentor_record.get_value_for_datastore(
              grading_record))
      if grading_project_survey_record_key:
        grading_project_survey_record = GSoCGradingProjectSurveyRecord.get(
            grading_project_survey_record_key)
        if grading_project_survey_record:
          grading_project_survey_record.project = new_project.key()
          if do_put:
            grading_project_survey_record.put()

      # update GSoCProjectSurveyRecord.project
      # this is another entity group, but XG transaction does the thing
      project_survey_record_key = (
          GSoCGradingRecord.student_record.get_value_for_datastore(
              grading_record))
      if project_survey_record_key:
        project_survey_record = GSoCProjectSurveyRecord.get(
            project_survey_record_key)
        if project_survey_record:
          project_survey_record.project = new_project.key()
          if do_put:
            project_survey_record.put()

      # update GSoCGradingRecord.parent
      new_grading_record = _convertParent(
          grading_record, parent=new_project.key())
      if do_put:
        new_grading_record.put()

    code_samples = GSoCCodeSample.all().ancestor(project.key())
    for code_sample in code_samples:
      # update GSoCCodeSample.parent
      new_code_sample = _convertParent(code_sample, parent=new_project.key())
      if do_put:
        new_code_sample.put()
      to_delete.append(code_sample)

  db.delete(to_delete)
Ejemplo n.º 10
0
  def testReviewProposal(self):
    self.timeline_helper.studentSignup()
    # TODO(daniel): Re-seed settings when they are added.
    #  {'notify_new_proposals' :True, 'notify_public_comments': True,
    #   'notify_private_comments' :True}
    mentor = profile_utils.seedNDBProfile(
        self.program.key(), mentor_for=[self.org.key])

    user = profile_utils.seedNDBUser()
    profile_utils.loginNDB(user)
    student = profile_utils.seedSOCStudent(self.program, user=user)
    proposal = proposal_utils.seedProposal(
        student.key, self.program.key(), org_key=self.org.key)

    suffix = "%s/%s/%d" % (
        self.gsoc.key().name(),
        student.key.parent().id(),
        proposal.key().id())

    # test review GET
    url = '/gsoc/proposal/review/' + suffix
    response = self.get(url)
    self.assertResponseOK(response)
    self.assertReviewTemplateUsed(response)

    self.assertNotContains(
        response,
        '<p class="status"><strong>Status:</strong> Pending</p>')

    # test comment POST
    from soc.modules.gsoc.models.comment import GSoCComment
    url = '/gsoc/proposal/comment/' + suffix
    override = {'author': student.key.to_old_key(), 'is_private': False}
    response, properties = self.modelPost(url, GSoCComment, override)
    self.assertResponseRedirect(response)

    comment = GSoCComment.all().ancestor(proposal).get()
    author_key = ndb.Key.from_old_key(
        GSoCComment.author.get_value_for_datastore(comment))
    self.assertEqual(author_key, student.key)

    # TODO(daniel): notifications
    # self.assertEmailSent(to=mentor.email)

    # TODO(daniel): add assertEmailNotSent to DjangoTestCase
    # self.assertEmailNotSent(to=self.profile_helper.profile.email)

    # login as a mentor
    profile_utils.loginNDB(mentor.key.parent().get())

    # test score POST
    from soc.modules.gsoc.models.score import GSoCScore
    url = '/gsoc/proposal/score/' + suffix
    override = {
        'author': mentor.key.to_old_key(), 'parent': proposal, 'value': 1}
    response, properties = self.modelPost(url, GSoCScore, override)
    self.assertResponseOK(response)

    score = GSoCScore.all().ancestor(proposal).get()
    author_key = ndb.Key.from_old_key(
        GSoCScore.author.get_value_for_datastore(score))
    self.assertEqual(author_key, mentor.key)
    self.assertEqual(1, score.value)

    proposal = GSoCProposal.all().get()
    self.assertEqual(1, proposal.score)
    self.assertEqual(1, proposal.nr_scores)

    # test updating score
    override['value'] = 4
    response, properties = self.modelPost(url, GSoCScore, override)
    self.assertResponseOK(response)

    proposal = GSoCProposal.get(proposal.key())
    self.assertEqual(4, proposal.score)
    self.assertEqual(1, proposal.nr_scores)

    # test removing score
    override['value'] = 0
    response, properties = self.modelPost(url, GSoCScore, override)
    self.assertResponseOK(response)

    proposal = GSoCProposal.get(proposal.key())
    self.assertEqual(0, proposal.score)
    self.assertEqual(0, proposal.nr_scores)
Ejemplo n.º 11
0
def convertGSoCProfileDBEntityGroup(profile_key):
    """Converts DB based part of entity group associated with the specified
  profile.

  Args:
    profile_key: db.Key of the profile to process
  """
    # map that associate old keys with new ones which are created during
    # the conversion
    conversion_map = {}
    to_delete = []
    do_put = True

    proposals = GSoCProposal.all().ancestor(profile_key).fetch(1000)
    for proposal in proposals:
        # update GSoCProposal.parent
        new_proposal = _convertParent(proposal)

        # update GSoCProposal.possible_mentors
        new_proposal.possible_mentors = _convertListProperty(
            GSoCProposal.possible_mentors, new_proposal)

        # update GSoCProposal.mentor
        new_proposal.mentor = _convertReferenceProperty(
            GSoCProposal.mentor, new_proposal)
        to_delete.append(proposal)
        if do_put:
            new_proposal.put()
            conversion_map[proposal.key()] = new_proposal.key()

        comments = GSoCComment.all().ancestor(proposal).fetch(1000)
        for comment in comments:
            # update GSoCComment.parent
            new_comment = _convertParent(comment, parent=new_proposal.key())

            # update GSoCComment.author
            new_comment.author = _convertReferenceProperty(
                GSoCComment.author, new_comment)
            if do_put:
                new_comment.put()
            to_delete.append(comment)

        scores = GSoCScore.all().ancestor(proposal).fetch(1000)
        for score in scores:
            # update GSoCScore.parent
            new_score = _convertParent(score, parent=new_proposal.key())

            # update GSoCScore.author
            new_score.author = _convertReferenceProperty(
                GSoCScore.author, new_score)
            if do_put:
                new_score.put()
            to_delete.append(score)

    projects = GSoCProject.all().ancestor(profile_key).fetch(1000)
    for project in projects:
        # update GSoCProject.parent
        new_project = _convertParent(project)

        # update GSoCProject.mentors
        new_project.mentors = _convertListProperty(GSoCProject.mentors,
                                                   new_project)

        # update GSoCProject.proposal
        proposal_key = GSoCProject.proposal.get_value_for_datastore(project)
        if proposal_key:
            new_project.proposal = conversion_map.get(
                GSoCProject.proposal.get_value_for_datastore(project))

        if do_put:
            new_project.put()
            conversion_map[project.key()] = new_project.key()
        to_delete.append(project)

        grading_records = GSoCGradingRecord.all().ancestor(project.key())
        for grading_record in grading_records:
            # update GSoCGradingProjectSurveyRecord.project
            # this is another entity group, but XG transaction does the thing
            grading_project_survey_record_key = (
                GSoCGradingRecord.mentor_record.get_value_for_datastore(
                    grading_record))
            if grading_project_survey_record_key:
                grading_project_survey_record = GSoCGradingProjectSurveyRecord.get(
                    grading_project_survey_record_key)
                if grading_project_survey_record:
                    grading_project_survey_record.project = new_project.key()
                    if do_put:
                        grading_project_survey_record.put()

            # update GSoCProjectSurveyRecord.project
            # this is another entity group, but XG transaction does the thing
            project_survey_record_key = (
                GSoCGradingRecord.student_record.get_value_for_datastore(
                    grading_record))
            if project_survey_record_key:
                project_survey_record = GSoCProjectSurveyRecord.get(
                    project_survey_record_key)
                if project_survey_record:
                    project_survey_record.project = new_project.key()
                    if do_put:
                        project_survey_record.put()

            # update GSoCGradingRecord.parent
            new_grading_record = _convertParent(grading_record,
                                                parent=new_project.key())
            if do_put:
                new_grading_record.put()

        code_samples = GSoCCodeSample.all().ancestor(project.key())
        for code_sample in code_samples:
            # update GSoCCodeSample.parent
            new_code_sample = _convertParent(code_sample,
                                             parent=new_project.key())
            if do_put:
                new_code_sample.put()
            to_delete.append(code_sample)

    db.delete(to_delete)
Ejemplo n.º 12
0
    def testReviewProposal(self):
        self.timeline_helper.studentSignup()
        # TODO(daniel): Re-seed settings when they are added.
        #  {'notify_new_proposals' :True, 'notify_public_comments': True,
        #   'notify_private_comments' :True}
        mentor = profile_utils.seedNDBProfile(self.program.key(),
                                              mentor_for=[self.org.key])

        user = profile_utils.seedNDBUser()
        profile_utils.loginNDB(user)
        student = profile_utils.seedSOCStudent(self.program, user=user)
        proposal = proposal_utils.seedProposal(student.key,
                                               self.program.key(),
                                               org_key=self.org.key)

        suffix = "%s/%s/%d" % (self.gsoc.key().name(),
                               student.key.parent().id(), proposal.key().id())

        # test review GET
        url = '/gsoc/proposal/review/' + suffix
        response = self.get(url)
        self.assertResponseOK(response)
        self.assertReviewTemplateUsed(response)

        self.assertNotContains(
            response, '<p class="status"><strong>Status:</strong> Pending</p>')

        # test comment POST
        from soc.modules.gsoc.models.comment import GSoCComment
        url = '/gsoc/proposal/comment/' + suffix
        override = {'author': student.key.to_old_key(), 'is_private': False}
        response, properties = self.modelPost(url, GSoCComment, override)
        self.assertResponseRedirect(response)

        comment = GSoCComment.all().ancestor(proposal).get()
        author_key = ndb.Key.from_old_key(
            GSoCComment.author.get_value_for_datastore(comment))
        self.assertEqual(author_key, student.key)

        # TODO(daniel): notifications
        # self.assertEmailSent(to=mentor.email)

        # TODO(daniel): add assertEmailNotSent to DjangoTestCase
        # self.assertEmailNotSent(to=self.profile_helper.profile.email)

        # login as a mentor
        profile_utils.loginNDB(mentor.key.parent().get())

        # test score POST
        from soc.modules.gsoc.models.score import GSoCScore
        url = '/gsoc/proposal/score/' + suffix
        override = {
            'author': mentor.key.to_old_key(),
            'parent': proposal,
            'value': 1
        }
        response, properties = self.modelPost(url, GSoCScore, override)
        self.assertResponseOK(response)

        score = GSoCScore.all().ancestor(proposal).get()
        author_key = ndb.Key.from_old_key(
            GSoCScore.author.get_value_for_datastore(score))
        self.assertEqual(author_key, mentor.key)
        self.assertEqual(1, score.value)

        proposal = GSoCProposal.all().get()
        self.assertEqual(1, proposal.score)
        self.assertEqual(1, proposal.nr_scores)

        # test updating score
        override['value'] = 4
        response, properties = self.modelPost(url, GSoCScore, override)
        self.assertResponseOK(response)

        proposal = GSoCProposal.get(proposal.key())
        self.assertEqual(4, proposal.score)
        self.assertEqual(1, proposal.nr_scores)

        # test removing score
        override['value'] = 0
        response, properties = self.modelPost(url, GSoCScore, override)
        self.assertResponseOK(response)

        proposal = GSoCProposal.get(proposal.key())
        self.assertEqual(0, proposal.score)
        self.assertEqual(0, proposal.nr_scores)