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

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 

21 

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 

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 = bool( 

297 util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) 

298 ) 

299 

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 

312 

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 ) 

332 

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 ) 

361 

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

376 

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. 

385 

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. 

400 

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

405 

406 Iterating over this object will yield results and 

407 resolve additional pages automatically. 

408 

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 

416 

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] 

420 

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 ) 

426 

427 # Send the request. 

428 response = rpc( 

429 request, 

430 retry=retry, 

431 timeout=timeout, 

432 metadata=metadata, 

433 ) 

434 

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 ) 

443 

444 # Done; return the response. 

445 return response 

446 

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. 

458 

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. 

467 

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. 

473 

474 """ 

475 

476 request = operations_pb2.GetOperationRequest(name=name) 

477 

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] 

481 

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 ) 

487 

488 # Send the request. 

489 response = rpc( 

490 request, 

491 retry=retry, 

492 timeout=timeout, 

493 metadata=metadata, 

494 ) 

495 

496 # Done; return the response. 

497 return response 

498 

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

511 

512 Args: 

513 name (str): 

514 The name of the operation resource to 

515 be deleted. 

516 

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) 

528 

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] 

532 

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 ) 

538 

539 # Send the request. 

540 rpc( 

541 request, 

542 retry=retry, 

543 timeout=timeout, 

544 metadata=metadata, 

545 ) 

546 

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

568 

569 Args: 

570 name (str): 

571 The name of the operation resource to 

572 be cancelled. 

573 

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) 

585 

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] 

589 

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 ) 

595 

596 # Send the request. 

597 rpc( 

598 request, 

599 retry=retry, 

600 timeout=timeout, 

601 metadata=metadata, 

602 )