Skip to content

Commit 631ece9

Browse files
committed
Refactor tests, fix naming.
1 parent 33f3dd5 commit 631ece9

8 files changed

Lines changed: 142 additions & 81 deletions

File tree

vision/google/cloud/vision/_gax.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class _GAPICVisionAPI(object):
3030
"""
3131
def __init__(self, client=None):
3232
self._client = client
33-
self._api = image_annotator_client.ImageAnnotatorClient()
33+
self._annotator_client = image_annotator_client.ImageAnnotatorClient()
3434

3535
def annotate(self, image, features):
3636
"""Annotate images through GAX.
@@ -49,9 +49,10 @@ def annotate(self, image, features):
4949
request = image_annotator_pb2.AnnotateImageRequest(
5050
image=gapic_image, features=gapic_features)
5151
requests = [request]
52-
api = self._api
53-
responses = api.batch_annotate_images(requests)
54-
return Annotations.from_pb(responses.responses[0])
52+
annotator_client = self._annotator_client
53+
images = annotator_client.batch_annotate_images(requests)
54+
if len(images.responses) == 1:
55+
return Annotations.from_pb(images.responses[0])
5556

5657

5758
def _to_gapic_feature(feature):

vision/google/cloud/vision/_http.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ def annotate(self, image, features):
4949
data = {'requests': [request]}
5050
api_response = self._connection.api_request(
5151
method='POST', path='/images:annotate', data=data)
52-
responses = api_response.get('responses')
53-
return Annotations.from_api_repr(responses[0])
52+
images = api_response.get('responses')
53+
if len(images) == 1:
54+
return Annotations.from_api_repr(images[0])
5455

5556

5657
def _make_request(image, features):

vision/google/cloud/vision/annotations.py

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@ def from_api_repr(cls, response):
9595

9696
@classmethod
9797
def from_pb(cls, response):
98-
"""Factory: construct an instance of ``Annotations`` from gRPC response.
98+
"""Factory: construct an instance of ``Annotations`` from protobuf.
9999
100100
:type response: :class:`~google.cloud.grpc.vision.v1.\
101101
image_annotator_pb2.AnnotateImageResponse`
102-
:param response: ``AnnotateImageResponse`` from gRPC call.
102+
:param response: ``AnnotateImageResponse`` from protobuf call.
103103
104104
:rtype: :class:`~google.cloud.vision.annotations.Annotations`
105105
:returns: ``Annotations`` instance populated from gRPC response.
@@ -109,21 +109,21 @@ def from_pb(cls, response):
109109

110110

111111
def _process_image_annotations(image):
112-
"""Helper for processing annotation types from gRPC responses.
112+
"""Helper for processing annotation types from protobuf.
113113
114114
:type image: :class:`~google.cloud.grpc.vision.v1.image_annotator_pb2.\
115115
AnnotateImageResponse`
116-
:param image: ``AnnotateImageResponse`` from gRPC response.
116+
:param image: ``AnnotateImageResponse`` from protobuf.
117117
118118
:rtype: dict
119119
:returns: Dictionary populated with entities from response.
120120
"""
121-
annotations = {}
122-
annotations['labels'] = _make_entity_from_pb(image.label_annotations)
123-
annotations['landmarks'] = _make_entity_from_pb(image.landmark_annotations)
124-
annotations['logos'] = _make_entity_from_pb(image.logo_annotations)
125-
annotations['texts'] = _make_entity_from_pb(image.text_annotations)
126-
return annotations
121+
return {
122+
'labels': _make_entity_from_pb(image.label_annotations),
123+
'landmarks': _make_entity_from_pb(image.landmark_annotations),
124+
'logos': _make_entity_from_pb(image.logo_annotations),
125+
'texts': _make_entity_from_pb(image.text_annotations),
126+
}
127127

128128

129129
def _make_entity_from_pb(annotations):
@@ -136,11 +136,7 @@ def _make_entity_from_pb(annotations):
136136
:rtype: list
137137
:returns: List of ``EntityAnnotation``.
138138
"""
139-
140-
entities = []
141-
for annotation in annotations:
142-
entities.append(EntityAnnotation.from_pb(annotation))
143-
return entities
139+
return [EntityAnnotation.from_pb(annotation) for annotation in annotations]
144140

145141

146142
def _entity_from_response_type(feature_type, results):

vision/google/cloud/vision/entity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def from_api_repr(cls, response):
6363
bounds = Bounds.from_api_repr(response.get('boundingPoly'))
6464
description = response['description']
6565
locale = response.get('locale', None)
66-
locations = [LocationInformation.from_api_repr(location)
66+
locations = [LocationInformation.from_api_repr(location['latLng'])
6767
for location in response.get('locations', [])]
6868
mid = response.get('mid', None)
6969
score = response.get('score', None)

vision/google/cloud/vision/geometry.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,18 +87,18 @@ def __init__(self, latitude, longitude):
8787
self._longitude = longitude
8888

8989
@classmethod
90-
def from_api_repr(cls, response):
90+
def from_api_repr(cls, location_info):
9191
"""Factory: construct location information from Vision API response.
9292
93-
:type response: dict
94-
:param response: Dictionary response of locations.
93+
:type location_info: dict
94+
:param location_info: Dictionary response of locations.
9595
9696
:rtype: :class:`~google.cloud.vision.geometry.LocationInformation`
9797
:returns: ``LocationInformation`` with populated latitude and
9898
longitude.
9999
"""
100-
latitude = response['latLng']['latitude']
101-
longitude = response['latLng']['longitude']
100+
latitude = location_info['latitude']
101+
longitude = location_info['longitude']
102102
return cls(latitude, longitude)
103103

104104
@classmethod

vision/unit_tests/test__gax.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,53 @@ def test_annotation(self):
3737
from google.cloud.vision.feature import FeatureTypes
3838
from google.cloud.vision.image import Image
3939

40-
client = mock.Mock()
40+
client = mock.Mock(spec_set=[])
4141
feature = Feature(FeatureTypes.LABEL_DETECTION, 5)
4242
image_content = b'abc 1 2 3'
4343
image = Image(client, content=image_content)
4444
with mock.patch('google.cloud.vision._gax.image_annotator_client.'
4545
'ImageAnnotatorClient'):
46-
api = self._make_one(client)
46+
gax_api = self._make_one(client)
4747

48-
api._api = mock.Mock()
49-
mock_response = mock.Mock(responses=['mock response data'])
50-
api._api.batch_annotate_images.return_value = mock_response
48+
mock_response = {
49+
'batch_annotate_images.return_value':
50+
mock.Mock(responses=['mock response data']),
51+
}
52+
53+
gax_api._annotator_client = mock.Mock(
54+
spec_set=['batch_annotate_images'], **mock_response)
5155

5256
with mock.patch('google.cloud.vision._gax.Annotations') as mock_anno:
53-
api.annotate(image, [feature])
57+
gax_api.annotate(image, [feature])
5458
mock_anno.from_pb.assert_called_with('mock response data')
55-
api._api.batch_annotate_images.assert_called()
59+
gax_api._annotator_client.batch_annotate_images.assert_called()
60+
61+
def test_annotate_no_results(self):
62+
from google.cloud.vision.feature import Feature
63+
from google.cloud.vision.feature import FeatureTypes
64+
from google.cloud.vision.image import Image
65+
66+
client = mock.Mock(spec_set=[])
67+
feature = Feature(FeatureTypes.LABEL_DETECTION, 5)
68+
image_content = b'abc 1 2 3'
69+
image = Image(client, content=image_content)
70+
with mock.patch('google.cloud.vision._gax.image_annotator_client.'
71+
'ImageAnnotatorClient'):
72+
gax_api = self._make_one(client)
73+
74+
mock_response = {
75+
'batch_annotate_images.return_value': mock.Mock(responses=[]),
76+
}
77+
78+
gax_api._annotator_client = mock.Mock(
79+
spec_set=['batch_annotate_images'], **mock_response)
80+
with mock.patch('google.cloud.vision._gax.Annotations'):
81+
self.assertIsNone(gax_api.annotate(image, [feature]))
82+
83+
gax_api._annotator_client.batch_annotate_images.assert_called()
5684

5785

58-
class TestToGAPICFeature(unittest.TestCase):
86+
class Test__to_gapic_feature(unittest.TestCase):
5987
def _call_fut(self, feature):
6088
from google.cloud.vision._gax import _to_gapic_feature
6189
return _to_gapic_feature(feature)
@@ -72,7 +100,7 @@ def test__to_gapic_feature(self):
72100
self.assertEqual(feature_pb.max_results, 5)
73101

74102

75-
class TestToGAPICImage(unittest.TestCase):
103+
class Test__to_gapic_image(unittest.TestCase):
76104
def _call_fut(self, image):
77105
from google.cloud.vision._gax import _to_gapic_image
78106
return _to_gapic_image(image)

vision/unit_tests/test__http.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,38 @@
1515
import base64
1616
import unittest
1717

18+
import mock
19+
1820

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

2325

26+
class Test_HTTPVisionAPI(unittest.TestCase):
27+
def _get_target_class(self):
28+
from google.cloud.vision._http import _HTTPVisionAPI
29+
return _HTTPVisionAPI
30+
31+
def _make_one(self, *args, **kwargs):
32+
return self._get_target_class()(*args, **kwargs)
33+
34+
def test_call_annotate_with_no_results(self):
35+
from google.cloud.vision.feature import Feature
36+
from google.cloud.vision.feature import FeatureTypes
37+
from google.cloud.vision.image import Image
38+
39+
client = mock.Mock(spec_set=['_connection'])
40+
feature = Feature(FeatureTypes.LABEL_DETECTION, 5)
41+
image_content = b'abc 1 2 3'
42+
image = Image(client, content=image_content)
43+
44+
http_api = self._make_one(client)
45+
http_api._connection = mock.Mock(spec_set=['api_request'])
46+
http_api._connection.api_request.return_value = {'responses': []}
47+
self.assertIsNone(http_api.annotate(image, [feature]))
48+
49+
2450
class TestVisionRequest(unittest.TestCase):
2551
@staticmethod
2652
def _get_target_function():
@@ -44,7 +70,6 @@ def test_call_vision_request(self):
4470
features = request['features']
4571
self.assertEqual(len(features), 1)
4672
feature = features[0]
47-
print(feature)
4873
self.assertEqual(feature['type'], FeatureTypes.FACE_DETECTION)
4974
self.assertEqual(feature['maxResults'], 3)
5075

0 commit comments

Comments
 (0)