def testAcceptProposalButton(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() proposal = self.createProposal({'scope': student.profile, 'parent': student.profile}) suffix = "%s/%s/%d" % ( self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) self.data.createMentor(self.org) url = '/gsoc/proposal/accept/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) # fail if mentor tries to accept the proposal self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() self.assertFalse(proposal.accept_as_project) # accept the proposal as project when the org admin tries to accept # the proposal self.data.createOrgAdmin(self.org) response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertTrue(proposal.accept_as_project)
def testAcceptProposalButton(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() proposal = self.createProposal({ 'scope': student.profile, 'parent': student.profile }) suffix = "%s/%s/%d" % (self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) self.data.createMentor(self.org) url = '/gsoc/proposal/accept/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) # fail if mentor tries to accept the proposal self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() self.assertFalse(proposal.accept_as_project) # accept the proposal as project when the org admin tries to accept # the proposal self.data.createOrgAdmin(self.org) response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertTrue(proposal.accept_as_project)
def acceptProposals(self): """Set student proposals' acceptance state and make sure the organization has slots available. """ self.student1 = self.createStudent('*****@*****.**', n_proposals=2) self.student1_proposals = GSoCProposal.all().ancestor( self.student1.profile) self.student2 = self.createStudent('*****@*****.**', n_proposals=3) self.student2_proposals = GSoCProposal.all().ancestor( self.student2.profile) self.assertEqual(self.student1_proposals.count(), 2) self.assertEqual(self.student2_proposals.count(), 3) #accept 1 of 2 proposal of student1 proposal1 = self.student1_proposals[0] proposal1.accept_as_project = True proposal1.put() proposal2 = self.student1_proposals[1] proposal2.accept_as_project = False proposal2.put() #reject all proposals of student2 for proposal in self.student2_proposals: proposal.accept_as_project = False proposal.put() self.org.slots = 5 self.org.put() self.timeline.studentsAnnounced()
def acceptProposals(self): """Set student proposals' acceptance state and make sure the organization has slots available. """ self.student1 = self.createStudent('*****@*****.**', n_proposals=2) self.student1_proposals = GSoCProposal.all().ancestor( self.student1.profile) self.student2 = self.createStudent('*****@*****.**', n_proposals=3) self.student2_proposals = GSoCProposal.all().ancestor( self.student2.profile) self.assertEqual(self.student1_proposals.count(), 2) self.assertEqual(self.student2_proposals.count(), 3) #accept 1 of 2 proposal of student1 proposal1 = self.student1_proposals[0] proposal1.accept_as_project = True proposal1.put() proposal2 = self.student1_proposals[1] proposal2.accept_as_project = False proposal2.put() #reject all proposals of student2 for proposal in self.student2_proposals: proposal.accept_as_project = False proposal.put() self.org.slots = 5 self.org.put() self.timeline.studentsAnnounced()
def getProposalsToBeAcceptedForOrg(org_entity, step_size=25): """Returns all StudentProposals which will be accepted into the program for the given organization. params: org_entity: the Organization for which the proposals should be checked step_size: optional parameter to specify the amount of Student Proposals that should be retrieved per roundtrip to the datastore returns: List with all StudentProposal which will be accepted into the program """ # check if there are already slots taken by this org q = GSoCProposal.all() q.filter('org', org_entity) q.filter('status', 'accepted') slots_left_to_assign = max(0, org_entity.slots - q.count()) if slots_left_to_assign == 0: # no slots left so return nothing return [] q = GSoCProposal.all() q.filter('org', org_entity) q.filter('status', 'pending') q.filter('accept_as_project', True) q.filter('has_mentor', True) q.order('-score') # We are not putting this into the filter because order and != do not mix # in GAE. proposals = q.fetch(slots_left_to_assign) offset = slots_left_to_assign # retrieve as many additional proposals as needed in case the top # N do not have a mentor assigned while len(proposals) < slots_left_to_assign: new_proposals = q.fetch(step_size, offset=offset) if not new_proposals: # we ran out of proposals` break proposals += new_proposals offset += step_size # cut off any superfluous proposals return proposals[:slots_left_to_assign]
def testAssignMentor(self): student = profile_utils.seedSOCStudent(self.program) proposal = proposal_utils.seedProposal( student.key, self.program.key(), org_key=self.org.key, mentor=None) suffix = "%s/%s/%d" % ( self.gsoc.key().name(), student.profile_id, proposal.key().id()) user = profile_utils.seedNDBUser() profile_utils.loginNDB(user) mentor = profile_utils.seedNDBProfile( self.program.key(), user=user, mentor_for=[self.org.key]) url = '/gsoc/proposal/assign_mentor/' + suffix postdata = {'assign_mentor': mentor.key} response = self.post(url, postdata) self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() mentor_key = GSoCProposal.mentor.get_value_for_datastore(proposal) self.assertIsNone(mentor_key)
def getListData(self): idx = lists.getListIndex(self.request) if idx != 0: return None org = self.data.organization program = self.data.program # Hold all the accepted projects for orgs where this user is a member of accepted = [] # Hold all duplicates for either the entire program or the orgs of the user. duplicates = [] dupQ = GSoCProposalDuplicate.all() dupQ.filter('is_duplicate', True) dupQ.filter('org', org) dupQ.filter('program', program) accepted.extend([p.key() for p in getProposalsToBeAcceptedForOrg(org)]) duplicate_entities = dupQ.fetch(1000) for dup in duplicate_entities: duplicates.extend(dup.duplicates) q = GSoCProposal.all() q.filter('org', org) q.filter('program', program) starter = lists.keyStarter prefetcher = lists.modelPrefetcher(GSoCProposal, ['org'], parent=True) response_builder = lists.RawQueryContentResponseBuilder( self.request, self._list_config, q, starter, prefetcher=prefetcher) return response_builder.build(accepted, duplicates)
def testResubmitProposal(self): """Tests that a proposal is successfully resubmitted if possible.""" old_number_of_proposals = self.profile.student_data.number_of_proposals self.kwargs = { 'sponsor': self.sponsor.link_id, 'program': self.program.program_id, 'user': self.profile.profile_id, 'id': self.proposal.key().id() } request = http.HttpRequest() data = request_data.RequestData(request, None, self.kwargs) handler = proposal_review_view.ResubmitProposalHandler(None) with mock.patch.object(proposal_logic, 'canProposalBeResubmitted', return_value=True): response = handler.handle(data, None, None) self.assertEqual(response.status_code, httplib.OK) # check that the proposal is withdrawn proposal = GSoCProposal.all().get() self.assertEqual(proposal.status, proposal_model.STATUS_PENDING) # check that number of proposals is updated profile = self.profile.key.get() self.assertEqual(old_number_of_proposals, profile.student_data.number_of_proposals - 1)
def testAssignMentor(self): student = profile_utils.seedSOCStudent(self.program) proposal = proposal_utils.seedProposal(student.key, self.program.key(), org_key=self.org.key, mentor=None) suffix = "%s/%s/%d" % (self.gsoc.key().name(), student.profile_id, proposal.key().id()) user = profile_utils.seedNDBUser() profile_utils.loginNDB(user) mentor = profile_utils.seedNDBProfile(self.program.key(), user=user, mentor_for=[self.org.key]) url = '/gsoc/proposal/assign_mentor/' + suffix postdata = {'assign_mentor': mentor.key} response = self.post(url, postdata) self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() mentor_key = GSoCProposal.mentor.get_value_for_datastore(proposal) self.assertIsNone(mentor_key)
def getListData(self): idx = lists.getListIndex(self.data.request) if idx != 0: return None program = self.data.program # Hold all the accepted projects for orgs where this user is a member of accepted = [] # Hold all duplicates for either the entire program or the orgs of the user. duplicates = [] dupQ = GSoCProposalDuplicate.all() dupQ.filter('is_duplicate', True) dupQ.filter('org', self.data.url_ndb_org.key.to_old_key()) dupQ.filter('program', program) accepted.extend( p.key() for p in getProposalsToBeAcceptedForOrg(self.data.url_ndb_org)) duplicate_entities = dupQ.fetch(1000) for dup in duplicate_entities: duplicates.extend(dup.duplicates) q = GSoCProposal.all() q.filter('org', self.data.url_ndb_org.key.to_old_key()) q.filter('program', program) starter = lists.keyStarter # TODO(daniel): enable prefetching from ndb models ('org', 'parent') # prefetcher = lists.ModelPrefetcher(GSoCProposal, [], parent=True) response_builder = lists.RawQueryContentResponseBuilder( self.data.request, self._list_config, q, starter, prefetcher=None) return response_builder.build(accepted, duplicates)
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()
def testSubmitProposal(self): mentor = GSoCProfileHelper(self.gsoc, self.dev_test) mentor.createOtherUser('*****@*****.**') mentor.createMentor(self.org) mentor.notificationSettings( new_proposals=True, public_comments=True, private_comments=True) other_mentor = GSoCProfileHelper(self.gsoc, self.dev_test) other_mentor.createOtherUser('*****@*****.**') other_mentor.createMentor(self.org) other_mentor.notificationSettings() self.data.createStudent() self.data.notificationSettings() self.timeline.studentSignup() url = '/gsoc/proposal/submit/' + self.org.key().name() response = self.get(url) self.assertProposalTemplatesUsed(response) # test proposal POST override = { 'program': self.gsoc, 'score': 0, 'nr_scores': 0, 'mentor': None, 'org': self.org, 'status': 'pending', 'accept_as_project': False, 'is_editable_post_deadline': False, 'extra': None, 'has_mentor': False, } response, properties = self.modelPost(url, GSoCProposal, override) self.assertResponseRedirect(response) self.assertEmailSent(to=mentor.profile.email, n=1) self.assertEmailNotSent(to=other_mentor.profile.email) proposal = GSoCProposal.all().get() self.assertPropertiesEqual(properties, proposal)
def testResubmitProposal(self): """Tests that a proposal is successfully resubmitted if possible.""" old_number_of_proposals = self.profile.student_data.number_of_proposals self.kwargs = { 'sponsor': self.sponsor.link_id, 'program': self.program.program_id, 'user': self.profile.profile_id, 'id': self.proposal.key().id() } request = http.HttpRequest() data = request_data.RequestData(request, None, self.kwargs) handler = proposal_review_view.ResubmitProposalHandler(None) with mock.patch.object( proposal_logic, 'canProposalBeResubmitted', return_value=True): response = handler.handle(data, None, None) self.assertEqual(response.status_code, httplib.OK) # check that the proposal is withdrawn proposal = GSoCProposal.all().get() self.assertEqual(proposal.status, proposal_model.STATUS_PENDING) # check that number of proposals is updated profile = self.profile.key.get() self.assertEqual( old_number_of_proposals, profile.student_data.number_of_proposals - 1)
def testUpdateProposal(self): """Test update proposals. """ mentor = GSoCProfileHelper(self.gsoc, self.dev_test) mentor.createOtherUser('*****@*****.**') mentor.createMentor(self.org) mentor.notificationSettings(proposal_updates=True) self.data.createStudentWithProposal(self.org, mentor.profile) self.data.notificationSettings() self.timeline.studentSignup() proposal = GSoCProposal.all().get() url = '/gsoc/proposal/update/%s/%s' % (self.gsoc.key().name(), proposal.key().id()) response = self.get(url) self.assertProposalTemplatesUsed(response) override = { 'program': self.gsoc, 'score': 0, 'nr_scores': 0, 'has_mentor': True, 'mentor': mentor.profile, 'org': self.org, 'status': 'pending', 'action': 'Update', 'is_publicly_visible': False, 'extra': None, 'accept_as_project': False, 'is_editable_post_deadline': False } response, properties = self.modelPost(url, GSoCProposal, override) self.assertResponseRedirect(response) properties.pop('action') proposal = GSoCProposal.all().get() self.assertPropertiesEqual(properties, proposal) # after update last_modified_on should be updated which is not equal # to created_on self.assertNotEqual(proposal.created_on, proposal.last_modified_on) self.assertEmailSent(to=mentor.profile.email, n=1)
def testWishToMentorButton(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() self.data.createMentor(self.org) other_mentor = self.createMentorWithSettings( '*****@*****.**') proposal = self.createProposal({ 'scope': student.profile, 'parent': student.profile }) suffix = "%s/%s/%d" % (self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) url = '/gsoc/proposal/wish_to_mentor/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) proposal = GSoCProposal.all().get() self.assertTrue(self.data.profile.key() in proposal.possible_mentors) postdata = {'value': 'checked'} response = self.post(url, postdata) proposal = GSoCProposal.all().get() self.assertFalse(self.data.profile.key() in proposal.possible_mentors) other_mentor.profile.mentor_for = [] other_mentor.profile.put() proposal.possible_mentors.append(other_mentor.profile.key()) proposal.put() url = '/gsoc/proposal/review/' + suffix response = self.get(url) proposal = GSoCProposal.all().get() self.assertFalse( other_mentor.profile.key() in proposal.possible_mentors)
def postHandler(self, data, withdraw=True): program = self.data.program for properties in data: if "full_project_key" not in properties: logging.warning("Missing key in '%s'" % properties) continue project_key = properties["full_project_key"] project = db.get(db.Key(project_key)) if not project: logging.warning("Project '%s' doesn't exist" % project_key) continue if withdraw and project.status == "withdrawn": logging.warning("Project '%s' already withdrawn" % project_key) continue if not withdraw and project.status == "accepted": logging.warning("Project '%s' already accepted" % project_key) continue profile = project.parent() profile_key = profile.key() qp = GSoCProposal.all() qp.ancestor(profile_key) qp.filter("org", project.org) # FIXME: ??? Mentors can change overtime so how does this work??? qp.filter("mentor IN", project.mentors) if withdraw: qp.filter("status", "accepted") else: qp.filter("status", "withdrawn") proposal = qp.get() def withdraw_or_accept_project_txn(): if withdraw: new_status = "withdrawn" new_number = 0 else: new_status = "accepted" new_number = 1 project.status = new_status proposal.status = new_status profile.number_of_projects = new_number db.put([proposal, project, profile]) db.run_in_transaction(withdraw_or_accept_project_txn) return True
def testWishToMentorButton(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() self.data.createMentor(self.org) other_mentor = self.createMentorWithSettings('*****@*****.**') proposal = self.createProposal({'scope': student.profile, 'parent': student.profile}) suffix = "%s/%s/%d" % ( self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) url = '/gsoc/proposal/wish_to_mentor/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) proposal = GSoCProposal.all().get() self.assertTrue(self.data.profile.key() in proposal.possible_mentors) postdata = {'value': 'checked'} response = self.post(url, postdata) proposal = GSoCProposal.all().get() self.assertFalse(self.data.profile.key() in proposal.possible_mentors) other_mentor.profile.mentor_for = [] other_mentor.profile.put() proposal.possible_mentors.append(other_mentor.profile.key()) proposal.put() url = '/gsoc/proposal/review/' + suffix response = self.get(url) proposal = GSoCProposal.all().get() self.assertFalse(other_mentor.profile.key() in proposal.possible_mentors)
def createStudent(self): """Creates two new students the first one has a duplicate the second one has none. """ profile_helper = GSoCProfileHelper(self.gsoc, self.dev_test) profile_helper.createOtherUser('*****@*****.**') self.student1 = profile_helper.createStudentWithProposals( self.org, self.mentor, 3) proposals = GSoCProposal.all().ancestor(self.student1).fetch(2) for p in proposals: p.accept_as_project = True p.put() profile_helper = GSoCProfileHelper(self.gsoc, self.dev_test) profile_helper.createOtherUser('*****@*****.**') self.student2 = profile_helper.createStudentWithProposals( self.org, self.mentor, 1) proposal = GSoCProposal.all().ancestor(self.student2).get() proposal.accept_as_project = True proposal.put()
def createStudent(self): """Creates two new students the first one has a duplicate the second one has none. """ profile_helper = GSoCProfileHelper(self.gsoc, self.dev_test) profile_helper.createOtherUser('*****@*****.**') self.student1 = profile_helper.createStudentWithProposals( self.org, self.mentor, 3) proposals = GSoCProposal.all().ancestor(self.student1).fetch(2) for p in proposals: p.accept_as_project = True p.put() profile_helper = GSoCProfileHelper(self.gsoc, self.dev_test) profile_helper.createOtherUser('*****@*****.**') self.student2 = profile_helper.createStudentWithProposals( self.org, self.mentor, 1) proposal = GSoCProposal.all().ancestor(self.student2).get() proposal.accept_as_project = True proposal.put()
def canStudentPropose(self): """Checks if the student is eligible to submit a proposal. """ # check if the timeline allows submitting proposals self.studentSignupActive() # check how many proposals the student has already submitted query = GSoCProposal.all() query.filter('scope = ', self.data.profile).ancestor(self.data.user) if query.count() >= self.data.program.apps_tasks_limit: # too many proposals access denied raise AccessViolation(DEF_MAX_PROPOSALS_REACHED)
def testWithdrawProposalButton(self): self.data.createStudent() 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()) url = '/gsoc/proposal/withdraw/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertEqual(proposal.status, 'withdrawn') url = '/gsoc/proposal/withdraw/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseBadRequest(response) proposal = GSoCProposal.all().get() self.assertEqual(proposal.status, 'withdrawn') url = '/gsoc/proposal/withdraw/' + suffix postdata = {'value': 'checked'} response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertEqual(proposal.status, 'pending')
def testUpdateProposal(self): """Test update proposals. """ mentor = GSoCProfileHelper(self.gsoc, self.dev_test) mentor.createOtherUser('*****@*****.**') mentor.createMentor(self.org) mentor.notificationSettings(proposal_updates=True) self.data.createStudentWithProposal(self.org, mentor.profile) self.data.notificationSettings() self.timeline.studentSignup() proposal = GSoCProposal.all().get() url = '/gsoc/proposal/update/%s/%s' % ( self.gsoc.key().name(), proposal.key().id()) response = self.get(url) self.assertProposalTemplatesUsed(response) override = { 'program': self.gsoc, 'score': 0, 'nr_scores': 0, 'has_mentor': True, 'mentor': mentor.profile, 'org': self.org, 'status': 'pending', 'action': 'Update', 'is_publicly_visible': False, 'extra': None, 'accept_as_project': False, 'is_editable_post_deadline': False } response, properties = self.modelPost(url, GSoCProposal, override) self.assertResponseRedirect(response) properties.pop('action') proposal = GSoCProposal.all().get() self.assertPropertiesEqual(properties, proposal) # after update last_modified_on should be updated which is not equal # to created_on self.assertNotEqual(proposal.created_on, proposal.last_modified_on) self.assertEmailSent(to=mentor.profile.email, n=1)
def testWithdrawProposalButton(self): self.data.createStudent() 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()) url = '/gsoc/proposal/withdraw/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertEqual(proposal.status, 'withdrawn') url = '/gsoc/proposal/withdraw/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseBadRequest(response) proposal = GSoCProposal.all().get() self.assertEqual(proposal.status, 'withdrawn') url = '/gsoc/proposal/withdraw/' + suffix postdata = {'value': 'checked'} response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertEqual(proposal.status, 'pending')
def testUpdateProposal(self): """Test update proposals. """ self.data.createStudentWithProposal() self.timeline.studentSignup() proposal = GSoCProposal.all().get() url = "/gsoc/proposal/update/%s/%s" % (self.gsoc.key().name(), proposal.key().id()) response = self.client.get(url) self.assertProposalTemplatesUsed(response) override = {"program": self.gsoc, "score": 0, "mentor": None, "org": self.org, "status": "new"} response, properties = self.modelPost(url, GSoCProposal, override) self.assertResponseRedirect(response)
def testUpdateProposal(self): """Test update proposals. """ self.data.createStudentWithProposal() self.timeline.studentSignup() proposal = GSoCProposal.all().get() url = '/gsoc/proposal/update/%s/%s' % ( self.gsoc.key().name(), proposal.key().id()) response = self.client.get(url) self.assertProposalTemplatesUsed(response) override = {'program': self.gsoc, 'score': 0, 'mentor': None, 'org': self.org, 'status': 'new'} response, properties = self.modelPost(url, GSoCProposal, override) self.assertResponseRedirect(response)
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)
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)
def clear(*args, **kwargs): """Removes all entities from the datastore. """ # TODO(dbentley): If there are more than 1000 instances of any model, # this method will not clear all instances. Instead, it should continually # call .all(), delete all those, and loop until .all() is empty. entities = itertools.chain(*[ Survey.all(), SurveyRecord.all(), GCIOrganization.all(), GSoCTimeline.all(), GCITimeline.all(), GSoCProgram.all(), GSoCProject.all(), GSoCProposal.all(), GCIProgram.all(), GCIScore.all(), GSoCStudentInfo.all(), GCIStudentInfo.all(), GCITask.all(), Sponsor.all(), Site.all(), Document.all(), # The below models are all subclasses of ndb.Model and therefore must # use .query() to return all instances instead of .all(). soc_org_model.SOCOrganization.query(), profile_model.Profile.query(), soc_profile.SOCStudentData.query(), user.User.query(), address.Address.query(), contact.Contact.query() ]) try: for entity in entities: if isinstance(entity, ndb.Model): entity.key.delete() else: entity.delete() except db.Timeout: return http.HttpResponseRedirect('#') memcache.flush_all() return http.HttpResponse('Done')
def clear(*args, **kwargs): """Removes all entities from the datastore. """ # TODO(dbentley): If there are more than 1000 instances of any model, # this method will not clear all instances. Instead, it should continually # call .all(), delete all those, and loop until .all() is empty. entities = itertools.chain(*[ Survey.all(), SurveyRecord.all(), GCIOrganization.all(), GSoCTimeline.all(), GCITimeline.all(), GSoCProgram.all(), GSoCProject.all(), GSoCProposal.all(), GCIProgram.all(), GCIScore.all(), GSoCStudentInfo.all(), GCIStudentInfo.all(), GCITask.all(), Sponsor.all(), Site.all(), Document.all(), # The below models are all subclasses of ndb.Model and therefore must # use .query() to return all instances instead of .all(). soc_org_model.SOCOrganization.query(), profile_model.Profile.query(), soc_profile.SOCStudentData.query(), user.User.query(), address.Address.query(), contact.Contact.query() ]) try: for entity in entities: if isinstance(entity, ndb.Model): entity.key.delete() else: entity.delete() except db.Timeout: return http.HttpResponseRedirect('#') memcache.flush_all() return http.HttpResponse('Done')
def getListData(self): """Returns the list data as requested by the current request. If the lists as requested is not supported by this component None is returned. """ idx = lists.getListIndex(self.request) if idx == 4: q = GSoCProposal.all() q.filter('org IN', self.data.mentor_for) starter = lists.keyModelStarter(GSoCProposal) response_builder = lists.RawQueryContentResponseBuilder( self.request, self._list_config, q, starter, prefetch=['org']) return response_builder.build() else: return None
def getListData(self): """Returns the list data as requested by the current request. If the lists as requested is not supported by this component None is returned. """ idx = lists.getListIndex(self.request) if idx == 4: q = GSoCProposal.all() q.filter('org IN', self.data.mentor_for) starter = lists.keyModelStarter(GSoCProposal) response_builder = lists.RawQueryContentResponseBuilder( self.request, self._list_config, q, starter, prefetch=['org']) return response_builder.build() else: return None
def testPubliclyVisibleButton(self): self.data.createStudent() 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()) url = '/gsoc/proposal/publicly_visible/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertTrue(proposal.is_publicly_visible)
def clear(*args, **kwargs): """Removes all entities from the datastore. """ # TODO(dbentley): If there are more than 1000 instances of any model, # this method will not clear all instances. Instead, it should continually # call .all(), delete all those, and loop until .all() is empty. entities = itertools.chain(*[ Notification.all(), GCIStudent.all(), Survey.all(), SurveyRecord.all(), StudentProposal.all(), GSoCOrganization.all(), GCIOrganization.all(), GSoCTimeline.all(), GCITimeline.all(), GSoCProgram.all(), GSoCProfile.all(), GCIProfile.all(), GSoCProposal.all(), GCIProgram.all(), GCIScore.all(), GSoCStudentInfo.all(), GCIStudentInfo.all(), GCITask.all(), Host.all(), Sponsor.all(), User.all(), Site.all(), Document.all(), ]) try: for entity in entities: entity.delete() except db.Timeout: return http.HttpResponseRedirect('#') # pylint: disable=E1101 memcache.flush_all() return http.HttpResponse('Done')
def testPubliclyVisibleButton(self): self.data.createStudent() 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()) url = '/gsoc/proposal/publicly_visible/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertTrue(proposal.is_publicly_visible)
def testSubmitProposal(self): mentor = GSoCProfileHelper(self.gsoc, self.dev_test) mentor.createOtherUser('*****@*****.**') mentor.createMentor(self.org) mentor.notificationSettings(new_proposals=True, public_comments=True, private_comments=True) other_mentor = GSoCProfileHelper(self.gsoc, self.dev_test) other_mentor.createOtherUser('*****@*****.**') other_mentor.createMentor(self.org) other_mentor.notificationSettings() self.data.createStudent() self.data.notificationSettings() self.timeline.studentSignup() url = '/gsoc/proposal/submit/' + self.org.key().name() response = self.get(url) self.assertProposalTemplatesUsed(response) # test proposal POST override = { 'program': self.gsoc, 'score': 0, 'nr_scores': 0, 'mentor': None, 'org': self.org, 'status': 'pending', 'accept_as_project': False, 'is_editable_post_deadline': False, 'extra': None, 'has_mentor': False, } response, properties = self.modelPost(url, GSoCProposal, override) self.assertResponseRedirect(response) self.assertEmailSent(to=mentor.profile.email, n=1) self.assertEmailNotSent(to=other_mentor.profile.email) proposal = GSoCProposal.all().get() self.assertPropertiesEqual(properties, proposal)
def process(student_info): logging.debug("Converting student_info '%r'" % student_info.key()) proposals = GSoCProposal.all().ancestor(student_info.parent_key()).fetch(1000) projects = GSoCProject.all().ancestor(student_info.parent_key()).fetch(1000) proposals = [i for i in proposals if i.status != 'withdrawn'] projects = [i for i in projects if i.status != 'withdrawn'] nr_proposals = len(proposals) nr_projects = len(projects) orgs = [GSoCProject.org.get_value_for_datastore(i) for i in projects] student_info.number_of_proposals = nr_proposals student_info.number_of_projects = nr_projects student_info.project_for_orgs = orgs yield operation.db.Put(student_info) yield operation.counters.Increment("student_infos_converted") yield operation.counters.Increment("proposals_counted", delta=nr_proposals) yield operation.counters.Increment("projects_counted", delta=nr_projects)
def _processEntity(self, entity): profile = entity.parent() project = GSoCProject.all().ancestor(profile).get() properties = { 'school_name': entity.school_name, 'school_country': entity.school_country, 'school_home_page': entity.school_home_page, 'school_type': entity.school_type, 'major': entity.major, 'degree': entity.degree, 'expected_graduation': entity.expected_graduation, 'number_of_proposals': GSoCProposal.all().ancestor(profile).count(), 'number_of_projects': 1 if project is not None else 0, 'project_for_orgs': [project.org.key()] if project else [] } studentInfo = GSoCStudentInfo(key_name = profile.key().name(), parent=profile, **properties) profile.student_info = studentInfo db.run_in_transaction(db.put, [profile, studentInfo])
def testAssignMentor(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() proposal = self.createProposal({ 'scope': student.profile, 'parent': student.profile }) suffix = "%s/%s/%d" % (self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) self.data.createMentor(self.org) url = '/gsoc/proposal/assign_mentor/' + suffix postdata = {'assign_mentor': self.data.profile.key()} response = self.post(url, postdata) self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() self.assertEqual(proposal.mentor, None)
def process(student_info): logging.debug("Converting student_info '%r'", student_info.key()) proposals = GSoCProposal.all().ancestor( student_info.parent_key()).fetch(1000) projects = GSoCProject.all().ancestor( student_info.parent_key()).fetch(1000) proposals = [i for i in proposals if i.status != 'withdrawn'] projects = [i for i in projects if i.status != 'withdrawn'] nr_proposals = len(proposals) nr_projects = len(projects) orgs = [GSoCProject.org.get_value_for_datastore(i) for i in projects] student_info.number_of_proposals = nr_proposals student_info.number_of_projects = nr_projects student_info.project_for_orgs = orgs yield operation.db.Put(student_info) yield operation.counters.Increment("student_infos_converted") yield operation.counters.Increment("proposals_counted", delta=nr_proposals) yield operation.counters.Increment("projects_counted", delta=nr_projects)
def testIgnoreProposalButton(self): student = profile_utils.seedSOCStudent(self.program) proposal = proposal_utils.seedProposal(student.key, self.program.key(), org_key=self.org.key) suffix = "%s/%s/%d" % (self.gsoc.key().name(), student.profile_id, proposal.key().id()) user = profile_utils.seedNDBUser() profile_utils.loginNDB(user) profile_utils.seedNDBProfile(self.program.key(), user=user, mentor_for=[self.org.key]) url = '/gsoc/proposal/ignore/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() self.assertNotEqual(proposal.status, 'ignored')
def testIgnoreProposalButton(self): student = profile_utils.seedSOCStudent(self.program) proposal = proposal_utils.seedProposal( student.key, self.program.key(), org_key=self.org.key) suffix = "%s/%s/%d" % ( self.gsoc.key().name(), student.profile_id, proposal.key().id()) user = profile_utils.seedNDBUser() profile_utils.loginNDB(user) profile_utils.seedNDBProfile( self.program.key(), user=user, mentor_for=[self.org.key]) url = '/gsoc/proposal/ignore/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() self.assertNotEqual(proposal.status, 'ignored')
def testIgnoreProposalButton(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() proposal = self.createProposal({ 'scope': student.profile, 'parent': student.profile }) suffix = "%s/%s/%d" % (self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) self.data.createMentor(self.org) url = '/gsoc/proposal/ignore/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() self.assertNotEqual(proposal.status, 'ignored')
def testProposalModificationButton(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() proposal = self.createProposal({ 'scope': student.profile, 'parent': student.profile }) suffix = "%s/%s/%d" % (self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) self.data.createMentor(self.org) url = '/gsoc/proposal/modification/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertTrue(proposal.is_editable_post_deadline)
def testAssignMentor(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() proposal = self.createProposal({'scope': student.profile, 'parent': student.profile}) suffix = "%s/%s/%d" % ( self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) self.data.createMentor(self.org) url = '/gsoc/proposal/assign_mentor/' + suffix postdata = {'assign_mentor': self.data.profile.key()} response = self.post(url, postdata) self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() self.assertEqual(proposal.mentor, None)
def testProposalModificationButton(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() proposal = self.createProposal({'scope': student.profile, 'parent': student.profile}) suffix = "%s/%s/%d" % ( self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) self.data.createMentor(self.org) url = '/gsoc/proposal/modification/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseOK(response) proposal = GSoCProposal.all().get() self.assertTrue(proposal.is_editable_post_deadline)
def testIgnoreProposalButton(self): student = GSoCProfileHelper(self.gsoc, self.dev_test) student.createOtherUser('*****@*****.**') student.createStudent() proposal = self.createProposal({'scope': student.profile, 'parent': student.profile}) suffix = "%s/%s/%d" % ( self.gsoc.key().name(), student.user.key().name(), proposal.key().id()) self.data.createMentor(self.org) url = '/gsoc/proposal/ignore/' + suffix postdata = {'value': 'unchecked'} response = self.post(url, postdata) self.assertResponseForbidden(response) proposal = GSoCProposal.all().get() self.assertNotEqual(proposal.status, 'ignored')
def getListData(self): idx = lists.getListIndex(self.data.request) if idx != 0: return None program = self.data.program # Hold all the accepted projects for orgs where this user is a member of accepted = [] # Hold all duplicates for either the entire program or the orgs of the user. duplicates = [] dupQ = GSoCProposalDuplicate.all() dupQ.filter('is_duplicate', True) dupQ.filter('org', self.data.url_ndb_org.key.to_old_key()) dupQ.filter('program', program) accepted.extend( p.key() for p in getProposalsToBeAcceptedForOrg(self.data.url_ndb_org)) duplicate_entities = dupQ.fetch(1000) for dup in duplicate_entities: duplicates.extend(dup.duplicates) q = GSoCProposal.all() q.filter('org', self.data.url_ndb_org.key.to_old_key()) q.filter('program', program) starter = lists.keyStarter # TODO(daniel): enable prefetching from ndb models ('org', 'parent') # prefetcher = lists.ModelPrefetcher(GSoCProposal, [], parent=True) response_builder = lists.RawQueryContentResponseBuilder( self.data.request, self._list_config, q, starter, prefetcher=None) return response_builder.build(accepted, duplicates)
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)
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)
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)
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)
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)
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)