def testGetProposalsToBeAcceptedForOrg(self): """Tests if all GSoCProposals to be accepted into a program for a given organization are returned. """ #Test that for organization which has been allotted all its slots, an empty #list is returned. org = self.foo_organization expected = [] actual = proposal_logic.getProposalsToBeAcceptedForOrg(org) self.assertEqual(expected, actual) #Test that for an organization which has empty slots, only accepted #proposals are returned. We have both accepted and rejected proposals for #bar_organization. org = self.bar_organization expected_proposals_entities = self.bar_to_be_accepted_proposals expected = set([prop.key() for prop in expected_proposals_entities]) actual_proposals_entities = proposal_logic.getProposalsToBeAcceptedForOrg(org) actual = set([prop.key() for prop in actual_proposals_entities]) self.assertEqual(expected, actual) #Since self.happy_organization has more accepted projects than the available #slots, a proposal with a higher score should be returned. actual_proposals_entities = proposal_logic.getProposalsToBeAcceptedForOrg( self.happy_organization) actual = [prop.key() for prop in actual_proposals_entities] expected = [self.happy_accepted_proposals[1].key()] self.assertEqual(actual, expected) #Create an organization which has empty slots but no accepted projects. properties = {'scope': self.program, 'slots': 5} organization = seeder_logic.seed(GSoCOrganization, properties) expected = [] actual = proposal_logic.getProposalsToBeAcceptedForOrg(organization) self.assertEqual(actual, expected)
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 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 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()
def testGetProposalsToBeAcceptedForOrg(self): """Tests if all GSoCProposals to be accepted into a program for a given organization are returned. """ #Test that for organization which has been allotted all its slots, an empty #list is returned. expected = [] actual = proposal_logic.getProposalsToBeAcceptedForOrg( self.foo_organization) self.assertEqual(expected, actual) #Test that for an organization which has empty slots, only accepted #proposals are returned. We have both accepted and rejected proposals for #bar_organization. expected_proposals_entities = self.bar_to_be_accepted_proposals expected = set([prop.key() for prop in expected_proposals_entities]) actual_proposals_entities = ( proposal_logic.getProposalsToBeAcceptedForOrg( self.bar_organization)) actual = set([prop.key() for prop in actual_proposals_entities]) self.assertEqual(expected, actual) #Since self.happy_organization has more accepted projects than the available #slots, a proposal with a higher score should be returned. actual_proposals_entities = proposal_logic.getProposalsToBeAcceptedForOrg( self.happy_organization) actual = [prop.key() for prop in actual_proposals_entities] expected = [self.happy_accepted_proposals[1].key()] self.assertEqual(actual, expected) # Create an organization which has empty slots but no accepted projects. organization = org_utils.seedSOCOrganization(self.program.key(), slot_allocation=5) expected = [] actual = proposal_logic.getProposalsToBeAcceptedForOrg(organization) self.assertEqual(actual, expected)
def calculate(self, request, *args, **kwargs): """Calculates the duplicate proposals in a given program for a student on a per Organization basis. Expects the following to be present in the POST dict: program_key: Specifies the program key name for which to find the duplicate proposals org_cursor: Specifies the organization datastore cursor from which to start the processing of finding the duplicate proposals Args: request: Django Request object """ post_dict = request.POST program_key = post_dict.get('program_key') if not program_key: # invalid task data, log and return OK return error_handler.logErrorAndReturnOK( 'Invalid program key: %s' % post_dict) program_entity = GSoCProgram.get_by_key_name(program_key) if not program_entity: # invalid program specified, log and return OK return error_handler.logErrorAndReturnOK( 'Invalid program specified: %s' % program_key) # get the organization and update the cursor if possible q = GSoCOrganization.all() q.filter('status', 'active') q.filter('scope', program_entity) q.filter('slots >', 0) # retrieve the org_cursor from POST data org_cursor = post_dict.get('org_cursor') if org_cursor: org_cursor = str(org_cursor) q.with_cursor(org_cursor) org_entity = q.get() # update the cursor org_cursor = q.cursor() if org_entity: # get all the proposals likely to be accepted in the program accepted_proposals = proposal_logic.getProposalsToBeAcceptedForOrg(org_entity) for ap in accepted_proposals: student_entity = ap.parent() q = GSoCProposalDuplicate.all() q.filter('student', student_entity) proposal_duplicate = q.get() if proposal_duplicate and ap.key() not in proposal_duplicate.duplicates: # non-counted (to-be) accepted proposal found proposal_duplicate.duplicates = proposal_duplicate.duplicates + \ [ap.key()] proposal_duplicate.is_duplicate = \ len(proposal_duplicate.duplicates) >= 2 if org_entity.key() not in proposal_duplicate.orgs: proposal_duplicate.orgs = proposal_duplicate.orgs + [org_entity.key()] else: pd_fields = { 'program': program_entity, 'student': student_entity, 'orgs':[org_entity.key()], 'duplicates': [ap.key()], 'is_duplicate': False } proposal_duplicate = GSoCProposalDuplicate(**pd_fields) proposal_duplicate.put() # Adds a new task that performs duplicate calculation for # the next organization. task_params = {'program_key': program_key, 'org_cursor': unicode(org_cursor)} task_url = '/tasks/gsoc/proposal_duplicates/calculate' new_task = taskqueue.Task(params=task_params, url=task_url) new_task.add() else: # There aren't any more organizations to process. So delete # all the proposals for which there are not more than one # proposal for duplicates property. duplicates_logic.deleteAllForProgram(program_entity, non_dupes_only=True) # update the proposal duplicate status and its timestamp pds_entity = duplicates_logic.getOrCreateStatusForProgram(program_entity) pds_entity.status = 'idle' pds_entity.calculated_on = datetime.datetime.now() pds_entity.put() # return OK return http.HttpResponse()
def calculate(self, request, *args, **kwargs): """Calculates the duplicate proposals in a given program for a student on a per Organization basis. Expects the following to be present in the POST dict: program_key: Specifies the program key name for which to find the duplicate proposals org_cursor: Specifies the organization datastore cursor from which to start the processing of finding the duplicate proposals Args: request: Django Request object """ post_dict = request.POST program_key = post_dict.get('program_key') if not program_key: # invalid task data, log and return OK return error_handler.logErrorAndReturnOK( 'Invalid program key: %s' % post_dict) program_entity = GSoCProgram.get_by_key_name(program_key) if not program_entity: # invalid program specified, log and return OK return error_handler.logErrorAndReturnOK( 'Invalid program specified: %s' % program_key) # get the organization and update the cursor if possible query = soc_org_model.SOCOrganization.query( soc_org_model.SOCOrganization.status == org_model.Status.ACCEPTED, soc_org_model.SOCOrganization.program == ndb.Key.from_old_key(program_entity.key()), soc_org_model.SOCOrganization.slot_allocation > 0) # retrieve the org_cursor from POST data org_cursor = post_dict.get('org_cursor') start_cursor = ( datastore_query.Cursor(urlsafe=org_cursor) if org_cursor else None) organizations, next_cursor, _ = query.fetch_page( 1, start_cursor=start_cursor) if organizations: organization = organizations[0] # get all the proposals likely to be accepted in the program accepted_proposals = ( proposal_logic.getProposalsToBeAcceptedForOrg(organization)) for accepted_proposal in accepted_proposals: q = GSoCProposalDuplicate.all() q.filter('student', accepted_proposal.parent_key()) proposal_duplicate = q.get() if (proposal_duplicate and accepted_proposal.key() not in proposal_duplicate.duplicates): # non-counted (to-be) accepted proposal found proposal_duplicate.duplicates = proposal_duplicate.duplicates + \ [accepted_proposal.key()] proposal_duplicate.is_duplicate = \ len(proposal_duplicate.duplicates) >= 2 if organization.key.to_old_key() not in proposal_duplicate.orgs: proposal_duplicate.orgs = ( proposal_duplicate.orgs + [organization.key.to_old_key()]) else: pd_fields = { 'program': program_entity, 'student': accepted_proposal.parent_key(), 'orgs':[organization.key.to_old_key()], 'duplicates': [accepted_proposal.key()], 'is_duplicate': False } proposal_duplicate = GSoCProposalDuplicate(**pd_fields) proposal_duplicate.put() # Adds a new task that performs duplicate calculation for # the next organization. task_params = { 'program_key': program_key, 'org_cursor': next_cursor.urlsafe() } task_url = '/tasks/gsoc/proposal_duplicates/calculate' new_task = taskqueue.Task(params=task_params, url=task_url) new_task.add() else: # There aren't any more organizations to process. So delete # all the proposals for which there are not more than one # proposal for duplicates property. duplicates_logic.deleteAllForProgram(program_entity, non_dupes_only=True) # update the proposal duplicate status and its timestamp pds_entity = duplicates_logic.getOrCreateStatusForProgram(program_entity) pds_entity.status = 'idle' pds_entity.calculated_on = datetime.datetime.now() pds_entity.put() # return OK return http.HttpResponse()
def calculate(self, request, *args, **kwargs): """Calculates the duplicate proposals in a given program for a student on a per Organization basis. Expects the following to be present in the POST dict: program_key: Specifies the program key name for which to find the duplicate proposals org_cursor: Specifies the organization datastore cursor from which to start the processing of finding the duplicate proposals Args: request: Django Request object """ post_dict = request.POST program_key = post_dict.get('program_key') if not program_key: # invalid task data, log and return OK return error_handler.logErrorAndReturnOK( 'Invalid program key: %s' % post_dict) program_entity = GSoCProgram.get_by_key_name(program_key) if not program_entity: # invalid program specified, log and return OK return error_handler.logErrorAndReturnOK( 'Invalid program specified: %s' % program_key) # get the organization and update the cursor if possible query = soc_org_model.SOCOrganization.query( soc_org_model.SOCOrganization.status == org_model.Status.ACCEPTED, soc_org_model.SOCOrganization.program == ndb.Key.from_old_key( program_entity.key()), soc_org_model.SOCOrganization.slot_allocation > 0) # retrieve the org_cursor from POST data org_cursor = post_dict.get('org_cursor') start_cursor = (datastore_query.Cursor( urlsafe=org_cursor) if org_cursor else None) organizations, next_cursor, _ = query.fetch_page( 1, start_cursor=start_cursor) if organizations: organization = organizations[0] # get all the proposals likely to be accepted in the program accepted_proposals = ( proposal_logic.getProposalsToBeAcceptedForOrg(organization)) for accepted_proposal in accepted_proposals: q = GSoCProposalDuplicate.all() q.filter('student', accepted_proposal.parent_key()) proposal_duplicate = q.get() if (proposal_duplicate and accepted_proposal.key() not in proposal_duplicate.duplicates): # non-counted (to-be) accepted proposal found proposal_duplicate.duplicates = proposal_duplicate.duplicates + \ [accepted_proposal.key()] proposal_duplicate.is_duplicate = \ len(proposal_duplicate.duplicates) >= 2 if organization.key.to_old_key( ) not in proposal_duplicate.orgs: proposal_duplicate.orgs = ( proposal_duplicate.orgs + [organization.key.to_old_key()]) else: pd_fields = { 'program': program_entity, 'student': accepted_proposal.parent_key(), 'orgs': [organization.key.to_old_key()], 'duplicates': [accepted_proposal.key()], 'is_duplicate': False } proposal_duplicate = GSoCProposalDuplicate(**pd_fields) proposal_duplicate.put() # Adds a new task that performs duplicate calculation for # the next organization. task_params = { 'program_key': program_key, 'org_cursor': next_cursor.urlsafe() } task_url = '/tasks/gsoc/proposal_duplicates/calculate' new_task = taskqueue.Task(params=task_params, url=task_url) new_task.add() else: # There aren't any more organizations to process. So delete # all the proposals for which there are not more than one # proposal for duplicates property. duplicates_logic.deleteAllForProgram(program_entity, non_dupes_only=True) # update the proposal duplicate status and its timestamp pds_entity = duplicates_logic.getOrCreateStatusForProgram( program_entity) pds_entity.status = 'idle' pds_entity.calculated_on = datetime.datetime.now() pds_entity.put() # return OK return http.HttpResponse()