Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/api_core/operations_v1/abstract_operations_client.py: 43%
151 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-06 06:03 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-06 06:03 +0000
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#
16from collections import OrderedDict
17from distutils import util
18import os
19import re
20from typing import Dict, Optional, Sequence, Tuple, Type, Union
22from google.api_core import client_options as client_options_lib # type: ignore
23from google.api_core import gapic_v1 # type: ignore
24from google.api_core import retry as retries # type: ignore
25from google.api_core.operations_v1 import pagers
26from google.api_core.operations_v1.transports.base import (
27 DEFAULT_CLIENT_INFO,
28 OperationsTransport,
29)
30from google.api_core.operations_v1.transports.rest import OperationsRestTransport
31from google.auth import credentials as ga_credentials # type: ignore
32from google.auth.exceptions import MutualTLSChannelError # type: ignore
33from google.auth.transport import mtls # type: ignore
34from google.longrunning import operations_pb2
35from google.oauth2 import service_account # type: ignore
37OptionalRetry = Union[retries.Retry, object]
40class AbstractOperationsClientMeta(type):
41 """Metaclass for the Operations client.
43 This provides class-level methods for building and retrieving
44 support objects (e.g. transport) without polluting the client instance
45 objects.
46 """
48 _transport_registry = OrderedDict() # type: Dict[str, Type[OperationsTransport]]
49 _transport_registry["rest"] = OperationsRestTransport
51 def get_transport_class(
52 cls,
53 label: Optional[str] = None,
54 ) -> Type[OperationsTransport]:
55 """Returns an appropriate transport class.
57 Args:
58 label: The name of the desired transport. If none is
59 provided, then the first transport in the registry is used.
61 Returns:
62 The transport class to use.
63 """
64 # If a specific transport is requested, return that one.
65 if label:
66 return cls._transport_registry[label]
68 # No transport is requested; return the default (that is, the first one
69 # in the dictionary).
70 return next(iter(cls._transport_registry.values()))
73class AbstractOperationsClient(metaclass=AbstractOperationsClientMeta):
74 """Manages long-running operations with an API service.
76 When an API method normally takes long time to complete, it can be
77 designed to return [Operation][google.api_core.operations_v1.Operation] to the
78 client, and the client can use this interface to receive the real
79 response asynchronously by polling the operation resource, or pass
80 the operation resource to another API (such as Google Cloud Pub/Sub
81 API) to receive the response. Any API service that returns
82 long-running operations should implement the ``Operations``
83 interface so developers can have a consistent client experience.
84 """
86 @staticmethod
87 def _get_default_mtls_endpoint(api_endpoint):
88 """Converts api endpoint to mTLS endpoint.
90 Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
91 "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
92 Args:
93 api_endpoint (Optional[str]): the api endpoint to convert.
94 Returns:
95 str: converted mTLS api endpoint.
96 """
97 if not api_endpoint:
98 return api_endpoint
100 mtls_endpoint_re = re.compile(
101 r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
102 )
104 m = mtls_endpoint_re.match(api_endpoint)
105 name, mtls, sandbox, googledomain = m.groups()
106 if mtls or not googledomain:
107 return api_endpoint
109 if sandbox:
110 return api_endpoint.replace(
111 "sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
112 )
114 return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")
116 DEFAULT_ENDPOINT = "longrunning.googleapis.com"
117 DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore
118 DEFAULT_ENDPOINT
119 )
121 @classmethod
122 def from_service_account_info(cls, info: dict, *args, **kwargs):
123 """Creates an instance of this client using the provided credentials
124 info.
126 Args:
127 info (dict): The service account private key info.
128 args: Additional arguments to pass to the constructor.
129 kwargs: Additional arguments to pass to the constructor.
131 Returns:
132 AbstractOperationsClient: The constructed client.
133 """
134 credentials = service_account.Credentials.from_service_account_info(info)
135 kwargs["credentials"] = credentials
136 return cls(*args, **kwargs)
138 @classmethod
139 def from_service_account_file(cls, filename: str, *args, **kwargs):
140 """Creates an instance of this client using the provided credentials
141 file.
143 Args:
144 filename (str): The path to the service account private key json
145 file.
146 args: Additional arguments to pass to the constructor.
147 kwargs: Additional arguments to pass to the constructor.
149 Returns:
150 AbstractOperationsClient: The constructed client.
151 """
152 credentials = service_account.Credentials.from_service_account_file(filename)
153 kwargs["credentials"] = credentials
154 return cls(*args, **kwargs)
156 from_service_account_json = from_service_account_file
158 @property
159 def transport(self) -> OperationsTransport:
160 """Returns the transport used by the client instance.
162 Returns:
163 OperationsTransport: The transport used by the client
164 instance.
165 """
166 return self._transport
168 @staticmethod
169 def common_billing_account_path(
170 billing_account: str,
171 ) -> str:
172 """Returns a fully-qualified billing_account string."""
173 return "billingAccounts/{billing_account}".format(
174 billing_account=billing_account,
175 )
177 @staticmethod
178 def parse_common_billing_account_path(path: str) -> Dict[str, str]:
179 """Parse a billing_account path into its component segments."""
180 m = re.match(r"^billingAccounts/(?P<billing_account>.+?)$", path)
181 return m.groupdict() if m else {}
183 @staticmethod
184 def common_folder_path(
185 folder: str,
186 ) -> str:
187 """Returns a fully-qualified folder string."""
188 return "folders/{folder}".format(
189 folder=folder,
190 )
192 @staticmethod
193 def parse_common_folder_path(path: str) -> Dict[str, str]:
194 """Parse a folder path into its component segments."""
195 m = re.match(r"^folders/(?P<folder>.+?)$", path)
196 return m.groupdict() if m else {}
198 @staticmethod
199 def common_organization_path(
200 organization: str,
201 ) -> str:
202 """Returns a fully-qualified organization string."""
203 return "organizations/{organization}".format(
204 organization=organization,
205 )
207 @staticmethod
208 def parse_common_organization_path(path: str) -> Dict[str, str]:
209 """Parse a organization path into its component segments."""
210 m = re.match(r"^organizations/(?P<organization>.+?)$", path)
211 return m.groupdict() if m else {}
213 @staticmethod
214 def common_project_path(
215 project: str,
216 ) -> str:
217 """Returns a fully-qualified project string."""
218 return "projects/{project}".format(
219 project=project,
220 )
222 @staticmethod
223 def parse_common_project_path(path: str) -> Dict[str, str]:
224 """Parse a project path into its component segments."""
225 m = re.match(r"^projects/(?P<project>.+?)$", path)
226 return m.groupdict() if m else {}
228 @staticmethod
229 def common_location_path(
230 project: str,
231 location: str,
232 ) -> str:
233 """Returns a fully-qualified location string."""
234 return "projects/{project}/locations/{location}".format(
235 project=project,
236 location=location,
237 )
239 @staticmethod
240 def parse_common_location_path(path: str) -> Dict[str, str]:
241 """Parse a location path into its component segments."""
242 m = re.match(r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)$", path)
243 return m.groupdict() if m else {}
245 def __init__(
246 self,
247 *,
248 credentials: Optional[ga_credentials.Credentials] = None,
249 transport: Union[str, OperationsTransport, None] = None,
250 client_options: Optional[client_options_lib.ClientOptions] = None,
251 client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
252 ) -> None:
253 """Instantiates the operations client.
255 Args:
256 credentials (Optional[google.auth.credentials.Credentials]): The
257 authorization credentials to attach to requests. These
258 credentials identify the application to the service; if none
259 are specified, the client will attempt to ascertain the
260 credentials from the environment.
261 transport (Union[str, OperationsTransport]): The
262 transport to use. If set to None, a transport is chosen
263 automatically.
264 client_options (google.api_core.client_options.ClientOptions): Custom options for the
265 client. It won't take effect if a ``transport`` instance is provided.
266 (1) The ``api_endpoint`` property can be used to override the
267 default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT
268 environment variable can also be used to override the endpoint:
269 "always" (always use the default mTLS endpoint), "never" (always
270 use the default regular endpoint) and "auto" (auto switch to the
271 default mTLS endpoint if client certificate is present, this is
272 the default value). However, the ``api_endpoint`` property takes
273 precedence if provided.
274 (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
275 is "true", then the ``client_cert_source`` property can be used
276 to provide client certificate for mutual TLS transport. If
277 not provided, the default SSL client certificate will be used if
278 present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
279 set, no client certificate will be used.
280 client_info (google.api_core.gapic_v1.client_info.ClientInfo):
281 The client info used to send a user-agent string along with
282 API requests. If ``None``, then default info will be used.
283 Generally, you only need to set this if you're developing
284 your own client library.
286 Raises:
287 google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
288 creation failed for any reason.
289 """
290 if isinstance(client_options, dict):
291 client_options = client_options_lib.from_dict(client_options)
292 if client_options is None:
293 client_options = client_options_lib.ClientOptions()
295 # Create SSL credentials for mutual TLS if needed.
296 use_client_cert = bool(
297 util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"))
298 )
300 client_cert_source_func = None
301 is_mtls = False
302 if use_client_cert:
303 if client_options.client_cert_source:
304 is_mtls = True
305 client_cert_source_func = client_options.client_cert_source
306 else:
307 is_mtls = mtls.has_default_client_cert_source()
308 if is_mtls:
309 client_cert_source_func = mtls.default_client_cert_source()
310 else:
311 client_cert_source_func = None
313 # Figure out which api endpoint to use.
314 if client_options.api_endpoint is not None:
315 api_endpoint = client_options.api_endpoint
316 else:
317 use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
318 if use_mtls_env == "never":
319 api_endpoint = self.DEFAULT_ENDPOINT
320 elif use_mtls_env == "always":
321 api_endpoint = self.DEFAULT_MTLS_ENDPOINT
322 elif use_mtls_env == "auto":
323 if is_mtls:
324 api_endpoint = self.DEFAULT_MTLS_ENDPOINT
325 else:
326 api_endpoint = self.DEFAULT_ENDPOINT
327 else:
328 raise MutualTLSChannelError(
329 "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted "
330 "values: never, auto, always"
331 )
333 # Save or instantiate the transport.
334 # Ordinarily, we provide the transport, but allowing a custom transport
335 # instance provides an extensibility point for unusual situations.
336 if isinstance(transport, OperationsTransport):
337 # transport is a OperationsTransport instance.
338 if credentials or client_options.credentials_file:
339 raise ValueError(
340 "When providing a transport instance, "
341 "provide its credentials directly."
342 )
343 if client_options.scopes:
344 raise ValueError(
345 "When providing a transport instance, provide its scopes "
346 "directly."
347 )
348 self._transport = transport
349 else:
350 Transport = type(self).get_transport_class(transport)
351 self._transport = Transport(
352 credentials=credentials,
353 credentials_file=client_options.credentials_file,
354 host=api_endpoint,
355 scopes=client_options.scopes,
356 client_cert_source_for_mtls=client_cert_source_func,
357 quota_project_id=client_options.quota_project_id,
358 client_info=client_info,
359 always_use_jwt_access=True,
360 )
362 def list_operations(
363 self,
364 name: str,
365 filter_: Optional[str] = None,
366 *,
367 page_size: Optional[int] = None,
368 page_token: Optional[str] = None,
369 retry: OptionalRetry = gapic_v1.method.DEFAULT,
370 timeout: Optional[float] = None,
371 metadata: Sequence[Tuple[str, str]] = (),
372 ) -> pagers.ListOperationsPager:
373 r"""Lists operations that match the specified filter in the request.
374 If the server doesn't support this method, it returns
375 ``UNIMPLEMENTED``.
377 NOTE: the ``name`` binding allows API services to override the
378 binding to use different resource name schemes, such as
379 ``users/*/operations``. To override the binding, API services
380 can add a binding such as ``"/v1/{name=users/*}/operations"`` to
381 their service configuration. For backwards compatibility, the
382 default name includes the operations collection id, however
383 overriding users must ensure the name binding is the parent
384 resource, without the operations collection id.
386 Args:
387 name (str):
388 The name of the operation's parent
389 resource.
390 filter_ (str):
391 The standard list filter.
392 This corresponds to the ``filter`` field
393 on the ``request`` instance; if ``request`` is provided, this
394 should not be set.
395 retry (google.api_core.retry.Retry): Designation of what errors, if any,
396 should be retried.
397 timeout (float): The timeout for this request.
398 metadata (Sequence[Tuple[str, str]]): Strings which should be
399 sent along with the request as metadata.
401 Returns:
402 google.api_core.operations_v1.pagers.ListOperationsPager:
403 The response message for
404 [Operations.ListOperations][google.api_core.operations_v1.Operations.ListOperations].
406 Iterating over this object will yield results and
407 resolve additional pages automatically.
409 """
410 # Create a protobuf request object.
411 request = operations_pb2.ListOperationsRequest(name=name, filter=filter_)
412 if page_size is not None:
413 request.page_size = page_size
414 if page_token is not None:
415 request.page_token = page_token
417 # Wrap the RPC method; this adds retry and timeout information,
418 # and friendly error handling.
419 rpc = self._transport._wrapped_methods[self._transport.list_operations]
421 # Certain fields should be provided within the metadata header;
422 # add these here.
423 metadata = tuple(metadata or ()) + (
424 gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
425 )
427 # Send the request.
428 response = rpc(
429 request,
430 retry=retry,
431 timeout=timeout,
432 metadata=metadata,
433 )
435 # This method is paged; wrap the response in a pager, which provides
436 # an `__iter__` convenience method.
437 response = pagers.ListOperationsPager(
438 method=rpc,
439 request=request,
440 response=response,
441 metadata=metadata,
442 )
444 # Done; return the response.
445 return response
447 def get_operation(
448 self,
449 name: str,
450 *,
451 retry: OptionalRetry = gapic_v1.method.DEFAULT,
452 timeout: Optional[float] = None,
453 metadata: Sequence[Tuple[str, str]] = (),
454 ) -> operations_pb2.Operation:
455 r"""Gets the latest state of a long-running operation.
456 Clients can use this method to poll the operation result
457 at intervals as recommended by the API service.
459 Args:
460 name (str):
461 The name of the operation resource.
462 retry (google.api_core.retry.Retry): Designation of what errors, if any,
463 should be retried.
464 timeout (float): The timeout for this request.
465 metadata (Sequence[Tuple[str, str]]): Strings which should be
466 sent along with the request as metadata.
468 Returns:
469 google.longrunning.operations_pb2.Operation:
470 This resource represents a long-
471 unning operation that is the result of a
472 network API call.
474 """
476 request = operations_pb2.GetOperationRequest(name=name)
478 # Wrap the RPC method; this adds retry and timeout information,
479 # and friendly error handling.
480 rpc = self._transport._wrapped_methods[self._transport.get_operation]
482 # Certain fields should be provided within the metadata header;
483 # add these here.
484 metadata = tuple(metadata or ()) + (
485 gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
486 )
488 # Send the request.
489 response = rpc(
490 request,
491 retry=retry,
492 timeout=timeout,
493 metadata=metadata,
494 )
496 # Done; return the response.
497 return response
499 def delete_operation(
500 self,
501 name: str,
502 *,
503 retry: OptionalRetry = gapic_v1.method.DEFAULT,
504 timeout: Optional[float] = None,
505 metadata: Sequence[Tuple[str, str]] = (),
506 ) -> None:
507 r"""Deletes a long-running operation. This method indicates that the
508 client is no longer interested in the operation result. It does
509 not cancel the operation. If the server doesn't support this
510 method, it returns ``google.rpc.Code.UNIMPLEMENTED``.
512 Args:
513 name (str):
514 The name of the operation resource to
515 be deleted.
517 This corresponds to the ``name`` field
518 on the ``request`` instance; if ``request`` is provided, this
519 should not be set.
520 retry (google.api_core.retry.Retry): Designation of what errors, if any,
521 should be retried.
522 timeout (float): The timeout for this request.
523 metadata (Sequence[Tuple[str, str]]): Strings which should be
524 sent along with the request as metadata.
525 """
526 # Create the request object.
527 request = operations_pb2.DeleteOperationRequest(name=name)
529 # Wrap the RPC method; this adds retry and timeout information,
530 # and friendly error handling.
531 rpc = self._transport._wrapped_methods[self._transport.delete_operation]
533 # Certain fields should be provided within the metadata header;
534 # add these here.
535 metadata = tuple(metadata or ()) + (
536 gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
537 )
539 # Send the request.
540 rpc(
541 request,
542 retry=retry,
543 timeout=timeout,
544 metadata=metadata,
545 )
547 def cancel_operation(
548 self,
549 name: Optional[str] = None,
550 *,
551 retry: OptionalRetry = gapic_v1.method.DEFAULT,
552 timeout: Optional[float] = None,
553 metadata: Sequence[Tuple[str, str]] = (),
554 ) -> None:
555 r"""Starts asynchronous cancellation on a long-running operation.
556 The server makes a best effort to cancel the operation, but
557 success is not guaranteed. If the server doesn't support this
558 method, it returns ``google.rpc.Code.UNIMPLEMENTED``. Clients
559 can use
560 [Operations.GetOperation][google.api_core.operations_v1.Operations.GetOperation]
561 or other methods to check whether the cancellation succeeded or
562 whether the operation completed despite cancellation. On
563 successful cancellation, the operation is not deleted; instead,
564 it becomes an operation with an
565 [Operation.error][google.api_core.operations_v1.Operation.error] value with
566 a [google.rpc.Status.code][google.rpc.Status.code] of 1,
567 corresponding to ``Code.CANCELLED``.
569 Args:
570 name (str):
571 The name of the operation resource to
572 be cancelled.
574 This corresponds to the ``name`` field
575 on the ``request`` instance; if ``request`` is provided, this
576 should not be set.
577 retry (google.api_core.retry.Retry): Designation of what errors, if any,
578 should be retried.
579 timeout (float): The timeout for this request.
580 metadata (Sequence[Tuple[str, str]]): Strings which should be
581 sent along with the request as metadata.
582 """
583 # Create the request object.
584 request = operations_pb2.CancelOperationRequest(name=name)
586 # Wrap the RPC method; this adds retry and timeout information,
587 # and friendly error handling.
588 rpc = self._transport._wrapped_methods[self._transport.cancel_operation]
590 # Certain fields should be provided within the metadata header;
591 # add these here.
592 metadata = tuple(metadata or ()) + (
593 gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
594 )
596 # Send the request.
597 rpc(
598 request,
599 retry=retry,
600 timeout=timeout,
601 metadata=metadata,
602 )