Skip to content

Commit

Permalink
Refactor tests, fix naming.
Browse files Browse the repository at this point in the history
  • Loading branch information
daspecster committed Jan 11, 2017
1 parent 33f3dd5 commit 631ece9
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 81 deletions.
9 changes: 5 additions & 4 deletions vision/google/cloud/vision/_gax.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class _GAPICVisionAPI(object):
"""
def __init__(self, client=None):
self._client = client
self._api = image_annotator_client.ImageAnnotatorClient()
self._annotator_client = image_annotator_client.ImageAnnotatorClient()

def annotate(self, image, features):
"""Annotate images through GAX.
Expand All @@ -49,9 +49,10 @@ def annotate(self, image, features):
request = image_annotator_pb2.AnnotateImageRequest(
image=gapic_image, features=gapic_features)
requests = [request]
api = self._api
responses = api.batch_annotate_images(requests)
return Annotations.from_pb(responses.responses[0])
annotator_client = self._annotator_client
images = annotator_client.batch_annotate_images(requests)
if len(images.responses) == 1:
return Annotations.from_pb(images.responses[0])


def _to_gapic_feature(feature):
Expand Down
5 changes: 3 additions & 2 deletions vision/google/cloud/vision/_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ def annotate(self, image, features):
data = {'requests': [request]}
api_response = self._connection.api_request(
method='POST', path='/images:annotate', data=data)
responses = api_response.get('responses')
return Annotations.from_api_repr(responses[0])
images = api_response.get('responses')
if len(images) == 1:
return Annotations.from_api_repr(images[0])


def _make_request(image, features):
Expand Down
26 changes: 11 additions & 15 deletions vision/google/cloud/vision/annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ def from_api_repr(cls, response):

@classmethod
def from_pb(cls, response):
"""Factory: construct an instance of ``Annotations`` from gRPC response.
"""Factory: construct an instance of ``Annotations`` from protobuf.
:type response: :class:`~google.cloud.grpc.vision.v1.\
image_annotator_pb2.AnnotateImageResponse`
:param response: ``AnnotateImageResponse`` from gRPC call.
:param response: ``AnnotateImageResponse`` from protobuf call.
:rtype: :class:`~google.cloud.vision.annotations.Annotations`
:returns: ``Annotations`` instance populated from gRPC response.
Expand All @@ -109,21 +109,21 @@ def from_pb(cls, response):


def _process_image_annotations(image):
"""Helper for processing annotation types from gRPC responses.
"""Helper for processing annotation types from protobuf.
:type image: :class:`~google.cloud.grpc.vision.v1.image_annotator_pb2.\
AnnotateImageResponse`
:param image: ``AnnotateImageResponse`` from gRPC response.
:param image: ``AnnotateImageResponse`` from protobuf.
:rtype: dict
:returns: Dictionary populated with entities from response.
"""
annotations = {}
annotations['labels'] = _make_entity_from_pb(image.label_annotations)
annotations['landmarks'] = _make_entity_from_pb(image.landmark_annotations)
annotations['logos'] = _make_entity_from_pb(image.logo_annotations)
annotations['texts'] = _make_entity_from_pb(image.text_annotations)
return annotations
return {
'labels': _make_entity_from_pb(image.label_annotations),
'landmarks': _make_entity_from_pb(image.landmark_annotations),
'logos': _make_entity_from_pb(image.logo_annotations),
'texts': _make_entity_from_pb(image.text_annotations),
}


def _make_entity_from_pb(annotations):
Expand All @@ -136,11 +136,7 @@ def _make_entity_from_pb(annotations):
:rtype: list
:returns: List of ``EntityAnnotation``.
"""

entities = []
for annotation in annotations:
entities.append(EntityAnnotation.from_pb(annotation))
return entities
return [EntityAnnotation.from_pb(annotation) for annotation in annotations]


def _entity_from_response_type(feature_type, results):
Expand Down
2 changes: 1 addition & 1 deletion vision/google/cloud/vision/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def from_api_repr(cls, response):
bounds = Bounds.from_api_repr(response.get('boundingPoly'))
description = response['description']
locale = response.get('locale', None)
locations = [LocationInformation.from_api_repr(location)
locations = [LocationInformation.from_api_repr(location['latLng'])
for location in response.get('locations', [])]
mid = response.get('mid', None)
score = response.get('score', None)
Expand Down
10 changes: 5 additions & 5 deletions vision/google/cloud/vision/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,18 @@ def __init__(self, latitude, longitude):
self._longitude = longitude

@classmethod
def from_api_repr(cls, response):
def from_api_repr(cls, location_info):
"""Factory: construct location information from Vision API response.
:type response: dict
:param response: Dictionary response of locations.
:type location_info: dict
:param location_info: Dictionary response of locations.
:rtype: :class:`~google.cloud.vision.geometry.LocationInformation`
:returns: ``LocationInformation`` with populated latitude and
longitude.
"""
latitude = response['latLng']['latitude']
longitude = response['latLng']['longitude']
latitude = location_info['latitude']
longitude = location_info['longitude']
return cls(latitude, longitude)

@classmethod
Expand Down
46 changes: 37 additions & 9 deletions vision/unit_tests/test__gax.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,53 @@ def test_annotation(self):
from google.cloud.vision.feature import FeatureTypes
from google.cloud.vision.image import Image

client = mock.Mock()
client = mock.Mock(spec_set=[])
feature = Feature(FeatureTypes.LABEL_DETECTION, 5)
image_content = b'abc 1 2 3'
image = Image(client, content=image_content)
with mock.patch('google.cloud.vision._gax.image_annotator_client.'
'ImageAnnotatorClient'):
api = self._make_one(client)
gax_api = self._make_one(client)

api._api = mock.Mock()
mock_response = mock.Mock(responses=['mock response data'])
api._api.batch_annotate_images.return_value = mock_response
mock_response = {
'batch_annotate_images.return_value':
mock.Mock(responses=['mock response data']),
}

gax_api._annotator_client = mock.Mock(
spec_set=['batch_annotate_images'], **mock_response)

with mock.patch('google.cloud.vision._gax.Annotations') as mock_anno:
api.annotate(image, [feature])
gax_api.annotate(image, [feature])
mock_anno.from_pb.assert_called_with('mock response data')
api._api.batch_annotate_images.assert_called()
gax_api._annotator_client.batch_annotate_images.assert_called()

def test_annotate_no_results(self):
from google.cloud.vision.feature import Feature
from google.cloud.vision.feature import FeatureTypes
from google.cloud.vision.image import Image

client = mock.Mock(spec_set=[])
feature = Feature(FeatureTypes.LABEL_DETECTION, 5)
image_content = b'abc 1 2 3'
image = Image(client, content=image_content)
with mock.patch('google.cloud.vision._gax.image_annotator_client.'
'ImageAnnotatorClient'):
gax_api = self._make_one(client)

mock_response = {
'batch_annotate_images.return_value': mock.Mock(responses=[]),
}

gax_api._annotator_client = mock.Mock(
spec_set=['batch_annotate_images'], **mock_response)
with mock.patch('google.cloud.vision._gax.Annotations'):
self.assertIsNone(gax_api.annotate(image, [feature]))

gax_api._annotator_client.batch_annotate_images.assert_called()


class TestToGAPICFeature(unittest.TestCase):
class Test__to_gapic_feature(unittest.TestCase):
def _call_fut(self, feature):
from google.cloud.vision._gax import _to_gapic_feature
return _to_gapic_feature(feature)
Expand All @@ -72,7 +100,7 @@ def test__to_gapic_feature(self):
self.assertEqual(feature_pb.max_results, 5)


class TestToGAPICImage(unittest.TestCase):
class Test__to_gapic_image(unittest.TestCase):
def _call_fut(self, image):
from google.cloud.vision._gax import _to_gapic_image
return _to_gapic_image(image)
Expand Down
27 changes: 26 additions & 1 deletion vision/unit_tests/test__http.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,38 @@
import base64
import unittest

import mock


IMAGE_CONTENT = b'/9j/4QNURXhpZgAASUkq'
PROJECT = 'PROJECT'
B64_IMAGE_CONTENT = base64.b64encode(IMAGE_CONTENT).decode('ascii')


class Test_HTTPVisionAPI(unittest.TestCase):
def _get_target_class(self):
from google.cloud.vision._http import _HTTPVisionAPI
return _HTTPVisionAPI

def _make_one(self, *args, **kwargs):
return self._get_target_class()(*args, **kwargs)

def test_call_annotate_with_no_results(self):
from google.cloud.vision.feature import Feature
from google.cloud.vision.feature import FeatureTypes
from google.cloud.vision.image import Image

client = mock.Mock(spec_set=['_connection'])
feature = Feature(FeatureTypes.LABEL_DETECTION, 5)
image_content = b'abc 1 2 3'
image = Image(client, content=image_content)

http_api = self._make_one(client)
http_api._connection = mock.Mock(spec_set=['api_request'])
http_api._connection.api_request.return_value = {'responses': []}
self.assertIsNone(http_api.annotate(image, [feature]))


class TestVisionRequest(unittest.TestCase):
@staticmethod
def _get_target_function():
Expand All @@ -44,7 +70,6 @@ def test_call_vision_request(self):
features = request['features']
self.assertEqual(len(features), 1)
feature = features[0]
print(feature)
self.assertEqual(feature['type'], FeatureTypes.FACE_DETECTION)
self.assertEqual(feature['maxResults'], 3)

Expand Down
Loading

0 comments on commit 631ece9

Please sign in to comment.