Skip to content

Commit fca6333

Browse files
authored
Fix Speech LRO handling and add HTTP side for multiple results. (#2965)
* Update after #2962 to fill out http side and handle new LRO. * Update _OperationsFuture usage. * Mock OperationsClient.
1 parent 3d2fee9 commit fca6333

File tree

4 files changed

+50
-22
lines changed

4 files changed

+50
-22
lines changed

packages/google-cloud-speech/google/cloud/speech/_gax.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ def async_recognize(self, sample, language_code=None,
104104
audio = RecognitionAudio(content=sample.content,
105105
uri=sample.source_uri)
106106
api = self._gapic_api
107-
response = api.async_recognize(config=config, audio=audio)
107+
operation_future = api.async_recognize(config=config, audio=audio)
108108

109-
return Operation.from_pb(response, self)
109+
return Operation.from_pb(operation_future.last_operation_data(), self)
110110

111111
def streaming_recognize(self, sample, language_code=None,
112112
max_alternatives=None, profanity_filter=None,

packages/google-cloud-speech/google/cloud/speech/client.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from google.cloud.environment_vars import DISABLE_GRPC
2424

2525
from google.cloud.speech._gax import GAPICSpeechAPI
26-
from google.cloud.speech.alternative import Alternative
26+
from google.cloud.speech.result import Result
2727
from google.cloud.speech.connection import Connection
2828
from google.cloud.speech.operation import Operation
2929
from google.cloud.speech.sample import Sample
@@ -235,12 +235,11 @@ def sync_recognize(self, sample, language_code=None, max_alternatives=None,
235235
api_response = self._connection.api_request(
236236
method='POST', path='speech:syncrecognize', data=data)
237237

238-
if len(api_response['results']) == 1:
239-
result = api_response['results'][0]
240-
return [Alternative.from_api_repr(alternative)
241-
for alternative in result['alternatives']]
238+
if len(api_response['results']) > 0:
239+
results = api_response['results']
240+
return [Result.from_api_repr(result) for result in results]
242241
else:
243-
raise ValueError('More than one result or none returned from API.')
242+
raise ValueError('No results were returned from the API')
244243

245244

246245
def _build_request_data(sample, language_code=None, max_alternatives=None,

packages/google-cloud-speech/google/cloud/speech/result.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,34 @@ def __init__(self, alternatives):
3232

3333
@classmethod
3434
def from_pb(cls, result):
35-
"""Factory: construct instance of ``SpeechRecognitionResult``.
35+
"""Factory: construct instance of ``Result``.
3636
3737
:type result: :class:`~google.cloud.grpc.speech.v1beta1\
38-
.cloud_speech_pb2.StreamingRecognizeResult`
39-
:param result: Instance of ``StreamingRecognizeResult`` protobuf.
38+
.cloud_speech_pb2.SpeechRecognitionResult`
39+
:param result: Instance of ``SpeechRecognitionResult`` protobuf.
4040
41-
:rtype: :class:`~google.cloud.speech.result.SpeechRecognitionResult`
42-
:returns: Instance of ``SpeechRecognitionResult``.
41+
:rtype: :class:`~google.cloud.speech.result.Result`
42+
:returns: Instance of ``Result``.
4343
"""
44-
alternatives = [Alternative.from_pb(result) for result
44+
alternatives = [Alternative.from_pb(alternative) for alternative
4545
in result.alternatives]
4646
return cls(alternatives=alternatives)
4747

48+
@classmethod
49+
def from_api_repr(cls, result):
50+
"""Factory: construct instance of ``Result``.
51+
52+
:type result: dict
53+
:param result: Dictionary of a :class:`~google.cloud.grpc.speech.\
54+
v1beta1.cloud_speech_pb2.SpeechRecognitionResult`
55+
56+
:rtype: :class:`~google.cloud.speech.result.Result`
57+
:returns: Instance of ``Result``.
58+
"""
59+
alternatives = [Alternative.from_api_repr(alternative) for alternative
60+
in result['alternatives']]
61+
return cls(alternatives=alternatives)
62+
4863
@property
4964
def confidence(self):
5065
"""Return the confidence for the most probable alternative.

packages/google-cloud-speech/unit_tests/test_client.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ def test_sync_recognize_content_with_optional_params_no_gax(self):
129129

130130
from google.cloud import speech
131131
from google.cloud.speech.alternative import Alternative
132+
from google.cloud.speech.result import Result
132133
from unit_tests._fixtures import SYNC_RECOGNIZE_RESPONSE
133134

134135
_B64_AUDIO_CONTENT = _bytes_to_unicode(b64encode(self.AUDIO_CONTENT))
@@ -174,13 +175,16 @@ def test_sync_recognize_content_with_optional_params_no_gax(self):
174175
alternative = SYNC_RECOGNIZE_RESPONSE['results'][0]['alternatives'][0]
175176
expected = Alternative.from_api_repr(alternative)
176177
self.assertEqual(len(response), 1)
177-
self.assertIsInstance(response[0], Alternative)
178-
self.assertEqual(response[0].transcript, expected.transcript)
179-
self.assertEqual(response[0].confidence, expected.confidence)
178+
self.assertIsInstance(response[0], Result)
179+
self.assertEqual(len(response[0].alternatives), 1)
180+
alternative = response[0].alternatives[0]
181+
self.assertEqual(alternative.transcript, expected.transcript)
182+
self.assertEqual(alternative.confidence, expected.confidence)
180183

181184
def test_sync_recognize_source_uri_without_optional_params_no_gax(self):
182185
from google.cloud import speech
183186
from google.cloud.speech.alternative import Alternative
187+
from google.cloud.speech.result import Result
184188
from unit_tests._fixtures import SYNC_RECOGNIZE_RESPONSE
185189

186190
RETURNED = SYNC_RECOGNIZE_RESPONSE
@@ -214,9 +218,12 @@ def test_sync_recognize_source_uri_without_optional_params_no_gax(self):
214218
expected = Alternative.from_api_repr(
215219
SYNC_RECOGNIZE_RESPONSE['results'][0]['alternatives'][0])
216220
self.assertEqual(len(response), 1)
217-
self.assertIsInstance(response[0], Alternative)
218-
self.assertEqual(response[0].transcript, expected.transcript)
219-
self.assertEqual(response[0].confidence, expected.confidence)
221+
self.assertIsInstance(response[0], Result)
222+
self.assertEqual(len(response[0].alternatives), 1)
223+
alternative = response[0].alternatives[0]
224+
225+
self.assertEqual(alternative.transcript, expected.transcript)
226+
self.assertEqual(alternative.confidence, expected.confidence)
220227

221228
def test_sync_recognize_with_empty_results_no_gax(self):
222229
from google.cloud import speech
@@ -710,19 +717,26 @@ class _MockGAPICSpeechAPI(object):
710717
_requests = None
711718
_response = None
712719
_results = None
720+
713721
SERVICE_ADDRESS = 'foo.apis.invalid'
714722

715723
def __init__(self, response=None, channel=None):
716724
self._response = response
717725
self._channel = channel
718726

719727
def async_recognize(self, config, audio):
728+
from google.gapic.longrunning.operations_client import OperationsClient
729+
from google.gax import _OperationFuture
720730
from google.longrunning.operations_pb2 import Operation
731+
from google.cloud.proto.speech.v1beta1.cloud_speech_pb2 import (
732+
AsyncRecognizeResponse)
721733

722734
self.config = config
723735
self.audio = audio
724-
operation = Operation()
725-
return operation
736+
operations_client = mock.Mock(spec=OperationsClient)
737+
operation_future = _OperationFuture(Operation(), operations_client,
738+
AsyncRecognizeResponse, {})
739+
return operation_future
726740

727741
def sync_recognize(self, config, audio):
728742
self.config = config

0 commit comments

Comments
 (0)