Skip to content

Commit

Permalink
Merge pull request #1177 from tseaver/search-list_documents
Browse files Browse the repository at this point in the history
Add 'Index.list_documents' API wrapper.
  • Loading branch information
tseaver committed Oct 14, 2015
2 parents 7e999cf + a9728ba commit 7196d60
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 6 deletions.
49 changes: 49 additions & 0 deletions gcloud/search/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

"""Define API Indexes."""

from gcloud.search.document import Document


class Index(object):
"""Indexes are containers for documents.
Expand Down Expand Up @@ -148,3 +150,50 @@ def _set_properties(self, api_response):
"""
self._properties.clear()
self._properties.update(api_response)

def list_documents(self, max_results=None, page_token=None,
view=None):
"""List documents created within this index.
See:
https://cloud.google.com/search/reference/rest/v1/projects/indexes/documents/list
:type max_results: int
:param max_results: maximum number of zones to return, If not
passed, defaults to a value set by the API.
:type page_token: string
:param page_token: opaque marker for the next "page" of zones. If
not passed, the API will return the first page of
zones.
:type view: string
:param view: One of 'ID_ONLY' (return only the document ID; the
default) or 'FULL' (return the full resource
representation for the document, including field
values)
:rtype: tuple, (list, str)
:returns: list of :class:`gcloud.dns.document.Document`, plus a
"next page token" string: if the token is not None,
indicates that more zones can be retrieved with another
call (pass that value as ``page_token``).
"""
params = {}

if max_results is not None:
params['pageSize'] = max_results

if page_token is not None:
params['pageToken'] = page_token

if view is not None:
params['view'] = view

path = '%s/documents' % (self.path,)
connection = self._client.connection
resp = connection.api_request(method='GET', path=path,
query_params=params)
zones = [Document.from_api_repr(resource, self)
for resource in resp['documents']]
return zones, resp.get('nextPageToken')
13 changes: 7 additions & 6 deletions gcloud/search/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ def test_list_indexes_defaults(self):
client = self._makeOne(self.PROJECT, creds)
conn = client.connection = _Connection(DATA)

zones, token = client.list_indexes()
indexes, token = client.list_indexes()

self.assertEqual(len(zones), len(DATA['indexes']))
for found, expected in zip(zones, DATA['indexes']):
self.assertEqual(len(indexes), len(DATA['indexes']))
for found, expected in zip(indexes, DATA['indexes']):
self.assertTrue(isinstance(found, Index))
self.assertEqual(found.name, expected['indexId'])
self.assertEqual(found.text_fields, None)
Expand All @@ -72,6 +72,7 @@ def test_list_indexes_defaults(self):
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'], {})

def test_list_indexes_explicit(self):
from gcloud.search.index import Index
Expand All @@ -93,11 +94,11 @@ def test_list_indexes_explicit(self):
client = self._makeOne(self.PROJECT, creds)
conn = client.connection = _Connection(DATA)

zones, token = client.list_indexes(
indexes, token = client.list_indexes(
max_results=3, page_token=TOKEN, prefix='index', view='FULL')

self.assertEqual(len(zones), len(DATA['indexes']))
for found, expected in zip(zones, DATA['indexes']):
self.assertEqual(len(indexes), len(DATA['indexes']))
for found, expected in zip(indexes, DATA['indexes']):
self.assertTrue(isinstance(found, Index))
self.assertEqual(found.name, expected['indexId'])
field_info = expected['indexedField']
Expand Down
113 changes: 113 additions & 0 deletions gcloud/search/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ def _makeResource(self):
}
}

def _makeDocumentResource(self, doc_id, rank=None, title=None):
resource = {'docId': doc_id}
if rank is not None:
resource['rank'] = rank
if title is not None:
resource['fields'] = {
'title': {
'values': [{
'stringValue': title,
'stringFormat': 'text',
'lang': 'en'}]
}
}
return resource

def _verifyResourceProperties(self, index, resource):

self.assertEqual(index.name, resource.get('indexId'))
Expand All @@ -61,6 +76,27 @@ def _verifyResourceProperties(self, index, resource):
self.assertEqual(index.number_fields, field_info.get('numberFields'))
self.assertEqual(index.geo_fields, field_info.get('geoFields'))

def _verifyDocumentResource(self, documents, resource):
from gcloud.search.document import Document
from gcloud.search.document import StringValue
self.assertEqual(len(documents), len(resource['documents']))
for found, expected in zip(documents, resource['documents']):
self.assertTrue(isinstance(found, Document))
self.assertEqual(found.name, expected['docId'])
self.assertEqual(found.rank, expected.get('rank'))
e_fields = expected.get('fields', ())
self.assertEqual(sorted(found.fields), sorted(e_fields))
for field, f_field in found.fields.items():
e_field = e_fields[field]
for f_value, e_value in zip(f_field.values, e_field['values']):
self.assertTrue(isinstance(f_value, StringValue))
self.assertEqual(f_value.string_value,
e_value['stringValue'])
self.assertEqual(f_value.string_format,
e_value['stringFormat'])
self.assertEqual(f_value.language,
e_value['lang'])

def test_ctor(self):
client = _Client(self.PROJECT)
index = self._makeOne(self.INDEX_ID, client)
Expand Down Expand Up @@ -105,9 +141,86 @@ def test_from_api_repr_w_properties(self):
self.assertTrue(index._client is client)
self._verifyResourceProperties(index, RESOURCE)

def test_list_documents_defaults(self):
DOCID_1 = 'docid-one'
DOCID_2 = 'docid-two'
PATH = 'projects/%s/indexes/%s/documents' % (
self.PROJECT, self.INDEX_ID)
TOKEN = 'TOKEN'
DOC_1 = self._makeDocumentResource(DOCID_1)
DOC_2 = self._makeDocumentResource(DOCID_2)
DATA = {
'nextPageToken': TOKEN,
'documents': [DOC_1, DOC_2],
}
client = _Client(self.PROJECT)
conn = client.connection = _Connection(DATA)
index = self._makeOne(self.INDEX_ID, client)

documents, token = index.list_documents()

self._verifyDocumentResource(documents, DATA)
self.assertEqual(token, TOKEN)

self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'], {})

def test_list_documents_explicit(self):
DOCID_1 = 'docid-one'
RANK_1 = 2345
TITLE_1 = 'Title One'
DOCID_2 = 'docid-two'
RANK_2 = 1234
TITLE_2 = 'Title Two'
PATH = 'projects/%s/indexes/%s/documents' % (
self.PROJECT, self.INDEX_ID)
TOKEN = 'TOKEN'
DOC_1 = self._makeDocumentResource(DOCID_1, RANK_1, TITLE_1)
DOC_2 = self._makeDocumentResource(DOCID_2, RANK_2, TITLE_2)
DATA = {'documents': [DOC_1, DOC_2]}
client = _Client(self.PROJECT)
conn = client.connection = _Connection(DATA)
index = self._makeOne(self.INDEX_ID, client)

documents, token = index.list_documents(
max_results=3, page_token=TOKEN, view='FULL')

self._verifyDocumentResource(documents, DATA)
self.assertEqual(token, None)

self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'],
{'pageSize': 3,
'pageToken': TOKEN,
'view': 'FULL'})


class _Client(object):

def __init__(self, project='project', connection=None):
self.project = project
self.connection = connection


class _Connection(object):

def __init__(self, *responses):
self._responses = responses
self._requested = []

def api_request(self, **kw):
from gcloud.exceptions import NotFound
self._requested.append(kw)

try:
response, self._responses = self._responses[0], self._responses[1:]
except: # pragma: NO COVER
raise NotFound('miss')
else:
return response

0 comments on commit 7196d60

Please sign in to comment.