Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/api_core/operations_v1/abstract_operations_client.py: 42%
153 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:45 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:45 +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
17import os
18import re
19from typing import Dict, Optional, Sequence, Tuple, Type, Union
21from google.api_core import client_options as client_options_lib # type: ignore
22from google.api_core import gapic_v1 # type: ignore
23from google.api_core import retry as retries # type: ignore
24from google.api_core.operations_v1 import pagers
25from google.api_core.operations_v1.transports.base import (
26 DEFAULT_CLIENT_INFO,
27 OperationsTransport,
28)
29from google.api_core.operations_v1.transports.rest import OperationsRestTransport
30from google.auth import credentials as ga_credentials # type: ignore
31from google.auth.exceptions import MutualTLSChannelError # type: ignore
32from google.auth.transport import mtls # type: ignore
33from google.longrunning import operations_pb2
34from google.oauth2 import service_account # type: ignore
35import grpc
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 = os.getenv(
297 "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
298 ).lower()
299 if use_client_cert not in ("true", "false"):
300 raise ValueError(
301 "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
302 )
303 client_cert_source_func = None
304 is_mtls = False
305 if use_client_cert == "true":
306 if client_options.client_cert_source:
307 is_mtls = True
308 client_cert_source_func = client_options.client_cert_source
309 else:
310 is_mtls = mtls.has_default_client_cert_source()
311 if is_mtls:
312 client_cert_source_func = mtls.default_client_cert_source()
313 else:
314 client_cert_source_func = None
316 # Figure out which api endpoint to use.
317 if client_options.api_endpoint is not None:
318 api_endpoint = client_options.api_endpoint
319 else:
320 use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
321 if use_mtls_env == "never":
322 api_endpoint = self.DEFAULT_ENDPOINT
323 elif use_mtls_env == "always":
324 api_endpoint = self.DEFAULT_MTLS_ENDPOINT
325 elif use_mtls_env == "auto":
326 if is_mtls:
327 api_endpoint = self.DEFAULT_MTLS_ENDPOINT
328 else:
329 api_endpoint = self.DEFAULT_ENDPOINT
330 else:
331 raise MutualTLSChannelError(
332 "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted "
333 "values: never, auto, always"
334 )
336 # Save or instantiate the transport.
337 # Ordinarily, we provide the transport, but allowing a custom transport
338 # instance provides an extensibility point for unusual situations.
339 if isinstance(transport, OperationsTransport):
340 # transport is a OperationsTransport instance.
341 if credentials or client_options.credentials_file:
342 raise ValueError(
343 "When providing a transport instance, "
344 "provide its credentials directly."
345 )
346 if client_options.scopes:
347 raise ValueError(
348 "When providing a transport instance, provide its scopes "
349 "directly."
350 )
351 self._transport = transport
352 else:
353 Transport = type(self).get_transport_class(transport)
354 self._transport = Transport(
355 credentials=credentials,
356 credentials_file=client_options.credentials_file,
357 host=api_endpoint,
358 scopes=client_options.scopes,
359 client_cert_source_for_mtls=client_cert_source_func,
360 quota_project_id=client_options.quota_project_id,
361 client_info=client_info,
362 always_use_jwt_access=True,
363 )
365 def list_operations(
366 self,
367 name: str,
368 filter_: Optional[str] = None,
369 *,
370 page_size: Optional[int] = None,
371 page_token: Optional[str] = None,
372 retry: OptionalRetry = gapic_v1.method.DEFAULT,
373 timeout: Optional[float] = None,
374 compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT,
375 metadata: Sequence[Tuple[str, str]] = (),
376 ) -> pagers.ListOperationsPager:
377 r"""Lists operations that match the specified filter in the request.
378 If the server doesn't support this method, it returns
379 ``UNIMPLEMENTED``.
381 NOTE: the ``name`` binding allows API services to override the
382 binding to use different resource name schemes, such as
383 ``users/*/operations``. To override the binding, API services
384 can add a binding such as ``"/v1/{name=users/*}/operations"`` to
385 their service configuration. For backwards compatibility, the
386 default name includes the operations collection id, however
387 overriding users must ensure the name binding is the parent
388 resource, without the operations collection id.
390 Args:
391 name (str):
392 The name of the operation's parent
393 resource.
394 filter_ (str):
395 The standard list filter.
396 This corresponds to the ``filter`` field
397 on the ``request`` instance; if ``request`` is provided, this
398 should not be set.
399 retry (google.api_core.retry.Retry): Designation of what errors, if any,
400 should be retried.
401 timeout (float): The timeout for this request.
402 metadata (Sequence[Tuple[str, str]]): Strings which should be
403 sent along with the request as metadata.
405 Returns:
406 google.api_core.operations_v1.pagers.ListOperationsPager:
407 The response message for
408 [Operations.ListOperations][google.api_core.operations_v1.Operations.ListOperations].
410 Iterating over this object will yield results and
411 resolve additional pages automatically.
413 """
414 # Create a protobuf request object.
415 request = operations_pb2.ListOperationsRequest(name=name, filter=filter_)
416 if page_size is not None:
417 request.page_size = page_size
418 if page_token is not None:
419 request.page_token = page_token
421 # Wrap the RPC method; this adds retry and timeout information,
422 # and friendly error handling.
423 rpc = self._transport._wrapped_methods[self._transport.list_operations]
425 # Certain fields should be provided within the metadata header;
426 # add these here.
427 metadata = tuple(metadata or ()) + (
428 gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
429 )
431 # Send the request.
432 response = rpc(
433 request,
434 retry=retry,
435 timeout=timeout,
436 compression=compression,
437 metadata=metadata,
438 )
440 # This method is paged; wrap the response in a pager, which provides
441 # an `__iter__` convenience method.
442 response = pagers.ListOperationsPager(
443 method=rpc,
444 request=request,
445 response=response,
446 metadata=metadata,
447 )
449 # Done; return the response.
450 return response
452 def get_operation(
453 self,
454 name: str,
455 *,
456 retry: OptionalRetry = gapic_v1.method.DEFAULT,
457 timeout: Optional[float] = None,
458 compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT,
459 metadata: Sequence[Tuple[str, str]] = (),
460 ) -> operations_pb2.Operation:
461 r"""Gets the latest state of a long-running operation.
462 Clients can use this method to poll the operation result
463 at intervals as recommended by the API service.
465 Args:
466 name (str):
467 The name of the operation resource.
468 retry (google.api_core.retry.Retry): Designation of what errors, if any,
469 should be retried.
470 timeout (float): The timeout for this request.
471 metadata (Sequence[Tuple[str, str]]): Strings which should be
472 sent along with the request as metadata.
474 Returns:
475 google.longrunning.operations_pb2.Operation:
476 This resource represents a long-
477 running operation that is the result of a
478 network API call.
480 """
482 request = operations_pb2.GetOperationRequest(name=name)
484 # Wrap the RPC method; this adds retry and timeout information,
485 # and friendly error handling.
486 rpc = self._transport._wrapped_methods[self._transport.get_operation]
488 # Certain fields should be provided within the metadata header;
489 # add these here.
490 metadata = tuple(metadata or ()) + (
491 gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
492 )
494 # Send the request.
495 response = rpc(
496 request,
497 retry=retry,
498 timeout=timeout,
499 compression=compression,
500 metadata=metadata,
501 )
503 # Done; return the response.
504 return response
506 def delete_operation(
507 self,
508 name: str,
509 *,
510 retry: OptionalRetry = gapic_v1.method.DEFAULT,
511 timeout: Optional[float] = None,
512 compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT,
513 metadata: Sequence[Tuple[str, str]] = (),
514 ) -> None:
515 r"""Deletes a long-running operation. This method indicates that the
516 client is no longer interested in the operation result. It does
517 not cancel the operation. If the server doesn't support this
518 method, it returns ``google.rpc.Code.UNIMPLEMENTED``.
520 Args:
521 name (str):
522 The name of the operation resource to
523 be deleted.
525 This corresponds to the ``name`` field
526 on the ``request`` instance; if ``request`` is provided, this
527 should not be set.
528 retry (google.api_core.retry.Retry): Designation of what errors, if any,
529 should be retried.
530 timeout (float): The timeout for this request.
531 metadata (Sequence[Tuple[str, str]]): Strings which should be
532 sent along with the request as metadata.
533 """
534 # Create the request object.
535 request = operations_pb2.DeleteOperationRequest(name=name)
537 # Wrap the RPC method; this adds retry and timeout information,
538 # and friendly error handling.
539 rpc = self._transport._wrapped_methods[self._transport.delete_operation]
541 # Certain fields should be provided within the metadata header;
542 # add these here.
543 metadata = tuple(metadata or ()) + (
544 gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
545 )
547 # Send the request.
548 rpc(
549 request,
550 retry=retry,
551 timeout=timeout,
552 compression=compression,
553 metadata=metadata,
554 )
556 def cancel_operation(
557 self,
558 name: Optional[str] = None,
559 *,
560 retry: OptionalRetry = gapic_v1.method.DEFAULT,
561 timeout: Optional[float] = None,
562 compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT,
563 metadata: Sequence[Tuple[str, str]] = (),
564 ) -> None:
565 r"""Starts asynchronous cancellation on a long-running operation.
566 The server makes a best effort to cancel the operation, but
567 success is not guaranteed. If the server doesn't support this
568 method, it returns ``google.rpc.Code.UNIMPLEMENTED``. Clients
569 can use
570 [Operations.GetOperation][google.api_core.operations_v1.Operations.GetOperation]
571 or other methods to check whether the cancellation succeeded or
572 whether the operation completed despite cancellation. On
573 successful cancellation, the operation is not deleted; instead,
574 it becomes an operation with an
575 [Operation.error][google.api_core.operations_v1.Operation.error] value with
576 a [google.rpc.Status.code][google.rpc.Status.code] of 1,
577 corresponding to ``Code.CANCELLED``.
579 Args:
580 name (str):
581 The name of the operation resource to
582 be cancelled.
584 This corresponds to the ``name`` field
585 on the ``request`` instance; if ``request`` is provided, this
586 should not be set.
587 retry (google.api_core.retry.Retry): Designation of what errors, if any,
588 should be retried.
589 timeout (float): The timeout for this request.
590 metadata (Sequence[Tuple[str, str]]): Strings which should be
591 sent along with the request as metadata.
592 """
593 # Create the request object.
594 request = operations_pb2.CancelOperationRequest(name=name)
596 # Wrap the RPC method; this adds retry and timeout information,
597 # and friendly error handling.
598 rpc = self._transport._wrapped_methods[self._transport.cancel_operation]
600 # Certain fields should be provided within the metadata header;
601 # add these here.
602 metadata = tuple(metadata or ()) + (
603 gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
604 )
606 # Send the request.
607 rpc(
608 request,
609 retry=retry,
610 timeout=timeout,
611 compression=compression,
612 metadata=metadata,
613 )