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

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 

20 

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 

36 

37OptionalRetry = Union[retries.Retry, object] 

38 

39 

40class AbstractOperationsClientMeta(type): 

41 """Metaclass for the Operations client. 

42 

43 This provides class-level methods for building and retrieving 

44 support objects (e.g. transport) without polluting the client instance 

45 objects. 

46 """ 

47 

48 _transport_registry = OrderedDict() # type: Dict[str, Type[OperationsTransport]] 

49 _transport_registry["rest"] = OperationsRestTransport 

50 

51 def get_transport_class( 

52 cls, 

53 label: Optional[str] = None, 

54 ) -> Type[OperationsTransport]: 

55 """Returns an appropriate transport class. 

56 

57 Args: 

58 label: The name of the desired transport. If none is 

59 provided, then the first transport in the registry is used. 

60 

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] 

67 

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())) 

71 

72 

73class AbstractOperationsClient(metaclass=AbstractOperationsClientMeta): 

74 """Manages long-running operations with an API service. 

75 

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 """ 

85 

86 @staticmethod 

87 def _get_default_mtls_endpoint(api_endpoint): 

88 """Converts api endpoint to mTLS endpoint. 

89 

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 

99 

100 mtls_endpoint_re = re.compile( 

101 r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?" 

102 ) 

103 

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 

108 

109 if sandbox: 

110 return api_endpoint.replace( 

111 "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" 

112 ) 

113 

114 return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") 

115 

116 DEFAULT_ENDPOINT = "longrunning.googleapis.com" 

117 DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore 

118 DEFAULT_ENDPOINT 

119 ) 

120 

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. 

125 

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. 

130 

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) 

137 

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. 

142 

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. 

148 

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) 

155 

156 from_service_account_json = from_service_account_file 

157 

158 @property 

159 def transport(self) -> OperationsTransport: 

160 """Returns the transport used by the client instance. 

161 

162 Returns: 

163 OperationsTransport: The transport used by the client 

164 instance. 

165 """ 

166 return self._transport 

167 

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 ) 

176 

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 {} 

182 

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 ) 

191 

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 {} 

197 

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 ) 

206 

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 {} 

212 

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 ) 

221 

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 {} 

227 

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 ) 

238 

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 {} 

244 

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. 

254 

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. 

285 

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() 

294 

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 

315 

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 ) 

335 

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 ) 

364 

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``. 

380 

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. 

389 

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. 

404 

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]. 

409 

410 Iterating over this object will yield results and 

411 resolve additional pages automatically. 

412 

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 

420 

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] 

424 

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 ) 

430 

431 # Send the request. 

432 response = rpc( 

433 request, 

434 retry=retry, 

435 timeout=timeout, 

436 compression=compression, 

437 metadata=metadata, 

438 ) 

439 

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 ) 

448 

449 # Done; return the response. 

450 return response 

451 

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. 

464 

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. 

473 

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. 

479 

480 """ 

481 

482 request = operations_pb2.GetOperationRequest(name=name) 

483 

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] 

487 

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 ) 

493 

494 # Send the request. 

495 response = rpc( 

496 request, 

497 retry=retry, 

498 timeout=timeout, 

499 compression=compression, 

500 metadata=metadata, 

501 ) 

502 

503 # Done; return the response. 

504 return response 

505 

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``. 

519 

520 Args: 

521 name (str): 

522 The name of the operation resource to 

523 be deleted. 

524 

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) 

536 

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] 

540 

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 ) 

546 

547 # Send the request. 

548 rpc( 

549 request, 

550 retry=retry, 

551 timeout=timeout, 

552 compression=compression, 

553 metadata=metadata, 

554 ) 

555 

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``. 

578 

579 Args: 

580 name (str): 

581 The name of the operation resource to 

582 be cancelled. 

583 

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) 

595 

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] 

599 

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 ) 

605 

606 # Send the request. 

607 rpc( 

608 request, 

609 retry=retry, 

610 timeout=timeout, 

611 compression=compression, 

612 metadata=metadata, 

613 )