Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Vision Image and Feature gRPC conversion helper functions. #2914

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions vision/google/cloud/vision/_gax.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,55 @@

"""GAX Client for interacting with the Google Cloud Vision API."""

from google.cloud.gapic.vision.v1 import image_annotator_client
from google.cloud.grpc.vision.v1 import image_annotator_pb2

from google.cloud._helpers import _to_bytes


class _GAPICVisionAPI(object):
"""Vision API for interacting with the gRPC version of Vision.

:type client: :class:`~google.cloud.core.client.Client`
:type client: :class:`~google.cloud.vision.client.Client`
:param client: Instance of ``Client`` object.
"""
def __init__(self, client=None):
raise NotImplementedError
self._client = client
self._api = image_annotator_client.ImageAnnotatorClient()


def _to_gapic_feature(feature):
"""Helper function to convert a ``Feature`` to a gRPC ``Feature``.

:type feature: :class:`~google.cloud.vision.feature.Feature`
:param feature: Local ``Feature`` class to be converted to gRPC ``Feature``
instance.

:rtype: :class:`~google.cloud.grpc.vision.v1.image_annotator_pb2.Feature`
:returns: gRPC ``Feature`` converted from
:class:`~google.cloud.vision.feature.Feature`.
"""
return image_annotator_pb2.Feature(
type=getattr(image_annotator_pb2.Feature, feature.feature_type),

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

max_results=feature.max_results)


def _to_gapic_image(image):
"""Helper function to convert an ``Image`` to a gRPC ``Image``.

:type image: :class:`~google.cloud.vision.image.Image`
:param image: Local ``Image`` class to be converted to gRPC ``Image``.

:rtype: :class:`~google.cloud.grpc.vision.v1.image_annotator_pb2.Image`
:returns: gRPC ``Image`` converted from
:class:`~google.cloud.vision.image.Image`.
"""
if image.content is not None:
return image_annotator_pb2.Image(content=_to_bytes(image.content))
if image.source is not None:
return image_annotator_pb2.Image(
source=image_annotator_pb2.ImageSource(
gcs_image_uri=image.source
),
)
raise ValueError('No image content or source found.')

This comment was marked as spam.

1 change: 1 addition & 0 deletions vision/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
REQUIREMENTS = [
'enum34',
'google-cloud-core >= 0.22.1, < 0.23dev',
'gapic-google-cloud-vision-v1 >= 0.14.0, < 0.15dev',
]

setup(
Expand Down
63 changes: 60 additions & 3 deletions vision/unit_tests/test__gax.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import unittest

import mock


class TestGAXClient(unittest.TestCase):
def _get_target_class(self):
Expand All @@ -23,7 +25,62 @@ def _get_target_class(self):
def _make_one(self, *args, **kwargs):
return self._get_target_class()(*args, **kwargs)

def test_gax_not_implemented(self):
def test_ctor(self):
client = mock.Mock()
with mock.patch('google.cloud.vision._gax.image_annotator_client.'
'ImageAnnotatorClient'):

This comment was marked as spam.

api = self._make_one(client)
self.assertIs(api._client, client)


class TestToGAPICFeature(unittest.TestCase):

This comment was marked as spam.

def _call_fut(self, feature):
from google.cloud.vision._gax import _to_gapic_feature

This comment was marked as spam.

return _to_gapic_feature(feature)

def test__to_gapic_feature(self):
from google.cloud.vision.feature import Feature
from google.cloud.vision.feature import FeatureTypes
from google.cloud.grpc.vision.v1 import image_annotator_pb2

feature = Feature(FeatureTypes.LABEL_DETECTION, 5)
feature_pb = self._call_fut(feature)
self.assertIsInstance(feature_pb, image_annotator_pb2.Feature)
self.assertEqual(feature_pb.type, 4)
self.assertEqual(feature_pb.max_results, 5)


class TestToGAPICImage(unittest.TestCase):

This comment was marked as spam.

def _call_fut(self, image):
from google.cloud.vision._gax import _to_gapic_image
return _to_gapic_image(image)

def test__to_gapic_image_content(self):
import base64
from google.cloud.vision.image import Image
from google.cloud.grpc.vision.v1 import image_annotator_pb2

image_content = b'abc 1 2 3'
b64_content = base64.b64encode(image_content)
client = object()
image = Image(client, content=image_content)
image_pb = self._call_fut(image)
self.assertIsInstance(image_pb, image_annotator_pb2.Image)
self.assertEqual(image_pb.content, b64_content)

def test__to_gapic_image_uri(self):
from google.cloud.vision.image import Image
from google.cloud.grpc.vision.v1 import image_annotator_pb2

image_uri = 'gs://1234/34.jpg'
client = object()
with self.assertRaises(NotImplementedError):
self._make_one(client=client)
image = Image(client, source_uri=image_uri)
image_pb = self._call_fut(image)
self.assertIsInstance(image_pb, image_annotator_pb2.Image)
self.assertEqual(image_pb.source.gcs_image_uri, image_uri)

def test__to_gapic_with_empty_image(self):
image = mock.Mock(
content=None, source=None, spec=['content', 'source'])
with self.assertRaises(ValueError):
self._call_fut(image)
17 changes: 14 additions & 3 deletions vision/unit_tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,25 @@ def test_annotate_with_preset_api(self):
client._vision_api.annotate()
api.annotate.assert_called_once_with()

def test_gax_not_implemented_from_client(self):
def test_make_gax_client(self):
from google.cloud.vision._gax import _GAPICVisionAPI

credentials = _make_credentials()
client = self._make_one(project=PROJECT, credentials=credentials,
use_gax=None)
client._connection = _Connection()
with mock.patch('google.cloud.vision.client._GAPICVisionAPI',
spec=True):
self.assertIsInstance(client._vision_api, _GAPICVisionAPI)

def test_make_http_client(self):
from google.cloud.vision._http import _HTTPVisionAPI

with self.assertRaises(NotImplementedError):
client._vision_api()
credentials = _make_credentials()
client = self._make_one(project=PROJECT, credentials=credentials,
use_gax=False)
client._connection = _Connection()
self.assertIsInstance(client._vision_api, _HTTPVisionAPI)

def test_face_annotation(self):
from google.cloud.vision.feature import Feature, FeatureTypes
Expand Down