def test_invalid_range_multiple_ranges(self): with self.assertRaises(InvalidStageInputError): emapaStageParser("1-10-4") with self.assertRaises(InvalidStageInputError): emapaStageParser("1--4")
def test_invalid_integer(self): """ non-integer should throw custom exception """ with self.assertRaises(InvalidStageInputError): emapaStageParser("b")
def test_wildcard_all(self): stages = emapaStageParser("all") expected = range(1,29) self.assertEqual(expected, stages) stages = emapaStageParser("ALL") self.assertEqual(expected, stages)
def test_invalid_range_non_integer(self): with self.assertRaises(InvalidStageInputError): emapaStageParser("1-b") with self.assertRaises(InvalidStageInputError): emapaStageParser("b-10") with self.assertRaises(InvalidStageInputError): emapaStageParser("x-z")
def test_invalid_range_empty_range(self): with self.assertRaises(InvalidStageInputError): emapaStageParser(" -4") with self.assertRaises(InvalidStageInputError): emapaStageParser("10 - ") with self.assertRaises(InvalidStageInputError): emapaStageParser(" - ")
def add_items(self, _user_key, emapa_id, stages_to_add): """ Parse stages_to_add into list of stages throws InvalidStageInputError on invalid input Adds clipboard record for every emapa_id, stage combo """ # find vocterm record emapa_term = self.vocterm_dao.get_by_primary_id(emapa_id) if not emapa_term: raise InvalidEMAPAIDError("Cannot find term for EMAPA ID: %s" % emapa_id) # parse stage input stages = emapaStageParser(stages_to_add) added_items = [] for stage in stages: # only add stages valid for this term if stage >= emapa_term.emapa_info.startstage \ and stage <= emapa_term.emapa_info.endstage: set_member = self.add_item(_user_key, emapa_term._term_key, stage) added_items.append(set_member) else: if "*" not in stages_to_add and "all" not in stages_to_add.lower(): raise InvalidStageInputError("%s is invalid for range %d-%d for %s(%s)" % \ (stage, emapa_term.emapa_info.startstage, emapa_term.emapa_info.endstage, emapa_term.term, emapa_id) ) if added_items: # adding a duplicate can cause sequencenums to have gaps # so we normalize them here # This is necessary, because EI requires sequencenums without gaps self.clipboard_dao.normalize_sequencenums(_user_key) return added_items
def test_range_input_same_stage(self): stages = emapaStageParser("10-10") expected = [10] self.assertEqual(expected, stages)
def test_range_input(self): stages = emapaStageParser("7-10") expected = [7, 8, 9, 10] self.assertEqual(expected, stages)
def test_list_input_unique(self): stages = emapaStageParser("1, 10, 10, 10, 20") expected = [1, 10, 20] self.assertEqual(expected, stages)
def test_list_input(self): stages = emapaStageParser("1, 11, 10") expected = [1, 11, 10] self.assertEqual(expected, stages)
def test_single_stage(self): stages = emapaStageParser("10") expected = [10] self.assertEqual(expected, stages)
def test_wildcard_in_list (self): stages = emapaStageParser("1, *, 20") expected = range(1,29) self.assertEqual(expected, stages)
def test_wildcard_asterisk(self): stages = emapaStageParser("*") expected = range(1,29) self.assertEqual(expected, stages)
def test_range_and_list(self): stages = emapaStageParser("1, 5-7, 20, 22-24") expected = [1, 5,6,7, 20, 22,23,24] self.assertEqual(expected, stages)
def test_invalid_range_left_greater_than_right(self): with self.assertRaises(InvalidStageInputError): emapaStageParser("10 - 2")
def test_empty_input(self): stages = emapaStageParser("") expected = [] self.assertEqual(expected, stages)
def _build_search_query(self, search_query): query = VocTerm.query if search_query.has_valid_param("isobsolete"): isobsolete = search_query.get_value("isobsolete") query = query.filter(VocTerm.isobsolete==isobsolete) if search_query.has_valid_param("_vocab_key"): query = query.filter(VocTerm._vocab_key==search_query.get_value("_vocab_key")) if search_query.has_valid_param("_term_key"): query = query.filter(VocTerm._term_key==search_query.get_value("_term_key")) if search_query.has_valid_param("term"): term = search_query.get_value("term") term = term.lower() query = query.filter(db.func.lower(VocTerm.term)==term) if search_query.has_valid_param("vocab_name"): vocab_name = search_query.get_value("vocab_name") vocab_name = vocab_name.lower() vocab_alias = db.aliased(Vocab) query = query.join(vocab_alias, VocTerm.vocab) query = query.filter(db.func.lower(vocab_alias.name)==vocab_name) # Specific to EMAPA Browser stage searching if search_query.has_valid_param('stageSearch'): stageSearch = search_query.get_value('stageSearch') stages = emapaStageParser(stageSearch) if stages: stages = [int(stage) for stage in stages] emapa_alias = db.aliased(VocTermEMAPA) emaps_alias = db.aliased(VocTermEMAPS) sub_term = db.aliased(VocTerm) sq = db.session.query(sub_term) \ .join(emapa_alias, sub_term.emapa_info) \ .join(emaps_alias, emapa_alias.emaps_infos) \ .filter(emaps_alias._stage_key.in_(stages)) \ .filter(sub_term._term_key==VocTerm._term_key) \ .correlate(VocTerm) query = query.filter(sq.exists()) # Specific to EMAPA Browser term searching if search_query.has_valid_param('termSearch'): termSearch = search_query.get_value('termSearch') termSearch = termSearch.lower() termsToSearch = splitSemicolonInput(termSearch) # query IDs, terms, and synonyms then UNION all # search accession ID accession_alias = db.aliased(Accession) sub_term1 = db.aliased(VocTerm) id_sq = db.session.query(sub_term1) \ .join(accession_alias, sub_term1.all_accession_ids) \ .filter(db.func.lower(accession_alias.accid).in_(termsToSearch)) \ .filter(sub_term1._term_key==VocTerm._term_key) \ .correlate(VocTerm) # search terms sub_term2 = db.aliased(VocTerm) term_sq = db.session.query(sub_term2) \ .filter(db.or_( db.func.lower(VocTerm.term).like(term) for term in termsToSearch \ )) \ .filter(sub_term2._term_key==VocTerm._term_key) \ .correlate(VocTerm) # search synonyms synonym_alias = db.aliased(Synonym) sub_term3 = db.aliased(VocTerm) synonym_sq = db.session.query(sub_term3) \ .join(synonym_alias, sub_term3.synonyms) \ .filter(db.or_( db.func.lower(synonym_alias.synonym).like(term) for term in termsToSearch \ )) \ .filter(sub_term3._term_key==VocTerm._term_key) \ .correlate(VocTerm) # perform union query1 = query.filter(id_sq.exists()) query2 = query.filter(term_sq.exists()) query3 = query.filter(synonym_sq.exists()) query = query1.union(query2).union(query3) # handle sorts sorts = [] if len(search_query.sorts) > 0: for sort_name in search_query.sorts: if sort_name == "sequencenum": sorts.append(VocTerm.sequencenum.asc()) elif sort_name == "term": sorts.append(VocTerm.term.asc()) else: sorts.append(VocTerm.sequencenum.asc()) query = query.order_by(*sorts) return query