def testListReferenceBasesPaging(self): referenceSet = self.backend.getReferenceSets()[0] reference = referenceSet.getReferences()[0] id_ = reference.getId() length = reference.getLength() completeSequence = reference.getBases(0, length) for start, end in [(0, length), (5, 10), (length // 2, length)]: sequence = completeSequence[start:end] for pageSize in [1, 2, length - 1]: self.backend.setMaxResponseLength(pageSize) args = protocol.ListReferenceBasesRequest() args.start, args.end = start, end response = self.sendListReferenceBasesRequest(id_, args) self.assertEqual(response.sequence, sequence[:pageSize]) self.assertEqual(response.offset, start) sequenceFragments = [response.sequence] while response.nextPageToken is not None: args = protocol.ListReferenceBasesRequest() args.pageToken = response.nextPageToken args.start, args.end = start, end response = self.sendListReferenceBasesRequest(id_, args) self.assertGreater(len(response.sequence), 0) sequenceFragments.append(response.sequence) offset = response.offset self.assertEqual( response.sequence, completeSequence[offset:offset + len(response.sequence)]) self.assertEqual("".join(sequenceFragments), sequence)
def sendReferenceBasesList(self, id_=None): if id_ is None: id_ = self.referenceId path = "/references/{}/bases".format(id_) request = protocol.ListReferenceBasesRequest() response = self.sendListRequest(path, request) return response
def testRunListRequest(self): # setup mockGet = mock.Mock() with mock.patch('requests.request', mockGet): text = { "offset": 123, "sequence": "sequence", "nextPageToken": "pageTok", } mockGet.side_effect = [ DummyResponse(json.dumps(text)), DummyResponse('{}')] protocolRequest = protocol.ListReferenceBasesRequest() protocolRequest.start = 1 protocolRequest.end = 5 url = "references/{id}/bases" protocolResponseClass = protocol.ListReferenceBasesResponse id_ = 'myId' # invoke SUT result = [base for base in self.httpClient.runListRequest( protocolRequest, url, protocolResponseClass, id_)] # verify results of invocation self.assertEqual(len(result), 2) self.assertEqual(result[0].offset, 123) self.assertEqual(result[0].sequence, "sequence") # verify requests.get called correctly url = "http://example.com/references/myId/bases" params = {"start": 1, "end": 5} httpMethod = 'GET' mockGet.assert_called_twice_with(httpMethod, url, params=params)
def testReferences(self): # search for reference sets path = utils.applyVersion('/referencesets/search') request = protocol.SearchReferenceSetsRequest() response = self.sendJsonPostRequest(path, request.toJsonString()) self.assertEqual(response.status_code, 200) responseData = protocol.SearchReferenceSetsResponse.fromJsonString( response.data) referenceSets = responseData.referenceSets self.assertEqual(self.numReferenceSets, len(referenceSets)) # search for references path = utils.applyVersion('/references/search') request = protocol.SearchReferencesRequest() response = self.sendJsonPostRequest(path, request.toJsonString()) self.assertEqual(response.status_code, 200) responseData = protocol.SearchReferencesResponse.fromJsonString( response.data) references = responseData.references self.assertEqual( self.numReferenceSets * self.numReferencesPerReferenceSet, len(references)) for referenceSet in referenceSets: # fetch the reference set path = utils.applyVersion('/referencesets/{}'.format( referenceSet.id)) response = self.app.get(path) self.assertEqual(response.status_code, 200) fetchedReferenceSet = protocol.ReferenceSet.fromJsonString( response.data) self.assertEqual(fetchedReferenceSet, referenceSet) self.assertEqual(len(fetchedReferenceSet.referenceIds), self.numReferencesPerReferenceSet) for referenceId in referenceSet.referenceIds: # fetch the reference path = utils.applyVersion('/references/{}'.format(referenceId)) response = self.app.get(path) self.assertEqual(response.status_code, 200) fetchedReference = protocol.Reference.fromJsonString( response.data) self.assertEqual(fetchedReference.id, referenceId) # fetch the bases path = utils.applyVersion( '/references/{}/bases'.format(referenceId)) args = protocol.ListReferenceBasesRequest().toJsonDict() response = self.app.get(path, data=args) self.assertEqual(response.status_code, 200) bases = protocol.ListReferenceBasesResponse.fromJsonString( response.data) self.assertEqual(len(bases.sequence), 200) self.assertEqual(set(bases.sequence), set(['A', 'C', 'T', 'G'])) calculatedDigest = hashlib.md5(bases.sequence).hexdigest() self.assertEqual(calculatedDigest, fetchedReference.md5checksum)
def testListReferenceBases(self): for referenceSet in self.backend.getReferenceSets(): for reference in referenceSet.getReferences(): id_ = reference.getId() length = reference.getLength() sequence = reference.getBases(0, length) # fetch the bases args = protocol.ListReferenceBasesRequest() response = self.sendListReferenceBasesRequest(id_, args) self.assertEqual(response.sequence, sequence) # Try some simple slices. ranges = [(0, length), (0, 1), (length - 1, length), (0, 0)] for start, end in ranges: args = protocol.ListReferenceBasesRequest() args.start, args.end = start, end response = self.sendListReferenceBasesRequest(id_, args) self.assertEqual(response.sequence, sequence[start:end]) self.assertIsNone(response.nextPageToken) self.assertEqual(response.offset, start)
def testRunListRequest(self): # setup mockGet = mock.Mock() with mock.patch('requests.request', mockGet): text = { "offset": 123, "sequence": "sequence", "nextPageToken": "pageTok", } mockGet.side_effect = [ DummyResponse(json.dumps(text)), DummyResponse('{}')] protocolRequest = protocol.ListReferenceBasesRequest() protocolRequest.start = 1 protocolRequest.end = 5 url = "references/{id}/bases" protocolResponseClass = protocol.ListReferenceBasesResponse id_ = 'myId' # invoke SUT result = [base for base in self.httpClient.runListRequest( protocolRequest, url, protocolResponseClass, id_)] # verify results of invocation self.assertEqual(len(result), 2) self.assertEqual(result[0].offset, 123) self.assertEqual(result[0].sequence, "sequence") # verify requests.get called correctly httpMethod = 'GET' url = "http://example.com/references/myId/bases" params = { 'start': 1, 'end': 5, 'key': 'KEY', 'pageToken': None} headers = {} data = None self.assertEqual(len(mockGet.call_args_list), 2) # assert first call correct firstCall = mockGet.call_args_list[0] self.assertRequestsCall( firstCall, httpMethod, url, headers, data, params, False) # assert second call correct params['pageToken'] = 'pageTok' secondCall = mockGet.call_args_list[1] self.assertRequestsCall( secondCall, httpMethod, url, headers, data, params, False)
def testListReferenceBasesErrors(self): referenceSet = self.backend.getReferenceSets()[0] for badId in self.getBadIds(): path = '/references/{}/bases'.format(badId) response = self.app.get(path) self.assertEqual(response.status_code, 404) reference = references.AbstractReference(referenceSet, badId) path = '/references/{}/bases'.format(reference.getId()) response = self.app.get(path) self.assertEqual(response.status_code, 404) reference = referenceSet.getReferences()[0] path = '/references/{}/bases'.format(reference.getId()) length = reference.getLength() badRanges = [(-1, 0), (-1, -1), (length, 0), (0, length + 1)] for start, end in badRanges: args = protocol.ListReferenceBasesRequest() args.start, args.end = start, end response = self.app.get(path, query_string=args.toJsonDict()) self.assertEqual(response.status_code, 416)
def listReferenceBases(self, id_, start=0, end=None): """ Returns an iterator over the bases from the server in the form of consecutive strings. This command does not conform to the patterns of the other search and get requests, and is implemented differently. """ request = protocol.ListReferenceBasesRequest() request.start = start request.end = end notDone = True # TODO We should probably use a StringIO here to make string buffering # a bit more efficient. basesList = [] while notDone: response = self._runListReferenceBasesPageRequest(id_, request) basesList.append(response.sequence) notDone = response.nextPageToken is not None request.pageToken = response.nextPageToken return "".join(basesList)
def runListReferenceBases(self, requestJson): """ Runs a listReferenceBases request for the specified ID and request arguments. """ # In the case when an empty post request is made to the endpoint # we instantiate an empty ListReferenceBasesRequest. if not requestJson: request = protocol.ListReferenceBasesRequest() else: try: request = protocol.fromJson(requestJson, protocol.ListReferenceBasesRequest) except protocol.json_format.ParseError: raise exceptions.InvalidJsonException(requestJson) compoundId = datamodel.ReferenceCompoundId.parse(request.reference_id) referenceSet = self.getDataRepository().getReferenceSet( compoundId.reference_set_id) reference = referenceSet.getReference(request.reference_id) start = request.start end = request.end if end == 0: # assume meant "get all" end = reference.getLength() if request.page_token: pageTokenStr = request.page_token start = paging._parsePageToken(pageTokenStr, 1)[0] chunkSize = self._maxResponseLength nextPageToken = None if start + chunkSize < end: end = start + chunkSize nextPageToken = str(start + chunkSize) sequence = reference.getBases(start, end) # build response response = protocol.ListReferenceBasesResponse() response.offset = start response.sequence = sequence if nextPageToken: response.next_page_token = nextPageToken return protocol.toJson(response)
def post(self, url, params=None, data=None): self.checkSessionParameters() assert url.startswith(self._urlPrefix) suffix = url[len(self._urlPrefix):] searchSuffix = "/search" if suffix.endswith(searchSuffix): datatype = suffix[1:-len(searchSuffix)] assert datatype in self._searchMethodMap method = self._searchMethodMap[datatype] result = method(data) else: # ListReferenceBases is an oddball and needs to be treated # separately. data = json.loads(data) args = protocol.ListReferenceBasesRequest() args.reference_id = data.get('referenceId', "") args.start = int(data.get('start', 0)) args.end = int(data.get('end', 0)) args.page_token = data.get('pageToken', "") result = self._backend.runListReferenceBases(protocol.toJson(args)) return DummyResponse(result)
def list_reference_bases(self, id_, start=0, end=None): """ Returns an iterator over the bases from the server in the form of consecutive strings. This command does not conform to the patterns of the other search and get requests, and is implemented differently. """ request = protocol.ListReferenceBasesRequest() request.start = pb.int(start) request.end = pb.int(end) request.reference_id = id_ not_done = True # TODO We should probably use a StringIO here to make string buffering # a bit more efficient. bases_list = [] while not_done: response = self._run_list_reference_bases_page_request(request) bases_list.append(response.sequence) not_done = bool(response.next_page_token) request.page_token = response.next_page_token return "".join(bases_list)
def createListReferenceBasesRequest(self): request = protocol.ListReferenceBasesRequest() request.start = self.args.start request.end = self.args.end return request