1# -*- coding: utf-8 -*-
2# Copyright 2020 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16import warnings
17from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union
18
19from google.api_core import gapic_v1  # type: ignore
20from google.api_core import grpc_helpers_async  # type: ignore
21from google.api_core import operations_v1  # type: ignore
22from google.auth import credentials as ga_credentials  # type: ignore
23from google.auth.transport.grpc import SslCredentials  # type: ignore
24
25import grpc  # type: ignore
26from grpc.experimental import aio  # type: ignore
27
28from google.cloud.speech_v1.types import cloud_speech
29from google.longrunning import operations_pb2  # type: ignore
30from .base import SpeechTransport, DEFAULT_CLIENT_INFO
31from .grpc import SpeechGrpcTransport
32
33
34class SpeechGrpcAsyncIOTransport(SpeechTransport):
35    """gRPC AsyncIO backend transport for Speech.
36
37    Service that implements Google Cloud Speech API.
38
39    This class defines the same methods as the primary client, so the
40    primary client can load the underlying transport implementation
41    and call it.
42
43    It sends protocol buffers over the wire using gRPC (which is built on
44    top of HTTP/2); the ``grpcio`` package must be installed.
45    """
46
47    _grpc_channel: aio.Channel
48    _stubs: Dict[str, Callable] = {}
49
50    @classmethod
51    def create_channel(
52        cls,
53        host: str = "speech.googleapis.com",
54        credentials: ga_credentials.Credentials = None,
55        credentials_file: Optional[str] = None,
56        scopes: Optional[Sequence[str]] = None,
57        quota_project_id: Optional[str] = None,
58        **kwargs,
59    ) -> aio.Channel:
60        """Create and return a gRPC AsyncIO channel object.
61        Args:
62            host (Optional[str]): The host for the channel to use.
63            credentials (Optional[~.Credentials]): The
64                authorization credentials to attach to requests. These
65                credentials identify this application to the service. If
66                none are specified, the client will attempt to ascertain
67                the credentials from the environment.
68            credentials_file (Optional[str]): A file with credentials that can
69                be loaded with :func:`google.auth.load_credentials_from_file`.
70                This argument is ignored if ``channel`` is provided.
71            scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
72                service. These are only used when credentials are not specified and
73                are passed to :func:`google.auth.default`.
74            quota_project_id (Optional[str]): An optional project to use for billing
75                and quota.
76            kwargs (Optional[dict]): Keyword arguments, which are passed to the
77                channel creation.
78        Returns:
79            aio.Channel: A gRPC AsyncIO channel object.
80        """
81
82        return grpc_helpers_async.create_channel(
83            host,
84            credentials=credentials,
85            credentials_file=credentials_file,
86            quota_project_id=quota_project_id,
87            default_scopes=cls.AUTH_SCOPES,
88            scopes=scopes,
89            default_host=cls.DEFAULT_HOST,
90            **kwargs,
91        )
92
93    def __init__(
94        self,
95        *,
96        host: str = "speech.googleapis.com",
97        credentials: ga_credentials.Credentials = None,
98        credentials_file: Optional[str] = None,
99        scopes: Optional[Sequence[str]] = None,
100        channel: aio.Channel = None,
101        api_mtls_endpoint: str = None,
102        client_cert_source: Callable[[], Tuple[bytes, bytes]] = None,
103        ssl_channel_credentials: grpc.ChannelCredentials = None,
104        client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None,
105        quota_project_id=None,
106        client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
107        always_use_jwt_access: Optional[bool] = False,
108    ) -> None:
109        """Instantiate the transport.
110
111        Args:
112            host (Optional[str]):
113                 The hostname to connect to.
114            credentials (Optional[google.auth.credentials.Credentials]): The
115                authorization credentials to attach to requests. These
116                credentials identify the application to the service; if none
117                are specified, the client will attempt to ascertain the
118                credentials from the environment.
119                This argument is ignored if ``channel`` is provided.
120            credentials_file (Optional[str]): A file with credentials that can
121                be loaded with :func:`google.auth.load_credentials_from_file`.
122                This argument is ignored if ``channel`` is provided.
123            scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
124                service. These are only used when credentials are not specified and
125                are passed to :func:`google.auth.default`.
126            channel (Optional[aio.Channel]): A ``Channel`` instance through
127                which to make calls.
128            api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
129                If provided, it overrides the ``host`` argument and tries to create
130                a mutual TLS channel with client SSL credentials from
131                ``client_cert_source`` or application default SSL credentials.
132            client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
133                Deprecated. A callback to provide client SSL certificate bytes and
134                private key bytes, both in PEM format. It is ignored if
135                ``api_mtls_endpoint`` is None.
136            ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
137                for the grpc channel. It is ignored if ``channel`` is provided.
138            client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]):
139                A callback to provide client certificate bytes and private key bytes,
140                both in PEM format. It is used to configure a mutual TLS channel. It is
141                ignored if ``channel`` or ``ssl_channel_credentials`` is provided.
142            quota_project_id (Optional[str]): An optional project to use for billing
143                and quota.
144            client_info (google.api_core.gapic_v1.client_info.ClientInfo):
145                The client info used to send a user-agent string along with
146                API requests. If ``None``, then default info will be used.
147                Generally, you only need to set this if you're developing
148                your own client library.
149            always_use_jwt_access (Optional[bool]): Whether self signed JWT should
150                be used for service account credentials.
151
152        Raises:
153            google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
154              creation failed for any reason.
155          google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
156              and ``credentials_file`` are passed.
157        """
158        self._grpc_channel = None
159        self._ssl_channel_credentials = ssl_channel_credentials
160        self._stubs: Dict[str, Callable] = {}
161        self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None
162
163        if api_mtls_endpoint:
164            warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning)
165        if client_cert_source:
166            warnings.warn("client_cert_source is deprecated", DeprecationWarning)
167
168        if channel:
169            # Ignore credentials if a channel was passed.
170            credentials = False
171            # If a channel was explicitly provided, set it.
172            self._grpc_channel = channel
173            self._ssl_channel_credentials = None
174        else:
175            if api_mtls_endpoint:
176                host = api_mtls_endpoint
177
178                # Create SSL credentials with client_cert_source or application
179                # default SSL credentials.
180                if client_cert_source:
181                    cert, key = client_cert_source()
182                    self._ssl_channel_credentials = grpc.ssl_channel_credentials(
183                        certificate_chain=cert, private_key=key
184                    )
185                else:
186                    self._ssl_channel_credentials = SslCredentials().ssl_credentials
187
188            else:
189                if client_cert_source_for_mtls and not ssl_channel_credentials:
190                    cert, key = client_cert_source_for_mtls()
191                    self._ssl_channel_credentials = grpc.ssl_channel_credentials(
192                        certificate_chain=cert, private_key=key
193                    )
194
195        # The base transport sets the host, credentials and scopes
196        super().__init__(
197            host=host,
198            credentials=credentials,
199            credentials_file=credentials_file,
200            scopes=scopes,
201            quota_project_id=quota_project_id,
202            client_info=client_info,
203            always_use_jwt_access=always_use_jwt_access,
204        )
205
206        if not self._grpc_channel:
207            self._grpc_channel = type(self).create_channel(
208                self._host,
209                credentials=self._credentials,
210                credentials_file=credentials_file,
211                scopes=self._scopes,
212                ssl_credentials=self._ssl_channel_credentials,
213                quota_project_id=quota_project_id,
214                options=[
215                    ("grpc.max_send_message_length", -1),
216                    ("grpc.max_receive_message_length", -1),
217                ],
218            )
219
220        # Wrap messages. This must be done after self._grpc_channel exists
221        self._prep_wrapped_messages(client_info)
222
223    @property
224    def grpc_channel(self) -> aio.Channel:
225        """Create the channel designed to connect to this service.
226
227        This property caches on the instance; repeated calls return
228        the same channel.
229        """
230        # Return the channel from cache.
231        return self._grpc_channel
232
233    @property
234    def operations_client(self) -> operations_v1.OperationsAsyncClient:
235        """Create the client designed to process long-running operations.
236
237        This property caches on the instance; repeated calls return the same
238        client.
239        """
240        # Sanity check: Only create a new client if we do not already have one.
241        if self._operations_client is None:
242            self._operations_client = operations_v1.OperationsAsyncClient(
243                self.grpc_channel
244            )
245
246        # Return the client from cache.
247        return self._operations_client
248
249    @property
250    def recognize(
251        self,
252    ) -> Callable[
253        [cloud_speech.RecognizeRequest], Awaitable[cloud_speech.RecognizeResponse]
254    ]:
255        r"""Return a callable for the recognize method over gRPC.
256
257        Performs synchronous speech recognition: receive
258        results after all audio has been sent and processed.
259
260        Returns:
261            Callable[[~.RecognizeRequest],
262                    Awaitable[~.RecognizeResponse]]:
263                A function that, when called, will call the underlying RPC
264                on the server.
265        """
266        # Generate a "stub function" on-the-fly which will actually make
267        # the request.
268        # gRPC handles serialization and deserialization, so we just need
269        # to pass in the functions for each.
270        if "recognize" not in self._stubs:
271            self._stubs["recognize"] = self.grpc_channel.unary_unary(
272                "/google.cloud.speech.v1.Speech/Recognize",
273                request_serializer=cloud_speech.RecognizeRequest.serialize,
274                response_deserializer=cloud_speech.RecognizeResponse.deserialize,
275            )
276        return self._stubs["recognize"]
277
278    @property
279    def long_running_recognize(
280        self,
281    ) -> Callable[
282        [cloud_speech.LongRunningRecognizeRequest], Awaitable[operations_pb2.Operation]
283    ]:
284        r"""Return a callable for the long running recognize method over gRPC.
285
286        Performs asynchronous speech recognition: receive results via
287        the google.longrunning.Operations interface. Returns either an
288        ``Operation.error`` or an ``Operation.response`` which contains
289        a ``LongRunningRecognizeResponse`` message. For more information
290        on asynchronous speech recognition, see the
291        `how-to <https://cloud.google.com/speech-to-text/docs/async-recognize>`__.
292
293        Returns:
294            Callable[[~.LongRunningRecognizeRequest],
295                    Awaitable[~.Operation]]:
296                A function that, when called, will call the underlying RPC
297                on the server.
298        """
299        # Generate a "stub function" on-the-fly which will actually make
300        # the request.
301        # gRPC handles serialization and deserialization, so we just need
302        # to pass in the functions for each.
303        if "long_running_recognize" not in self._stubs:
304            self._stubs["long_running_recognize"] = self.grpc_channel.unary_unary(
305                "/google.cloud.speech.v1.Speech/LongRunningRecognize",
306                request_serializer=cloud_speech.LongRunningRecognizeRequest.serialize,
307                response_deserializer=operations_pb2.Operation.FromString,
308            )
309        return self._stubs["long_running_recognize"]
310
311    @property
312    def streaming_recognize(
313        self,
314    ) -> Callable[
315        [cloud_speech.StreamingRecognizeRequest],
316        Awaitable[cloud_speech.StreamingRecognizeResponse],
317    ]:
318        r"""Return a callable for the streaming recognize method over gRPC.
319
320        Performs bidirectional streaming speech recognition:
321        receive results while sending audio. This method is only
322        available via the gRPC API (not REST).
323
324        Returns:
325            Callable[[~.StreamingRecognizeRequest],
326                    Awaitable[~.StreamingRecognizeResponse]]:
327                A function that, when called, will call the underlying RPC
328                on the server.
329        """
330        # Generate a "stub function" on-the-fly which will actually make
331        # the request.
332        # gRPC handles serialization and deserialization, so we just need
333        # to pass in the functions for each.
334        if "streaming_recognize" not in self._stubs:
335            self._stubs["streaming_recognize"] = self.grpc_channel.stream_stream(
336                "/google.cloud.speech.v1.Speech/StreamingRecognize",
337                request_serializer=cloud_speech.StreamingRecognizeRequest.serialize,
338                response_deserializer=cloud_speech.StreamingRecognizeResponse.deserialize,
339            )
340        return self._stubs["streaming_recognize"]
341
342    def close(self):
343        return self.grpc_channel.close()
344
345
346__all__ = ("SpeechGrpcAsyncIOTransport",)
347