From 293ecdad78b51f248f8d5c023bdba3bac998ea5c Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 22:27:27 -0700 Subject: [PATCH 1/3] chore: Update gapic-generator-python to v1.17.1 (#1090) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: Update gapic-generator-python to v1.17.0 PiperOrigin-RevId: 627075268 Source-Link: https://github.com/googleapis/googleapis/commit/b0a5b9d2b7021525100441756e3914ed3d616cb6 Source-Link: https://github.com/googleapis/googleapis-gen/commit/56b44dca0ceea3ad2afe9ce4a9aeadf9bdf1b445 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNTZiNDRkY2EwY2VlYTNhZDJhZmU5Y2U0YTlhZWFkZjliZGYxYjQ0NSJ9 chore: Update gapic-generator-python to v1.17.0 PiperOrigin-RevId: 626992299 Source-Link: https://github.com/googleapis/googleapis/commit/e495ff587351369637ecee17bfd260d2e76a41f7 Source-Link: https://github.com/googleapis/googleapis-gen/commit/2463c3c27110a92d1fab175109ef94bfe5967168 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiMjQ2M2MzYzI3MTEwYTkyZDFmYWIxNzUxMDllZjk0YmZlNTk2NzE2OCJ9 feat(spanner): adding `EXPECTED_FULFILLMENT_PERIOD` to the indicate instance creation times (with `FULFILLMENT_PERIOD_NORMAL` or `FULFILLMENT_PERIOD_EXTENDED` ENUM) with the extended instance creation time triggered by On-Demand Capacity Feature PiperOrigin-RevId: 621488048 Source-Link: https://github.com/googleapis/googleapis/commit/0aa0992a5430c211a73c9b861d65e1e8a7a91a9e Source-Link: https://github.com/googleapis/googleapis-gen/commit/b8ad4c73a5c05fed8bcfddb931326996c3441791 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYjhhZDRjNzNhNWMwNWZlZDhiY2ZkZGI5MzEzMjY5OTZjMzQ0MTc5MSJ9 chore: Update gapic-generator-python to v1.16.1 PiperOrigin-RevId: 618243632 Source-Link: https://github.com/googleapis/googleapis/commit/078a38bd240827be8e69a5b62993380d1b047994 Source-Link: https://github.com/googleapis/googleapis-gen/commit/7af768c3f8ce58994482350f7401173329950a31 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiN2FmNzY4YzNmOGNlNTg5OTQ0ODIzNTBmNzQwMTE3MzMyOTk1MGEzMSJ9 feat: Add include_recaptcha_script for as a new action in firewall policies PiperOrigin-RevId: 612851792 Source-Link: https://github.com/googleapis/googleapis/commit/49ea2c0fc42dd48996b833f05a258ad7e8590d3d Source-Link: https://github.com/googleapis/googleapis-gen/commit/460fdcbbbe00f35b1c591b1f3ef0c77ebd3ce277 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNDYwZmRjYmJiZTAwZjM1YjFjNTkxYjFmM2VmMGM3N2ViZDNjZTI3NyJ9 fix(deps): Exclude google-auth 2.24.0 and 2.25.0 chore: Update gapic-generator-python to v1.14.4 PiperOrigin-RevId: 611561820 Source-Link: https://github.com/googleapis/googleapis/commit/87ef1fe57feede1f23b523f3c7fc4c3f2b92d6d2 Source-Link: https://github.com/googleapis/googleapis-gen/commit/197316137594aafad94dea31226528fbcc39310c Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiMTk3MzE2MTM3NTk0YWFmYWQ5NGRlYTMxMjI2NTI4ZmJjYzM5MzEwYyJ9 feat: Add instance partition support to spanner instance proto PiperOrigin-RevId: 611127452 Source-Link: https://github.com/googleapis/googleapis/commit/618d47cf1e3dc4970aaec81e417039fc9d62bfdc Source-Link: https://github.com/googleapis/googleapis-gen/commit/92d855588828430e8b428ed78219e23ee666da78 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiOTJkODU1NTg4ODI4NDMwZThiNDI4ZWQ3ODIxOWUyM2VlNjY2ZGE3OCJ9 feat: Update TransactionOptions to include new option exclude_txn_from_change_streams PiperOrigin-RevId: 607807587 Source-Link: https://github.com/googleapis/googleapis/commit/d8af2d65a80fad70cb98e038be22b7f1f7197de5 Source-Link: https://github.com/googleapis/googleapis-gen/commit/601de717f1e342feada7e01f5da525465a5890d9 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNjAxZGU3MTdmMWUzNDJmZWFkYTdlMDFmNWRhNTI1NDY1YTU4OTBkOSJ9 fix(deps): Require `google-api-core>=1.34.1` fix: Resolve issue with missing import for certain enums in `**/types/…` PiperOrigin-RevId: 607041732 Source-Link: https://github.com/googleapis/googleapis/commit/b4532678459355676c95c00e39866776b7f40b2e Source-Link: https://github.com/googleapis/googleapis-gen/commit/cd796416f0f54cb22b2c44fb2d486960e693a346 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiY2Q3OTY0MTZmMGY1NGNiMjJiMmM0NGZiMmQ0ODY5NjBlNjkzYTM0NiJ9 feat(spanner): add field for multiplexed session in spanner.proto docs: update comments PiperOrigin-RevId: 607015598 Source-Link: https://github.com/googleapis/googleapis/commit/8e8a37da239bf53604509bf8153b792adad7eca3 Source-Link: https://github.com/googleapis/googleapis-gen/commit/0b517308dcc390d0b821f8a5d982cbca9e564010 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiMGI1MTczMDhkY2MzOTBkMGI4MjFmOGE1ZDk4MmNiY2E5ZTU2NDAxMCJ9 fix(diregapic): s/bazel/bazelisk/ in DIREGAPIC build GitHub action PiperOrigin-RevId: 604714585 Source-Link: https://github.com/googleapis/googleapis/commit/e4dce1324f4cb6dedb6822cb157e13cb8e0b3073 Source-Link: https://github.com/googleapis/googleapis-gen/commit/4036f78305c5c2aab80ff91960b3a3d983ff4b03 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNDAzNmY3ODMwNWM1YzJhYWI4MGZmOTE5NjBiM2EzZDk4M2ZmNGIwMyJ9 fix: Resolve AttributeError 'Credentials' object has no attribute 'universe_domain' fix: Add google-auth as a direct dependency fix: Add staticmethod decorator to methods added in v1.14.0 chore: Update gapic-generator-python to v1.14.1 PiperOrigin-RevId: 603728206 Source-Link: https://github.com/googleapis/googleapis/commit/9063da8b4d45339db4e2d7d92a27c6708620e694 Source-Link: https://github.com/googleapis/googleapis-gen/commit/891c67d0a855b08085eb301dabb14064ef4b2c6d Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiODkxYzY3ZDBhODU1YjA4MDg1ZWIzMDFkYWJiMTQwNjRlZjRiMmM2ZCJ9 feat: Allow users to explicitly configure universe domain chore: Update gapic-generator-python to v1.14.0 PiperOrigin-RevId: 603108274 Source-Link: https://github.com/googleapis/googleapis/commit/3d83e3652f689ab51c3f95f876458c6faef619bf Source-Link: https://github.com/googleapis/googleapis-gen/commit/baf5e9bbb14a768b2b4c9eae9feb78f18f1757fa Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYmFmNWU5YmJiMTRhNzY4YjJiNGM5ZWFlOWZlYjc4ZjE4ZjE3NTdmYSJ9 docs: update the comment regarding eligible SQL shapes for PartitionQuery PiperOrigin-RevId: 602806739 Source-Link: https://github.com/googleapis/googleapis/commit/20b095b497152b0f40b85b1cda3a1f74c6527063 Source-Link: https://github.com/googleapis/googleapis-gen/commit/fc8a8ea3029c590d27fcbf36ad31ef7a822f40f4 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiZmM4YThlYTMwMjljNTkwZDI3ZmNiZjM2YWQzMWVmN2E4MjJmNDBmNCJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * feat: add `RESOURCE_EXHAUSTED` to the list of retryable error codes PiperOrigin-RevId: 628281023 Source-Link: https://github.com/googleapis/googleapis/commit/60536a2a263b6d33b0b1adb5b10c10e34ccf4528 Source-Link: https://github.com/googleapis/googleapis-gen/commit/c5cfd5b956f9eadff54096c9f1c8a57ab01db294 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYzVjZmQ1Yjk1NmY5ZWFkZmY1NDA5NmM5ZjFjOGE1N2FiMDFkYjI5NCJ9 * chore: Update gapic-generator-python to v1.17.1 PiperOrigin-RevId: 629071173 Source-Link: https://github.com/googleapis/googleapis/commit/4afa392105cc62e965631d15b772ff68454ecf1c Source-Link: https://github.com/googleapis/googleapis-gen/commit/16dbbb4d0457db5e61ac9f99b0d52a46154455ac Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiMTZkYmJiNGQwNDU3ZGI1ZTYxYWM5Zjk5YjBkNTJhNDYxNTQ0NTVhYyJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix(spanner): remove mock credentials --------- Co-authored-by: Owl Bot Co-authored-by: Sri Harsha CH --- .../spanner_admin_database_v1/__init__.py | 2 +- .../services/__init__.py | 2 +- .../services/database_admin/__init__.py | 2 +- .../services/database_admin/async_client.py | 643 +- .../services/database_admin/client.py | 580 +- .../services/database_admin/pagers.py | 2 +- .../database_admin/transports/__init__.py | 2 +- .../database_admin/transports/base.py | 8 +- .../database_admin/transports/grpc.py | 29 +- .../database_admin/transports/grpc_asyncio.py | 275 +- .../database_admin/transports/rest.py | 68 +- .../types/__init__.py | 2 +- .../spanner_admin_database_v1/types/backup.py | 2 +- .../spanner_admin_database_v1/types/common.py | 2 +- .../types/spanner_database_admin.py | 2 +- .../spanner_admin_instance_v1/__init__.py | 26 +- .../gapic_metadata.json | 90 + .../services/__init__.py | 2 +- .../services/instance_admin/__init__.py | 2 +- .../services/instance_admin/async_client.py | 1314 +- .../services/instance_admin/client.py | 1379 +- .../services/instance_admin/pagers.py | 275 +- .../instance_admin/transports/__init__.py | 2 +- .../instance_admin/transports/base.py | 101 +- .../instance_admin/transports/grpc.py | 316 +- .../instance_admin/transports/grpc_asyncio.py | 483 +- .../instance_admin/transports/rest.py | 1052 +- .../types/__init__.py | 26 +- .../spanner_admin_instance_v1/types/common.py | 21 +- .../types/spanner_instance_admin.py | 640 +- google/cloud/spanner_v1/services/__init__.py | 2 +- .../spanner_v1/services/spanner/__init__.py | 2 +- .../services/spanner/async_client.py | 484 +- .../spanner_v1/services/spanner/client.py | 491 +- .../spanner_v1/services/spanner/pagers.py | 2 +- .../services/spanner/transports/__init__.py | 2 +- .../services/spanner/transports/base.py | 21 +- .../services/spanner/transports/grpc.py | 29 +- .../spanner/transports/grpc_asyncio.py | 245 +- .../services/spanner/transports/rest.py | 76 +- google/cloud/spanner_v1/types/__init__.py | 2 +- .../cloud/spanner_v1/types/commit_response.py | 2 +- google/cloud/spanner_v1/types/keys.py | 2 +- google/cloud/spanner_v1/types/mutation.py | 2 +- google/cloud/spanner_v1/types/query_plan.py | 2 +- google/cloud/spanner_v1/types/result_set.py | 2 +- google/cloud/spanner_v1/types/spanner.py | 52 +- google/cloud/spanner_v1/types/transaction.py | 25 +- google/cloud/spanner_v1/types/type.py | 2 +- ...data_google.spanner.admin.database.v1.json | 2 +- ...data_google.spanner.admin.instance.v1.json | 1268 +- .../snippet_metadata_google.spanner.v1.json | 2 +- ...erated_database_admin_copy_backup_async.py | 2 +- ...nerated_database_admin_copy_backup_sync.py | 2 +- ...ated_database_admin_create_backup_async.py | 2 +- ...rated_database_admin_create_backup_sync.py | 2 +- ...ed_database_admin_create_database_async.py | 2 +- ...ted_database_admin_create_database_sync.py | 2 +- ...ated_database_admin_delete_backup_async.py | 2 +- ...rated_database_admin_delete_backup_sync.py | 2 +- ...ated_database_admin_drop_database_async.py | 2 +- ...rated_database_admin_drop_database_sync.py | 2 +- ...nerated_database_admin_get_backup_async.py | 2 +- ...enerated_database_admin_get_backup_sync.py | 2 +- ...rated_database_admin_get_database_async.py | 2 +- ...d_database_admin_get_database_ddl_async.py | 2 +- ...ed_database_admin_get_database_ddl_sync.py | 2 +- ...erated_database_admin_get_database_sync.py | 2 +- ...ted_database_admin_get_iam_policy_async.py | 2 +- ...ated_database_admin_get_iam_policy_sync.py | 2 +- ...base_admin_list_backup_operations_async.py | 2 +- ...abase_admin_list_backup_operations_sync.py | 2 +- ...rated_database_admin_list_backups_async.py | 2 +- ...erated_database_admin_list_backups_sync.py | 2 +- ...se_admin_list_database_operations_async.py | 2 +- ...ase_admin_list_database_operations_sync.py | 2 +- ...atabase_admin_list_database_roles_async.py | 2 +- ...database_admin_list_database_roles_sync.py | 2 +- ...ted_database_admin_list_databases_async.py | 2 +- ...ated_database_admin_list_databases_sync.py | 2 +- ...d_database_admin_restore_database_async.py | 2 +- ...ed_database_admin_restore_database_sync.py | 2 +- ...ted_database_admin_set_iam_policy_async.py | 2 +- ...ated_database_admin_set_iam_policy_sync.py | 2 +- ...tabase_admin_test_iam_permissions_async.py | 2 +- ...atabase_admin_test_iam_permissions_sync.py | 2 +- ...ated_database_admin_update_backup_async.py | 2 +- ...rated_database_admin_update_backup_sync.py | 2 +- ...ed_database_admin_update_database_async.py | 2 +- ...atabase_admin_update_database_ddl_async.py | 2 +- ...database_admin_update_database_ddl_sync.py | 2 +- ...ted_database_admin_update_database_sync.py | 2 +- ...ed_instance_admin_create_instance_async.py | 2 +- ...ance_admin_create_instance_config_async.py | 2 +- ...tance_admin_create_instance_config_sync.py | 2 +- ...e_admin_create_instance_partition_async.py | 64 + ...ce_admin_create_instance_partition_sync.py | 64 + ...ted_instance_admin_create_instance_sync.py | 2 +- ...ed_instance_admin_delete_instance_async.py | 2 +- ...ance_admin_delete_instance_config_async.py | 2 +- ...tance_admin_delete_instance_config_sync.py | 2 +- ...e_admin_delete_instance_partition_async.py | 50 + ...ce_admin_delete_instance_partition_sync.py | 50 + ...ted_instance_admin_delete_instance_sync.py | 2 +- ...ted_instance_admin_get_iam_policy_async.py | 2 +- ...ated_instance_admin_get_iam_policy_sync.py | 2 +- ...rated_instance_admin_get_instance_async.py | 2 +- ...nstance_admin_get_instance_config_async.py | 2 +- ...instance_admin_get_instance_config_sync.py | 2 +- ...ance_admin_get_instance_partition_async.py | 52 + ...tance_admin_get_instance_partition_sync.py | 52 + ...erated_instance_admin_get_instance_sync.py | 2 +- ...n_list_instance_config_operations_async.py | 2 +- ...in_list_instance_config_operations_sync.py | 2 +- ...tance_admin_list_instance_configs_async.py | 2 +- ...stance_admin_list_instance_configs_sync.py | 2 +- ...ist_instance_partition_operations_async.py | 53 + ...list_instance_partition_operations_sync.py | 53 + ...ce_admin_list_instance_partitions_async.py | 53 + ...nce_admin_list_instance_partitions_sync.py | 53 + ...ted_instance_admin_list_instances_async.py | 2 +- ...ated_instance_admin_list_instances_sync.py | 2 +- ...ted_instance_admin_set_iam_policy_async.py | 2 +- ...ated_instance_admin_set_iam_policy_sync.py | 2 +- ...stance_admin_test_iam_permissions_async.py | 2 +- ...nstance_admin_test_iam_permissions_sync.py | 2 +- ...ed_instance_admin_update_instance_async.py | 2 +- ...ance_admin_update_instance_config_async.py | 2 +- ...tance_admin_update_instance_config_sync.py | 2 +- ...e_admin_update_instance_partition_async.py | 62 + ...ce_admin_update_instance_partition_sync.py | 62 + ...ted_instance_admin_update_instance_sync.py | 2 +- ...ted_spanner_batch_create_sessions_async.py | 2 +- ...ated_spanner_batch_create_sessions_sync.py | 2 +- ..._v1_generated_spanner_batch_write_async.py | 2 +- ...r_v1_generated_spanner_batch_write_sync.py | 2 +- ...nerated_spanner_begin_transaction_async.py | 2 +- ...enerated_spanner_begin_transaction_sync.py | 2 +- ...anner_v1_generated_spanner_commit_async.py | 2 +- ...panner_v1_generated_spanner_commit_sync.py | 2 +- ..._generated_spanner_create_session_async.py | 2 +- ...1_generated_spanner_create_session_sync.py | 2 +- ..._generated_spanner_delete_session_async.py | 2 +- ...1_generated_spanner_delete_session_sync.py | 2 +- ...nerated_spanner_execute_batch_dml_async.py | 2 +- ...enerated_spanner_execute_batch_dml_sync.py | 2 +- ..._v1_generated_spanner_execute_sql_async.py | 2 +- ...r_v1_generated_spanner_execute_sql_sync.py | 2 +- ...ted_spanner_execute_streaming_sql_async.py | 2 +- ...ated_spanner_execute_streaming_sql_sync.py | 2 +- ..._v1_generated_spanner_get_session_async.py | 2 +- ...r_v1_generated_spanner_get_session_sync.py | 2 +- ...1_generated_spanner_list_sessions_async.py | 2 +- ...v1_generated_spanner_list_sessions_sync.py | 2 +- ...generated_spanner_partition_query_async.py | 2 +- ..._generated_spanner_partition_query_sync.py | 2 +- ..._generated_spanner_partition_read_async.py | 2 +- ...1_generated_spanner_partition_read_sync.py | 2 +- ...spanner_v1_generated_spanner_read_async.py | 2 +- .../spanner_v1_generated_spanner_read_sync.py | 2 +- ...ner_v1_generated_spanner_rollback_async.py | 2 +- ...nner_v1_generated_spanner_rollback_sync.py | 2 +- ..._generated_spanner_streaming_read_async.py | 2 +- ...1_generated_spanner_streaming_read_sync.py | 2 +- ...ixup_spanner_admin_database_v1_keywords.py | 2 +- ...ixup_spanner_admin_instance_v1_keywords.py | 10 +- scripts/fixup_spanner_v1_keywords.py | 4 +- tests/__init__.py | 2 +- tests/unit/__init__.py | 2 +- tests/unit/gapic/__init__.py | 2 +- .../spanner_admin_database_v1/__init__.py | 2 +- .../test_database_admin.py | 4414 +++++- .../spanner_admin_instance_v1/__init__.py | 2 +- .../test_instance_admin.py | 11947 +++++++++++++--- tests/unit/gapic/spanner_v1/__init__.py | 2 +- tests/unit/gapic/spanner_v1/test_spanner.py | 3556 ++++- tests/unit/test_client.py | 8 +- tests/unit/test_instance.py | 16 +- 178 files changed, 26659 insertions(+), 4245 deletions(-) create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_partition_async.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_partition_sync.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_partition_async.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_partition_sync.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_partition_async.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_partition_sync.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partition_operations_async.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partition_operations_sync.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partitions_async.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partitions_sync.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_partition_async.py create mode 100644 samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_partition_sync.py diff --git a/google/cloud/spanner_admin_database_v1/__init__.py b/google/cloud/spanner_admin_database_v1/__init__.py index 8de76679e0..a14af051d6 100644 --- a/google/cloud/spanner_admin_database_v1/__init__.py +++ b/google/cloud/spanner_admin_database_v1/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_database_v1/services/__init__.py b/google/cloud/spanner_admin_database_v1/services/__init__.py index 89a37dc92c..8f6cf06824 100644 --- a/google/cloud/spanner_admin_database_v1/services/__init__.py +++ b/google/cloud/spanner_admin_database_v1/services/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py b/google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py index 9b1870398c..cae7306643 100644 --- a/google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py +++ b/google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py b/google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py index c0f9389db8..bd0fbc5532 100644 --- a/google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py +++ b/google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ import re from typing import ( Dict, + Callable, Mapping, MutableMapping, MutableSequence, @@ -38,9 +39,9 @@ from google.oauth2 import service_account # type: ignore try: - OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault] + OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None] except AttributeError: # pragma: NO COVER - OptionalRetry = Union[retries.AsyncRetry, object] # type: ignore + OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore @@ -74,8 +75,12 @@ class DatabaseAdminAsyncClient: _client: DatabaseAdminClient + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. DEFAULT_ENDPOINT = DatabaseAdminClient.DEFAULT_ENDPOINT DEFAULT_MTLS_ENDPOINT = DatabaseAdminClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = DatabaseAdminClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = DatabaseAdminClient._DEFAULT_UNIVERSE backup_path = staticmethod(DatabaseAdminClient.backup_path) parse_backup_path = staticmethod(DatabaseAdminClient.parse_backup_path) @@ -196,6 +201,25 @@ def transport(self) -> DatabaseAdminTransport: """ return self._client.transport + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + get_transport_class = functools.partial( type(DatabaseAdminClient).get_transport_class, type(DatabaseAdminClient) ) @@ -204,11 +228,13 @@ def __init__( self, *, credentials: Optional[ga_credentials.Credentials] = None, - transport: Union[str, DatabaseAdminTransport] = "grpc_asyncio", + transport: Optional[ + Union[str, DatabaseAdminTransport, Callable[..., DatabaseAdminTransport]] + ] = "grpc_asyncio", client_options: Optional[ClientOptions] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiates the database admin client. + """Instantiates the database admin async client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -216,26 +242,43 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.DatabaseAdminTransport]): The - transport to use. If set to None, a transport is chosen - automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. - (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT - environment variable can also be used to override the endpoint: + transport (Optional[Union[str,DatabaseAdminTransport,Callable[..., DatabaseAdminTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the DatabaseAdminTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint) and "auto" (auto switch to the - default mTLS endpoint if client certificate is present, this is - the default value). However, the ``api_endpoint`` property takes - precedence if provided. - (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable is "true", then the ``client_cert_source`` property can be used - to provide client certificate for mutual TLS transport. If + to provide a client certificate for mTLS transport. If not provided, the default SSL client certificate will be used if present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not set, no client certificate will be used. + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport creation failed for any reason. @@ -315,8 +358,8 @@ async def sample_list_databases(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -324,7 +367,10 @@ async def sample_list_databases(): "the individual field arguments should be set." ) - request = spanner_database_admin.ListDatabasesRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_database_admin.ListDatabasesRequest): + request = spanner_database_admin.ListDatabasesRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -333,21 +379,9 @@ async def sample_list_databases(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.list_databases, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_databases + ] # Certain fields should be provided within the metadata header; # add these here. @@ -355,6 +389,9 @@ async def sample_list_databases(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -469,8 +506,8 @@ async def sample_create_database(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, create_statement]) if request is not None and has_flattened_params: raise ValueError( @@ -478,7 +515,10 @@ async def sample_create_database(): "the individual field arguments should be set." ) - request = spanner_database_admin.CreateDatabaseRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_database_admin.CreateDatabaseRequest): + request = spanner_database_admin.CreateDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -489,11 +529,9 @@ async def sample_create_database(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.create_database, - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_database + ] # Certain fields should be provided within the metadata header; # add these here. @@ -501,6 +539,9 @@ async def sample_create_database(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -582,8 +623,8 @@ async def sample_get_database(): A Cloud Spanner database. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -591,7 +632,10 @@ async def sample_get_database(): "the individual field arguments should be set." ) - request = spanner_database_admin.GetDatabaseRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_database_admin.GetDatabaseRequest): + request = spanner_database_admin.GetDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -600,21 +644,9 @@ async def sample_get_database(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.get_database, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_database + ] # Certain fields should be provided within the metadata header; # add these here. @@ -622,6 +654,9 @@ async def sample_get_database(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -752,8 +787,8 @@ async def sample_update_database(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database, update_mask]) if request is not None and has_flattened_params: raise ValueError( @@ -761,7 +796,10 @@ async def sample_update_database(): "the individual field arguments should be set." ) - request = spanner_database_admin.UpdateDatabaseRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_database_admin.UpdateDatabaseRequest): + request = spanner_database_admin.UpdateDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -772,21 +810,9 @@ async def sample_update_database(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.update_database, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_database + ] # Certain fields should be provided within the metadata header; # add these here. @@ -796,6 +822,9 @@ async def sample_update_database(): ), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -924,8 +953,8 @@ async def sample_update_database_ddl(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database, statements]) if request is not None and has_flattened_params: raise ValueError( @@ -933,7 +962,10 @@ async def sample_update_database_ddl(): "the individual field arguments should be set." ) - request = spanner_database_admin.UpdateDatabaseDdlRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_database_admin.UpdateDatabaseDdlRequest): + request = spanner_database_admin.UpdateDatabaseDdlRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -944,21 +976,9 @@ async def sample_update_database_ddl(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.update_database_ddl, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_database_ddl + ] # Certain fields should be provided within the metadata header; # add these here. @@ -966,6 +986,9 @@ async def sample_update_database_ddl(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1040,8 +1063,8 @@ async def sample_drop_database(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database]) if request is not None and has_flattened_params: raise ValueError( @@ -1049,7 +1072,10 @@ async def sample_drop_database(): "the individual field arguments should be set." ) - request = spanner_database_admin.DropDatabaseRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_database_admin.DropDatabaseRequest): + request = spanner_database_admin.DropDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1058,21 +1084,9 @@ async def sample_drop_database(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.drop_database, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.drop_database + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1080,6 +1094,9 @@ async def sample_drop_database(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. await rpc( request, @@ -1155,8 +1172,8 @@ async def sample_get_database_ddl(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database]) if request is not None and has_flattened_params: raise ValueError( @@ -1164,7 +1181,10 @@ async def sample_get_database_ddl(): "the individual field arguments should be set." ) - request = spanner_database_admin.GetDatabaseDdlRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_database_admin.GetDatabaseDdlRequest): + request = spanner_database_admin.GetDatabaseDdlRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1173,21 +1193,9 @@ async def sample_get_database_ddl(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.get_database_ddl, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_database_ddl + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1195,6 +1203,9 @@ async def sample_get_database_ddl(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1305,8 +1316,8 @@ async def sample_set_iam_policy(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource]) if request is not None and has_flattened_params: raise ValueError( @@ -1314,22 +1325,18 @@ async def sample_set_iam_policy(): "the individual field arguments should be set." ) - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. if isinstance(request, dict): request = iam_policy_pb2.SetIamPolicyRequest(**request) elif not request: - request = iam_policy_pb2.SetIamPolicyRequest( - resource=resource, - ) + request = iam_policy_pb2.SetIamPolicyRequest(resource=resource) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.set_iam_policy, - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.set_iam_policy + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1337,6 +1344,9 @@ async def sample_set_iam_policy(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1448,8 +1458,8 @@ async def sample_get_iam_policy(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource]) if request is not None and has_flattened_params: raise ValueError( @@ -1457,32 +1467,18 @@ async def sample_get_iam_policy(): "the individual field arguments should be set." ) - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. if isinstance(request, dict): request = iam_policy_pb2.GetIamPolicyRequest(**request) elif not request: - request = iam_policy_pb2.GetIamPolicyRequest( - resource=resource, - ) + request = iam_policy_pb2.GetIamPolicyRequest(resource=resource) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.get_iam_policy, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_iam_policy + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1490,6 +1486,9 @@ async def sample_get_iam_policy(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1582,8 +1581,8 @@ async def sample_test_iam_permissions(): Response message for TestIamPermissions method. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource, permissions]) if request is not None and has_flattened_params: raise ValueError( @@ -1591,23 +1590,20 @@ async def sample_test_iam_permissions(): "the individual field arguments should be set." ) - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. if isinstance(request, dict): request = iam_policy_pb2.TestIamPermissionsRequest(**request) elif not request: request = iam_policy_pb2.TestIamPermissionsRequest( - resource=resource, - permissions=permissions, + resource=resource, permissions=permissions ) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.test_iam_permissions, - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.test_iam_permissions + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1615,6 +1611,9 @@ async def sample_test_iam_permissions(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1728,8 +1727,8 @@ async def sample_create_backup(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, backup, backup_id]) if request is not None and has_flattened_params: raise ValueError( @@ -1737,7 +1736,10 @@ async def sample_create_backup(): "the individual field arguments should be set." ) - request = gsad_backup.CreateBackupRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, gsad_backup.CreateBackupRequest): + request = gsad_backup.CreateBackupRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1750,11 +1752,9 @@ async def sample_create_backup(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.create_backup, - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_backup + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1762,6 +1762,9 @@ async def sample_create_backup(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1899,8 +1902,8 @@ async def sample_copy_backup(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, backup_id, source_backup, expire_time]) if request is not None and has_flattened_params: raise ValueError( @@ -1908,7 +1911,10 @@ async def sample_copy_backup(): "the individual field arguments should be set." ) - request = backup.CopyBackupRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, backup.CopyBackupRequest): + request = backup.CopyBackupRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1923,11 +1929,9 @@ async def sample_copy_backup(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.copy_backup, - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.copy_backup + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1935,6 +1939,9 @@ async def sample_copy_backup(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2014,8 +2021,8 @@ async def sample_get_backup(): A backup of a Cloud Spanner database. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -2023,7 +2030,10 @@ async def sample_get_backup(): "the individual field arguments should be set." ) - request = backup.GetBackupRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, backup.GetBackupRequest): + request = backup.GetBackupRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -2032,21 +2042,9 @@ async def sample_get_backup(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.get_backup, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_backup + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2054,6 +2052,9 @@ async def sample_get_backup(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2141,8 +2142,8 @@ async def sample_update_backup(): A backup of a Cloud Spanner database. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([backup, update_mask]) if request is not None and has_flattened_params: raise ValueError( @@ -2150,7 +2151,10 @@ async def sample_update_backup(): "the individual field arguments should be set." ) - request = gsad_backup.UpdateBackupRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, gsad_backup.UpdateBackupRequest): + request = gsad_backup.UpdateBackupRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -2161,21 +2165,9 @@ async def sample_update_backup(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.update_backup, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_backup + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2185,6 +2177,9 @@ async def sample_update_backup(): ), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2250,8 +2245,8 @@ async def sample_delete_backup(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -2259,7 +2254,10 @@ async def sample_delete_backup(): "the individual field arguments should be set." ) - request = backup.DeleteBackupRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, backup.DeleteBackupRequest): + request = backup.DeleteBackupRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -2268,21 +2266,9 @@ async def sample_delete_backup(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.delete_backup, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.delete_backup + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2290,6 +2276,9 @@ async def sample_delete_backup(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. await rpc( request, @@ -2365,8 +2354,8 @@ async def sample_list_backups(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -2374,7 +2363,10 @@ async def sample_list_backups(): "the individual field arguments should be set." ) - request = backup.ListBackupsRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, backup.ListBackupsRequest): + request = backup.ListBackupsRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -2383,21 +2375,9 @@ async def sample_list_backups(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.list_backups, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_backups + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2405,6 +2385,9 @@ async def sample_list_backups(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2538,8 +2521,8 @@ async def sample_restore_database(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, database_id, backup]) if request is not None and has_flattened_params: raise ValueError( @@ -2547,7 +2530,10 @@ async def sample_restore_database(): "the individual field arguments should be set." ) - request = spanner_database_admin.RestoreDatabaseRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_database_admin.RestoreDatabaseRequest): + request = spanner_database_admin.RestoreDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -2560,11 +2546,9 @@ async def sample_restore_database(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.restore_database, - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.restore_database + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2572,6 +2556,9 @@ async def sample_restore_database(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2668,8 +2655,8 @@ async def sample_list_database_operations(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -2677,7 +2664,12 @@ async def sample_list_database_operations(): "the individual field arguments should be set." ) - request = spanner_database_admin.ListDatabaseOperationsRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_database_admin.ListDatabaseOperationsRequest + ): + request = spanner_database_admin.ListDatabaseOperationsRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -2686,21 +2678,9 @@ async def sample_list_database_operations(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.list_database_operations, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_database_operations + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2708,6 +2688,9 @@ async def sample_list_database_operations(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2805,8 +2788,8 @@ async def sample_list_backup_operations(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -2814,7 +2797,10 @@ async def sample_list_backup_operations(): "the individual field arguments should be set." ) - request = backup.ListBackupOperationsRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, backup.ListBackupOperationsRequest): + request = backup.ListBackupOperationsRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -2823,21 +2809,9 @@ async def sample_list_backup_operations(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.list_backup_operations, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_backup_operations + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2845,6 +2819,9 @@ async def sample_list_backup_operations(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2933,8 +2910,8 @@ async def sample_list_database_roles(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -2942,7 +2919,10 @@ async def sample_list_database_roles(): "the individual field arguments should be set." ) - request = spanner_database_admin.ListDatabaseRolesRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_database_admin.ListDatabaseRolesRequest): + request = spanner_database_admin.ListDatabaseRolesRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -2951,21 +2931,9 @@ async def sample_list_database_roles(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.list_database_roles, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_database_roles + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2973,6 +2941,9 @@ async def sample_list_database_roles(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -3036,6 +3007,9 @@ async def list_operations( gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -3090,6 +3064,9 @@ async def get_operation( gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -3148,6 +3125,9 @@ async def delete_operation( gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. await rpc( request, @@ -3202,6 +3182,9 @@ async def cancel_operation( gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. await rpc( request, diff --git a/google/cloud/spanner_admin_database_v1/services/database_admin/client.py b/google/cloud/spanner_admin_database_v1/services/database_admin/client.py index 39904ec05f..09cc03f548 100644 --- a/google/cloud/spanner_admin_database_v1/services/database_admin/client.py +++ b/google/cloud/spanner_admin_database_v1/services/database_admin/client.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ import re from typing import ( Dict, + Callable, Mapping, MutableMapping, MutableSequence, @@ -28,6 +29,7 @@ Union, cast, ) +import warnings from google.cloud.spanner_admin_database_v1 import gapic_version as package_version @@ -42,9 +44,9 @@ from google.oauth2 import service_account # type: ignore try: - OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] except AttributeError: # pragma: NO COVER - OptionalRetry = Union[retries.Retry, object] # type: ignore + OptionalRetry = Union[retries.Retry, object, None] # type: ignore from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore @@ -142,11 +144,15 @@ def _get_default_mtls_endpoint(api_endpoint): return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. DEFAULT_ENDPOINT = "spanner.googleapis.com" DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore DEFAULT_ENDPOINT ) + _DEFAULT_ENDPOINT_TEMPLATE = "spanner.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): """Creates an instance of this client using the provided credentials @@ -410,7 +416,7 @@ def parse_common_location_path(path: str) -> Dict[str, str]: def get_mtls_endpoint_and_cert_source( cls, client_options: Optional[client_options_lib.ClientOptions] = None ): - """Return the API endpoint and client cert source for mutual TLS. + """Deprecated. Return the API endpoint and client cert source for mutual TLS. The client cert source is determined in the following order: (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the @@ -440,6 +446,11 @@ def get_mtls_endpoint_and_cert_source( Raises: google.auth.exceptions.MutualTLSChannelError: If any errors happen. """ + + warnings.warn( + "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", + DeprecationWarning, + ) if client_options is None: client_options = client_options_lib.ClientOptions() use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") @@ -473,11 +484,185 @@ def get_mtls_endpoint_and_cert_source( return api_endpoint, client_cert_source + @staticmethod + def _read_environment_variables(): + """Returns the environment variables used by the client. + + Returns: + Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, + GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. + + Raises: + ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not + any of ["true", "false"]. + google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT + is not any of ["auto", "never", "always"]. + """ + use_client_cert = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + return use_client_cert == "true", use_mtls_endpoint, universe_domain_env + + @staticmethod + def _get_client_cert_source(provided_cert_source, use_cert_flag): + """Return the client cert source to be used by the client. + + Args: + provided_cert_source (bytes): The client certificate source provided. + use_cert_flag (bool): A flag indicating whether to use the client certificate. + + Returns: + bytes or None: The client cert source to be used by the client. + """ + client_cert_source = None + if use_cert_flag: + if provided_cert_source: + client_cert_source = provided_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + return client_cert_source + + @staticmethod + def _get_api_endpoint( + api_override, client_cert_source, universe_domain, use_mtls_endpoint + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = DatabaseAdminClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = DatabaseAdminClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = DatabaseAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], universe_domain_env: Optional[str] + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = DatabaseAdminClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + @staticmethod + def _compare_universes( + client_universe: str, credentials: ga_credentials.Credentials + ) -> bool: + """Returns True iff the universe domains used by the client and credentials match. + + Args: + client_universe (str): The universe domain configured via the client options. + credentials (ga_credentials.Credentials): The credentials being used in the client. + + Returns: + bool: True iff client_universe matches the universe in credentials. + + Raises: + ValueError: when client_universe does not match the universe in credentials. + """ + + default_universe = DatabaseAdminClient._DEFAULT_UNIVERSE + credentials_universe = getattr(credentials, "universe_domain", default_universe) + + if client_universe != credentials_universe: + raise ValueError( + "The configured universe domain " + f"({client_universe}) does not match the universe domain " + f"found in the credentials ({credentials_universe}). " + "If you haven't configured the universe domain explicitly, " + f"`{default_universe}` is the default." + ) + return True + + def _validate_universe_domain(self): + """Validates client's and credentials' universe domains are consistent. + + Returns: + bool: True iff the configured universe domain is valid. + + Raises: + ValueError: If the configured universe domain is not valid. + """ + self._is_universe_domain_valid = ( + self._is_universe_domain_valid + or DatabaseAdminClient._compare_universes( + self.universe_domain, self.transport._credentials + ) + ) + return self._is_universe_domain_valid + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + def __init__( self, *, credentials: Optional[ga_credentials.Credentials] = None, - transport: Optional[Union[str, DatabaseAdminTransport]] = None, + transport: Optional[ + Union[str, DatabaseAdminTransport, Callable[..., DatabaseAdminTransport]] + ] = None, client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -489,25 +674,37 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, DatabaseAdminTransport]): The - transport to use. If set to None, a transport is chosen - automatically. - client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the - client. It won't take effect if a ``transport`` instance is provided. - (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT - environment variable can also be used to override the endpoint: + transport (Optional[Union[str,DatabaseAdminTransport,Callable[..., DatabaseAdminTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the DatabaseAdminTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint) and "auto" (auto switch to the - default mTLS endpoint if client certificate is present, this is - the default value). However, the ``api_endpoint`` property takes - precedence if provided. - (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable is "true", then the ``client_cert_source`` property can be used - to provide client certificate for mutual TLS transport. If + to provide a client certificate for mTLS transport. If not provided, the default SSL client certificate will be used if present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): The client info used to send a user-agent string along with API requests. If ``None``, then default info will be used. @@ -518,17 +715,34 @@ def __init__( google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ - if isinstance(client_options, dict): - client_options = client_options_lib.from_dict(client_options) - if client_options is None: - client_options = client_options_lib.ClientOptions() - client_options = cast(client_options_lib.ClientOptions, client_options) + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr(self._client_options, "universe_domain", None) - api_endpoint, client_cert_source_func = self.get_mtls_endpoint_and_cert_source( - client_options + ( + self._use_client_cert, + self._use_mtls_endpoint, + self._universe_domain_env, + ) = DatabaseAdminClient._read_environment_variables() + self._client_cert_source = DatabaseAdminClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = DatabaseAdminClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env ) + self._api_endpoint = None # updated below, depending on `transport` - api_key_value = getattr(client_options, "api_key", None) + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + api_key_value = getattr(self._client_options, "api_key", None) if api_key_value and credentials: raise ValueError( "client_options.api_key and credentials are mutually exclusive" @@ -537,20 +751,33 @@ def __init__( # Save or instantiate the transport. # Ordinarily, we provide the transport, but allowing a custom transport # instance provides an extensibility point for unusual situations. - if isinstance(transport, DatabaseAdminTransport): + transport_provided = isinstance(transport, DatabaseAdminTransport) + if transport_provided: # transport is a DatabaseAdminTransport instance. - if credentials or client_options.credentials_file or api_key_value: + if credentials or self._client_options.credentials_file or api_key_value: raise ValueError( "When providing a transport instance, " "provide its credentials directly." ) - if client_options.scopes: + if self._client_options.scopes: raise ValueError( "When providing a transport instance, provide its scopes " "directly." ) - self._transport = transport - else: + self._transport = cast(DatabaseAdminTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or DatabaseAdminClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: import google.auth._default # type: ignore if api_key_value and hasattr( @@ -560,17 +787,24 @@ def __init__( api_key_value ) - Transport = type(self).get_transport_class(transport) - self._transport = Transport( + transport_init: Union[ + Type[DatabaseAdminTransport], Callable[..., DatabaseAdminTransport] + ] = ( + type(self).get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., DatabaseAdminTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( credentials=credentials, - credentials_file=client_options.credentials_file, - host=api_endpoint, - scopes=client_options.scopes, - client_cert_source_for_mtls=client_cert_source_func, - quota_project_id=client_options.quota_project_id, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, client_info=client_info, always_use_jwt_access=True, - api_audience=client_options.api_audience, + api_audience=self._client_options.api_audience, ) def list_databases( @@ -641,8 +875,8 @@ def sample_list_databases(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -650,10 +884,8 @@ def sample_list_databases(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.ListDatabasesRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_database_admin.ListDatabasesRequest): request = spanner_database_admin.ListDatabasesRequest(request) # If we have keyword arguments corresponding to fields on the @@ -671,6 +903,9 @@ def sample_list_databases(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -785,8 +1020,8 @@ def sample_create_database(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, create_statement]) if request is not None and has_flattened_params: raise ValueError( @@ -794,10 +1029,8 @@ def sample_create_database(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.CreateDatabaseRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_database_admin.CreateDatabaseRequest): request = spanner_database_admin.CreateDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the @@ -817,6 +1050,9 @@ def sample_create_database(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -898,8 +1134,8 @@ def sample_get_database(): A Cloud Spanner database. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -907,10 +1143,8 @@ def sample_get_database(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.GetDatabaseRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_database_admin.GetDatabaseRequest): request = spanner_database_admin.GetDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the @@ -928,6 +1162,9 @@ def sample_get_database(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1058,8 +1295,8 @@ def sample_update_database(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database, update_mask]) if request is not None and has_flattened_params: raise ValueError( @@ -1067,10 +1304,8 @@ def sample_update_database(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.UpdateDatabaseRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_database_admin.UpdateDatabaseRequest): request = spanner_database_admin.UpdateDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1092,6 +1327,9 @@ def sample_update_database(): ), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1220,8 +1458,8 @@ def sample_update_database_ddl(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database, statements]) if request is not None and has_flattened_params: raise ValueError( @@ -1229,10 +1467,8 @@ def sample_update_database_ddl(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.UpdateDatabaseDdlRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_database_admin.UpdateDatabaseDdlRequest): request = spanner_database_admin.UpdateDatabaseDdlRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1252,6 +1488,9 @@ def sample_update_database_ddl(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1326,8 +1565,8 @@ def sample_drop_database(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database]) if request is not None and has_flattened_params: raise ValueError( @@ -1335,10 +1574,8 @@ def sample_drop_database(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.DropDatabaseRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_database_admin.DropDatabaseRequest): request = spanner_database_admin.DropDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1356,6 +1593,9 @@ def sample_drop_database(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. rpc( request, @@ -1431,8 +1671,8 @@ def sample_get_database_ddl(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database]) if request is not None and has_flattened_params: raise ValueError( @@ -1440,10 +1680,8 @@ def sample_get_database_ddl(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.GetDatabaseDdlRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_database_admin.GetDatabaseDdlRequest): request = spanner_database_admin.GetDatabaseDdlRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1461,6 +1699,9 @@ def sample_get_database_ddl(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1571,8 +1812,8 @@ def sample_set_iam_policy(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource]) if request is not None and has_flattened_params: raise ValueError( @@ -1581,8 +1822,8 @@ def sample_set_iam_policy(): ) if isinstance(request, dict): - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. request = iam_policy_pb2.SetIamPolicyRequest(**request) elif not request: # Null request, just make one. @@ -1600,6 +1841,9 @@ def sample_set_iam_policy(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1711,8 +1955,8 @@ def sample_get_iam_policy(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource]) if request is not None and has_flattened_params: raise ValueError( @@ -1721,8 +1965,8 @@ def sample_get_iam_policy(): ) if isinstance(request, dict): - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. request = iam_policy_pb2.GetIamPolicyRequest(**request) elif not request: # Null request, just make one. @@ -1740,6 +1984,9 @@ def sample_get_iam_policy(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1832,8 +2079,8 @@ def sample_test_iam_permissions(): Response message for TestIamPermissions method. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource, permissions]) if request is not None and has_flattened_params: raise ValueError( @@ -1842,8 +2089,8 @@ def sample_test_iam_permissions(): ) if isinstance(request, dict): - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. request = iam_policy_pb2.TestIamPermissionsRequest(**request) elif not request: # Null request, just make one. @@ -1863,6 +2110,9 @@ def sample_test_iam_permissions(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1976,8 +2226,8 @@ def sample_create_backup(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, backup, backup_id]) if request is not None and has_flattened_params: raise ValueError( @@ -1985,10 +2235,8 @@ def sample_create_backup(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a gsad_backup.CreateBackupRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, gsad_backup.CreateBackupRequest): request = gsad_backup.CreateBackupRequest(request) # If we have keyword arguments corresponding to fields on the @@ -2010,6 +2258,9 @@ def sample_create_backup(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2147,8 +2398,8 @@ def sample_copy_backup(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, backup_id, source_backup, expire_time]) if request is not None and has_flattened_params: raise ValueError( @@ -2156,10 +2407,8 @@ def sample_copy_backup(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a backup.CopyBackupRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, backup.CopyBackupRequest): request = backup.CopyBackupRequest(request) # If we have keyword arguments corresponding to fields on the @@ -2183,6 +2432,9 @@ def sample_copy_backup(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2262,8 +2514,8 @@ def sample_get_backup(): A backup of a Cloud Spanner database. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -2271,10 +2523,8 @@ def sample_get_backup(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a backup.GetBackupRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, backup.GetBackupRequest): request = backup.GetBackupRequest(request) # If we have keyword arguments corresponding to fields on the @@ -2292,6 +2542,9 @@ def sample_get_backup(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2379,8 +2632,8 @@ def sample_update_backup(): A backup of a Cloud Spanner database. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([backup, update_mask]) if request is not None and has_flattened_params: raise ValueError( @@ -2388,10 +2641,8 @@ def sample_update_backup(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a gsad_backup.UpdateBackupRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, gsad_backup.UpdateBackupRequest): request = gsad_backup.UpdateBackupRequest(request) # If we have keyword arguments corresponding to fields on the @@ -2413,6 +2664,9 @@ def sample_update_backup(): ), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2478,8 +2732,8 @@ def sample_delete_backup(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -2487,10 +2741,8 @@ def sample_delete_backup(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a backup.DeleteBackupRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, backup.DeleteBackupRequest): request = backup.DeleteBackupRequest(request) # If we have keyword arguments corresponding to fields on the @@ -2508,6 +2760,9 @@ def sample_delete_backup(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. rpc( request, @@ -2583,8 +2838,8 @@ def sample_list_backups(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -2592,10 +2847,8 @@ def sample_list_backups(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a backup.ListBackupsRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, backup.ListBackupsRequest): request = backup.ListBackupsRequest(request) # If we have keyword arguments corresponding to fields on the @@ -2613,6 +2866,9 @@ def sample_list_backups(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2746,8 +3002,8 @@ def sample_restore_database(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, database_id, backup]) if request is not None and has_flattened_params: raise ValueError( @@ -2755,10 +3011,8 @@ def sample_restore_database(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.RestoreDatabaseRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_database_admin.RestoreDatabaseRequest): request = spanner_database_admin.RestoreDatabaseRequest(request) # If we have keyword arguments corresponding to fields on the @@ -2780,6 +3034,9 @@ def sample_restore_database(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2876,8 +3133,8 @@ def sample_list_database_operations(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -2885,10 +3142,8 @@ def sample_list_database_operations(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.ListDatabaseOperationsRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance( request, spanner_database_admin.ListDatabaseOperationsRequest ): @@ -2908,6 +3163,9 @@ def sample_list_database_operations(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -3005,8 +3263,8 @@ def sample_list_backup_operations(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -3014,10 +3272,8 @@ def sample_list_backup_operations(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a backup.ListBackupOperationsRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, backup.ListBackupOperationsRequest): request = backup.ListBackupOperationsRequest(request) # If we have keyword arguments corresponding to fields on the @@ -3035,6 +3291,9 @@ def sample_list_backup_operations(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -3123,8 +3382,8 @@ def sample_list_database_roles(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -3132,10 +3391,8 @@ def sample_list_database_roles(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_database_admin.ListDatabaseRolesRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_database_admin.ListDatabaseRolesRequest): request = spanner_database_admin.ListDatabaseRolesRequest(request) # If we have keyword arguments corresponding to fields on the @@ -3153,6 +3410,9 @@ def sample_list_database_roles(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -3229,6 +3489,9 @@ def list_operations( gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -3283,6 +3546,9 @@ def get_operation( gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -3341,6 +3607,9 @@ def delete_operation( gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. rpc( request, @@ -3395,6 +3664,9 @@ def cancel_operation( gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. rpc( request, diff --git a/google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py b/google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py index 70dc04a79f..3efd19e231 100644 --- a/google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py +++ b/google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/__init__.py b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/__init__.py index 3c6b040e23..a20c366a95 100644 --- a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/__init__.py +++ b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/base.py b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/base.py index 2d2b2b5ad9..65c68857cf 100644 --- a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/base.py +++ b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/base.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -67,7 +67,7 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -130,6 +130,10 @@ def __init__( host += ":443" self._host = host + @property + def host(self): + return self._host + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py index d518b455fa..854b5ae85a 100644 --- a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py +++ b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -64,7 +64,7 @@ def __init__( credentials: Optional[ga_credentials.Credentials] = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, - channel: Optional[grpc.Channel] = None, + channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None, api_mtls_endpoint: Optional[str] = None, client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, @@ -78,20 +78,23 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. scopes (Optional(Sequence[str])): A list of scopes. This argument is - ignored if ``channel`` is provided. - channel (Optional[grpc.Channel]): A ``Channel`` instance through - which to make calls. + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from @@ -101,11 +104,11 @@ def __init__( private key bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials - for the grpc channel. It is ignored if ``channel`` is provided. + for the grpc channel. It is ignored if a ``channel`` instance is provided. client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): A callback to provide client certificate bytes and private key bytes, both in PEM format. It is used to configure a mutual TLS channel. It is - ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -132,7 +135,7 @@ def __init__( if client_cert_source: warnings.warn("client_cert_source is deprecated", DeprecationWarning) - if channel: + if isinstance(channel, grpc.Channel): # Ignore credentials if a channel was passed. credentials = False # If a channel was explicitly provided, set it. @@ -173,7 +176,9 @@ def __init__( ) if not self._grpc_channel: - self._grpc_channel = type(self).create_channel( + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( self._host, # use the credentials which are saved credentials=self._credentials, diff --git a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py index ddf3d0eb53..27edc02d88 100644 --- a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py +++ b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers_async +from google.api_core import exceptions as core_exceptions +from google.api_core import retry_async as retries from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -79,7 +81,6 @@ def create_channel( the credentials from the environment. credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. scopes (Optional[Sequence[str]]): A optional list of scopes needed for this service. These are only used when credentials are not specified and are passed to :func:`google.auth.default`. @@ -109,7 +110,7 @@ def __init__( credentials: Optional[ga_credentials.Credentials] = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, - channel: Optional[aio.Channel] = None, + channel: Optional[Union[aio.Channel, Callable[..., aio.Channel]]] = None, api_mtls_endpoint: Optional[str] = None, client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, @@ -123,21 +124,24 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. scopes (Optional[Sequence[str]]): A optional list of scopes needed for this service. These are only used when credentials are not specified and are passed to :func:`google.auth.default`. - channel (Optional[aio.Channel]): A ``Channel`` instance through - which to make calls. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from @@ -147,11 +151,11 @@ def __init__( private key bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials - for the grpc channel. It is ignored if ``channel`` is provided. + for the grpc channel. It is ignored if a ``channel`` instance is provided. client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): A callback to provide client certificate bytes and private key bytes, both in PEM format. It is used to configure a mutual TLS channel. It is - ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -178,7 +182,7 @@ def __init__( if client_cert_source: warnings.warn("client_cert_source is deprecated", DeprecationWarning) - if channel: + if isinstance(channel, aio.Channel): # Ignore credentials if a channel was passed. credentials = False # If a channel was explicitly provided, set it. @@ -218,7 +222,9 @@ def __init__( ) if not self._grpc_channel: - self._grpc_channel = type(self).create_channel( + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( self._host, # use the credentials which are saved credentials=self._credentials, @@ -973,6 +979,251 @@ def list_database_roles( ) return self._stubs["list_database_roles"] + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.list_databases: gapic_v1.method_async.wrap_method( + self.list_databases, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.create_database: gapic_v1.method_async.wrap_method( + self.create_database, + default_timeout=3600.0, + client_info=client_info, + ), + self.get_database: gapic_v1.method_async.wrap_method( + self.get_database, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.update_database: gapic_v1.method_async.wrap_method( + self.update_database, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.update_database_ddl: gapic_v1.method_async.wrap_method( + self.update_database_ddl, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.drop_database: gapic_v1.method_async.wrap_method( + self.drop_database, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.get_database_ddl: gapic_v1.method_async.wrap_method( + self.get_database_ddl, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.set_iam_policy: gapic_v1.method_async.wrap_method( + self.set_iam_policy, + default_timeout=30.0, + client_info=client_info, + ), + self.get_iam_policy: gapic_v1.method_async.wrap_method( + self.get_iam_policy, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.test_iam_permissions: gapic_v1.method_async.wrap_method( + self.test_iam_permissions, + default_timeout=30.0, + client_info=client_info, + ), + self.create_backup: gapic_v1.method_async.wrap_method( + self.create_backup, + default_timeout=3600.0, + client_info=client_info, + ), + self.copy_backup: gapic_v1.method_async.wrap_method( + self.copy_backup, + default_timeout=3600.0, + client_info=client_info, + ), + self.get_backup: gapic_v1.method_async.wrap_method( + self.get_backup, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.update_backup: gapic_v1.method_async.wrap_method( + self.update_backup, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.delete_backup: gapic_v1.method_async.wrap_method( + self.delete_backup, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.list_backups: gapic_v1.method_async.wrap_method( + self.list_backups, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.restore_database: gapic_v1.method_async.wrap_method( + self.restore_database, + default_timeout=3600.0, + client_info=client_info, + ), + self.list_database_operations: gapic_v1.method_async.wrap_method( + self.list_database_operations, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.list_backup_operations: gapic_v1.method_async.wrap_method( + self.list_backup_operations, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.list_database_roles: gapic_v1.method_async.wrap_method( + self.list_database_roles, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + } + def close(self): return self.grpc_channel.close() diff --git a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest.py b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest.py index 07fe33ae45..0b3cf277e8 100644 --- a/google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest.py +++ b/google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -35,9 +35,9 @@ import warnings try: - OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] except AttributeError: # pragma: NO COVER - OptionalRetry = Union[retries.Retry, object] # type: ignore + OptionalRetry = Union[retries.Retry, object, None] # type: ignore from google.cloud.spanner_admin_database_v1.types import backup @@ -799,7 +799,7 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -1013,9 +1013,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1024,7 +1022,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1112,9 +1109,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1123,7 +1118,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1209,9 +1203,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1220,7 +1212,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1302,7 +1293,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1377,7 +1367,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1456,7 +1445,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1543,7 +1531,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1634,7 +1621,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1797,9 +1783,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1808,7 +1792,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1900,7 +1883,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1989,7 +1971,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2082,7 +2063,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2173,7 +2153,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2262,7 +2241,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2351,9 +2329,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -2362,7 +2338,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2524,9 +2499,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -2535,7 +2508,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2631,9 +2603,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -2642,7 +2612,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2729,9 +2698,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -2740,7 +2707,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2830,9 +2796,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -2841,7 +2805,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2946,9 +2909,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -2957,7 +2918,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) diff --git a/google/cloud/spanner_admin_database_v1/types/__init__.py b/google/cloud/spanner_admin_database_v1/types/__init__.py index ca9e75cf9e..a53acf5648 100644 --- a/google/cloud/spanner_admin_database_v1/types/__init__.py +++ b/google/cloud/spanner_admin_database_v1/types/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_database_v1/types/backup.py b/google/cloud/spanner_admin_database_v1/types/backup.py index 89180ccded..6feff1bcdd 100644 --- a/google/cloud/spanner_admin_database_v1/types/backup.py +++ b/google/cloud/spanner_admin_database_v1/types/backup.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_database_v1/types/common.py b/google/cloud/spanner_admin_database_v1/types/common.py index 9b62821e00..3c7c190602 100644 --- a/google/cloud/spanner_admin_database_v1/types/common.py +++ b/google/cloud/spanner_admin_database_v1/types/common.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py b/google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py index b124e628d8..e799c50c04 100644 --- a/google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py +++ b/google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_instance_v1/__init__.py b/google/cloud/spanner_admin_instance_v1/__init__.py index e92a5768ad..bf71662118 100644 --- a/google/cloud/spanner_admin_instance_v1/__init__.py +++ b/google/cloud/spanner_admin_instance_v1/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -22,27 +22,39 @@ from .services.instance_admin import InstanceAdminAsyncClient from .types.common import OperationProgress +from .types.common import FulfillmentPeriod from .types.spanner_instance_admin import AutoscalingConfig from .types.spanner_instance_admin import CreateInstanceConfigMetadata from .types.spanner_instance_admin import CreateInstanceConfigRequest from .types.spanner_instance_admin import CreateInstanceMetadata +from .types.spanner_instance_admin import CreateInstancePartitionMetadata +from .types.spanner_instance_admin import CreateInstancePartitionRequest from .types.spanner_instance_admin import CreateInstanceRequest from .types.spanner_instance_admin import DeleteInstanceConfigRequest +from .types.spanner_instance_admin import DeleteInstancePartitionRequest from .types.spanner_instance_admin import DeleteInstanceRequest from .types.spanner_instance_admin import GetInstanceConfigRequest +from .types.spanner_instance_admin import GetInstancePartitionRequest from .types.spanner_instance_admin import GetInstanceRequest from .types.spanner_instance_admin import Instance from .types.spanner_instance_admin import InstanceConfig +from .types.spanner_instance_admin import InstancePartition from .types.spanner_instance_admin import ListInstanceConfigOperationsRequest from .types.spanner_instance_admin import ListInstanceConfigOperationsResponse from .types.spanner_instance_admin import ListInstanceConfigsRequest from .types.spanner_instance_admin import ListInstanceConfigsResponse +from .types.spanner_instance_admin import ListInstancePartitionOperationsRequest +from .types.spanner_instance_admin import ListInstancePartitionOperationsResponse +from .types.spanner_instance_admin import ListInstancePartitionsRequest +from .types.spanner_instance_admin import ListInstancePartitionsResponse from .types.spanner_instance_admin import ListInstancesRequest from .types.spanner_instance_admin import ListInstancesResponse from .types.spanner_instance_admin import ReplicaInfo from .types.spanner_instance_admin import UpdateInstanceConfigMetadata from .types.spanner_instance_admin import UpdateInstanceConfigRequest from .types.spanner_instance_admin import UpdateInstanceMetadata +from .types.spanner_instance_admin import UpdateInstancePartitionMetadata +from .types.spanner_instance_admin import UpdateInstancePartitionRequest from .types.spanner_instance_admin import UpdateInstanceRequest __all__ = ( @@ -51,18 +63,28 @@ "CreateInstanceConfigMetadata", "CreateInstanceConfigRequest", "CreateInstanceMetadata", + "CreateInstancePartitionMetadata", + "CreateInstancePartitionRequest", "CreateInstanceRequest", "DeleteInstanceConfigRequest", + "DeleteInstancePartitionRequest", "DeleteInstanceRequest", + "FulfillmentPeriod", "GetInstanceConfigRequest", + "GetInstancePartitionRequest", "GetInstanceRequest", "Instance", "InstanceAdminClient", "InstanceConfig", + "InstancePartition", "ListInstanceConfigOperationsRequest", "ListInstanceConfigOperationsResponse", "ListInstanceConfigsRequest", "ListInstanceConfigsResponse", + "ListInstancePartitionOperationsRequest", + "ListInstancePartitionOperationsResponse", + "ListInstancePartitionsRequest", + "ListInstancePartitionsResponse", "ListInstancesRequest", "ListInstancesResponse", "OperationProgress", @@ -70,5 +92,7 @@ "UpdateInstanceConfigMetadata", "UpdateInstanceConfigRequest", "UpdateInstanceMetadata", + "UpdateInstancePartitionMetadata", + "UpdateInstancePartitionRequest", "UpdateInstanceRequest", ) diff --git a/google/cloud/spanner_admin_instance_v1/gapic_metadata.json b/google/cloud/spanner_admin_instance_v1/gapic_metadata.json index a3ee34c069..361a5807c8 100644 --- a/google/cloud/spanner_admin_instance_v1/gapic_metadata.json +++ b/google/cloud/spanner_admin_instance_v1/gapic_metadata.json @@ -20,6 +20,11 @@ "create_instance_config" ] }, + "CreateInstancePartition": { + "methods": [ + "create_instance_partition" + ] + }, "DeleteInstance": { "methods": [ "delete_instance" @@ -30,6 +35,11 @@ "delete_instance_config" ] }, + "DeleteInstancePartition": { + "methods": [ + "delete_instance_partition" + ] + }, "GetIamPolicy": { "methods": [ "get_iam_policy" @@ -45,6 +55,11 @@ "get_instance_config" ] }, + "GetInstancePartition": { + "methods": [ + "get_instance_partition" + ] + }, "ListInstanceConfigOperations": { "methods": [ "list_instance_config_operations" @@ -55,6 +70,16 @@ "list_instance_configs" ] }, + "ListInstancePartitionOperations": { + "methods": [ + "list_instance_partition_operations" + ] + }, + "ListInstancePartitions": { + "methods": [ + "list_instance_partitions" + ] + }, "ListInstances": { "methods": [ "list_instances" @@ -79,6 +104,11 @@ "methods": [ "update_instance_config" ] + }, + "UpdateInstancePartition": { + "methods": [ + "update_instance_partition" + ] } } }, @@ -95,6 +125,11 @@ "create_instance_config" ] }, + "CreateInstancePartition": { + "methods": [ + "create_instance_partition" + ] + }, "DeleteInstance": { "methods": [ "delete_instance" @@ -105,6 +140,11 @@ "delete_instance_config" ] }, + "DeleteInstancePartition": { + "methods": [ + "delete_instance_partition" + ] + }, "GetIamPolicy": { "methods": [ "get_iam_policy" @@ -120,6 +160,11 @@ "get_instance_config" ] }, + "GetInstancePartition": { + "methods": [ + "get_instance_partition" + ] + }, "ListInstanceConfigOperations": { "methods": [ "list_instance_config_operations" @@ -130,6 +175,16 @@ "list_instance_configs" ] }, + "ListInstancePartitionOperations": { + "methods": [ + "list_instance_partition_operations" + ] + }, + "ListInstancePartitions": { + "methods": [ + "list_instance_partitions" + ] + }, "ListInstances": { "methods": [ "list_instances" @@ -154,6 +209,11 @@ "methods": [ "update_instance_config" ] + }, + "UpdateInstancePartition": { + "methods": [ + "update_instance_partition" + ] } } }, @@ -170,6 +230,11 @@ "create_instance_config" ] }, + "CreateInstancePartition": { + "methods": [ + "create_instance_partition" + ] + }, "DeleteInstance": { "methods": [ "delete_instance" @@ -180,6 +245,11 @@ "delete_instance_config" ] }, + "DeleteInstancePartition": { + "methods": [ + "delete_instance_partition" + ] + }, "GetIamPolicy": { "methods": [ "get_iam_policy" @@ -195,6 +265,11 @@ "get_instance_config" ] }, + "GetInstancePartition": { + "methods": [ + "get_instance_partition" + ] + }, "ListInstanceConfigOperations": { "methods": [ "list_instance_config_operations" @@ -205,6 +280,16 @@ "list_instance_configs" ] }, + "ListInstancePartitionOperations": { + "methods": [ + "list_instance_partition_operations" + ] + }, + "ListInstancePartitions": { + "methods": [ + "list_instance_partitions" + ] + }, "ListInstances": { "methods": [ "list_instances" @@ -229,6 +314,11 @@ "methods": [ "update_instance_config" ] + }, + "UpdateInstancePartition": { + "methods": [ + "update_instance_partition" + ] } } } diff --git a/google/cloud/spanner_admin_instance_v1/services/__init__.py b/google/cloud/spanner_admin_instance_v1/services/__init__.py index 89a37dc92c..8f6cf06824 100644 --- a/google/cloud/spanner_admin_instance_v1/services/__init__.py +++ b/google/cloud/spanner_admin_instance_v1/services/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py b/google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py index cfb0247370..aab66a65b0 100644 --- a/google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py +++ b/google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_instance_v1/services/instance_admin/async_client.py b/google/cloud/spanner_admin_instance_v1/services/instance_admin/async_client.py index a6ad4ca887..08380012aa 100644 --- a/google/cloud/spanner_admin_instance_v1/services/instance_admin/async_client.py +++ b/google/cloud/spanner_admin_instance_v1/services/instance_admin/async_client.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ import re from typing import ( Dict, + Callable, Mapping, MutableMapping, MutableSequence, @@ -38,9 +39,9 @@ from google.oauth2 import service_account # type: ignore try: - OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault] + OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None] except AttributeError: # pragma: NO COVER - OptionalRetry = Union[retries.AsyncRetry, object] # type: ignore + OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore @@ -84,8 +85,12 @@ class InstanceAdminAsyncClient: _client: InstanceAdminClient + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. DEFAULT_ENDPOINT = InstanceAdminClient.DEFAULT_ENDPOINT DEFAULT_MTLS_ENDPOINT = InstanceAdminClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = InstanceAdminClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = InstanceAdminClient._DEFAULT_UNIVERSE instance_path = staticmethod(InstanceAdminClient.instance_path) parse_instance_path = staticmethod(InstanceAdminClient.parse_instance_path) @@ -93,6 +98,10 @@ class InstanceAdminAsyncClient: parse_instance_config_path = staticmethod( InstanceAdminClient.parse_instance_config_path ) + instance_partition_path = staticmethod(InstanceAdminClient.instance_partition_path) + parse_instance_partition_path = staticmethod( + InstanceAdminClient.parse_instance_partition_path + ) common_billing_account_path = staticmethod( InstanceAdminClient.common_billing_account_path ) @@ -196,6 +205,25 @@ def transport(self) -> InstanceAdminTransport: """ return self._client.transport + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + get_transport_class = functools.partial( type(InstanceAdminClient).get_transport_class, type(InstanceAdminClient) ) @@ -204,11 +232,13 @@ def __init__( self, *, credentials: Optional[ga_credentials.Credentials] = None, - transport: Union[str, InstanceAdminTransport] = "grpc_asyncio", + transport: Optional[ + Union[str, InstanceAdminTransport, Callable[..., InstanceAdminTransport]] + ] = "grpc_asyncio", client_options: Optional[ClientOptions] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiates the instance admin client. + """Instantiates the instance admin async client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -216,26 +246,43 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.InstanceAdminTransport]): The - transport to use. If set to None, a transport is chosen - automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. - (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT - environment variable can also be used to override the endpoint: + transport (Optional[Union[str,InstanceAdminTransport,Callable[..., InstanceAdminTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the InstanceAdminTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint) and "auto" (auto switch to the - default mTLS endpoint if client certificate is present, this is - the default value). However, the ``api_endpoint`` property takes - precedence if provided. - (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable is "true", then the ``client_cert_source`` property can be used - to provide client certificate for mutual TLS transport. If + to provide a client certificate for mTLS transport. If not provided, the default SSL client certificate will be used if present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not set, no client certificate will be used. + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport creation failed for any reason. @@ -316,8 +363,8 @@ async def sample_list_instance_configs(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -325,7 +372,10 @@ async def sample_list_instance_configs(): "the individual field arguments should be set." ) - request = spanner_instance_admin.ListInstanceConfigsRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.ListInstanceConfigsRequest): + request = spanner_instance_admin.ListInstanceConfigsRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -334,21 +384,9 @@ async def sample_list_instance_configs(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.list_instance_configs, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_instance_configs + ] # Certain fields should be provided within the metadata header; # add these here. @@ -356,6 +394,9 @@ async def sample_list_instance_configs(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -443,8 +484,8 @@ async def sample_get_instance_config(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -452,7 +493,10 @@ async def sample_get_instance_config(): "the individual field arguments should be set." ) - request = spanner_instance_admin.GetInstanceConfigRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.GetInstanceConfigRequest): + request = spanner_instance_admin.GetInstanceConfigRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -461,21 +505,9 @@ async def sample_get_instance_config(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.get_instance_config, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_instance_config + ] # Certain fields should be provided within the metadata header; # add these here. @@ -483,6 +515,9 @@ async def sample_get_instance_config(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -632,8 +667,8 @@ async def sample_create_instance_config(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, instance_config, instance_config_id]) if request is not None and has_flattened_params: raise ValueError( @@ -641,7 +676,10 @@ async def sample_create_instance_config(): "the individual field arguments should be set." ) - request = spanner_instance_admin.CreateInstanceConfigRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.CreateInstanceConfigRequest): + request = spanner_instance_admin.CreateInstanceConfigRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -654,11 +692,9 @@ async def sample_create_instance_config(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.create_instance_config, - default_timeout=None, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_instance_config + ] # Certain fields should be provided within the metadata header; # add these here. @@ -666,6 +702,9 @@ async def sample_create_instance_config(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -821,8 +860,8 @@ async def sample_update_instance_config(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([instance_config, update_mask]) if request is not None and has_flattened_params: raise ValueError( @@ -830,7 +869,10 @@ async def sample_update_instance_config(): "the individual field arguments should be set." ) - request = spanner_instance_admin.UpdateInstanceConfigRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.UpdateInstanceConfigRequest): + request = spanner_instance_admin.UpdateInstanceConfigRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -841,11 +883,9 @@ async def sample_update_instance_config(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.update_instance_config, - default_timeout=None, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_instance_config + ] # Certain fields should be provided within the metadata header; # add these here. @@ -855,6 +895,9 @@ async def sample_update_instance_config(): ), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -937,8 +980,8 @@ async def sample_delete_instance_config(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -946,7 +989,10 @@ async def sample_delete_instance_config(): "the individual field arguments should be set." ) - request = spanner_instance_admin.DeleteInstanceConfigRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.DeleteInstanceConfigRequest): + request = spanner_instance_admin.DeleteInstanceConfigRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -955,11 +1001,9 @@ async def sample_delete_instance_config(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.delete_instance_config, - default_timeout=None, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.delete_instance_config + ] # Certain fields should be provided within the metadata header; # add these here. @@ -967,6 +1011,9 @@ async def sample_delete_instance_config(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. await rpc( request, @@ -1053,8 +1100,8 @@ async def sample_list_instance_config_operations(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -1062,7 +1109,14 @@ async def sample_list_instance_config_operations(): "the individual field arguments should be set." ) - request = spanner_instance_admin.ListInstanceConfigOperationsRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.ListInstanceConfigOperationsRequest + ): + request = spanner_instance_admin.ListInstanceConfigOperationsRequest( + request + ) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1071,11 +1125,9 @@ async def sample_list_instance_config_operations(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.list_instance_config_operations, - default_timeout=None, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_instance_config_operations + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1083,6 +1135,9 @@ async def sample_list_instance_config_operations(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1171,8 +1226,8 @@ async def sample_list_instances(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -1180,7 +1235,10 @@ async def sample_list_instances(): "the individual field arguments should be set." ) - request = spanner_instance_admin.ListInstancesRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.ListInstancesRequest): + request = spanner_instance_admin.ListInstancesRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1189,21 +1247,9 @@ async def sample_list_instances(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.list_instances, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_instances + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1211,6 +1257,9 @@ async def sample_list_instances(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1231,6 +1280,130 @@ async def sample_list_instances(): # Done; return the response. return response + async def list_instance_partitions( + self, + request: Optional[ + Union[spanner_instance_admin.ListInstancePartitionsRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListInstancePartitionsAsyncPager: + r"""Lists all instance partitions for the given instance. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + async def sample_list_instance_partitions(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.ListInstancePartitionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_instance_partitions(request=request) + + # Handle the response + async for response in page_result: + print(response) + + Args: + request (Optional[Union[google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsRequest, dict]]): + The request object. The request for + [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions]. + parent (:class:`str`): + Required. The instance whose instance partitions should + be listed. Values are of the form + ``projects//instances/``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstancePartitionsAsyncPager: + The response for + [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions]. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.ListInstancePartitionsRequest + ): + request = spanner_instance_admin.ListInstancePartitionsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_instance_partitions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # This method is paged; wrap the response in a pager, which provides + # an `__aiter__` convenience method. + response = pagers.ListInstancePartitionsAsyncPager( + method=rpc, + request=request, + response=response, + metadata=metadata, + ) + + # Done; return the response. + return response + async def get_instance( self, request: Optional[ @@ -1295,8 +1468,8 @@ async def sample_get_instance(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -1304,7 +1477,10 @@ async def sample_get_instance(): "the individual field arguments should be set." ) - request = spanner_instance_admin.GetInstanceRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.GetInstanceRequest): + request = spanner_instance_admin.GetInstanceRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1313,21 +1489,9 @@ async def sample_get_instance(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.get_instance, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_instance + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1335,6 +1499,9 @@ async def sample_get_instance(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1479,8 +1646,8 @@ async def sample_create_instance(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, instance_id, instance]) if request is not None and has_flattened_params: raise ValueError( @@ -1488,7 +1655,10 @@ async def sample_create_instance(): "the individual field arguments should be set." ) - request = spanner_instance_admin.CreateInstanceRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.CreateInstanceRequest): + request = spanner_instance_admin.CreateInstanceRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1501,11 +1671,9 @@ async def sample_create_instance(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.create_instance, - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_instance + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1513,6 +1681,9 @@ async def sample_create_instance(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1668,8 +1839,8 @@ async def sample_update_instance(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([instance, field_mask]) if request is not None and has_flattened_params: raise ValueError( @@ -1677,7 +1848,10 @@ async def sample_update_instance(): "the individual field arguments should be set." ) - request = spanner_instance_admin.UpdateInstanceRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.UpdateInstanceRequest): + request = spanner_instance_admin.UpdateInstanceRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1688,11 +1862,9 @@ async def sample_update_instance(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.update_instance, - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_instance + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1702,6 +1874,9 @@ async def sample_update_instance(): ), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1786,8 +1961,8 @@ async def sample_delete_instance(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -1795,7 +1970,10 @@ async def sample_delete_instance(): "the individual field arguments should be set." ) - request = spanner_instance_admin.DeleteInstanceRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.DeleteInstanceRequest): + request = spanner_instance_admin.DeleteInstanceRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1804,21 +1982,9 @@ async def sample_delete_instance(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.delete_instance, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.delete_instance + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1826,6 +1992,9 @@ async def sample_delete_instance(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. await rpc( request, @@ -1929,8 +2098,8 @@ async def sample_set_iam_policy(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource]) if request is not None and has_flattened_params: raise ValueError( @@ -1938,22 +2107,18 @@ async def sample_set_iam_policy(): "the individual field arguments should be set." ) - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. if isinstance(request, dict): request = iam_policy_pb2.SetIamPolicyRequest(**request) elif not request: - request = iam_policy_pb2.SetIamPolicyRequest( - resource=resource, - ) + request = iam_policy_pb2.SetIamPolicyRequest(resource=resource) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.set_iam_policy, - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.set_iam_policy + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1961,6 +2126,9 @@ async def sample_set_iam_policy(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2068,8 +2236,8 @@ async def sample_get_iam_policy(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource]) if request is not None and has_flattened_params: raise ValueError( @@ -2077,32 +2245,18 @@ async def sample_get_iam_policy(): "the individual field arguments should be set." ) - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. if isinstance(request, dict): request = iam_policy_pb2.GetIamPolicyRequest(**request) elif not request: - request = iam_policy_pb2.GetIamPolicyRequest( - resource=resource, - ) + request = iam_policy_pb2.GetIamPolicyRequest(resource=resource) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.get_iam_policy, - default_retry=retries.AsyncRetry( - initial=1.0, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_iam_policy + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2110,6 +2264,9 @@ async def sample_get_iam_policy(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2199,8 +2356,8 @@ async def sample_test_iam_permissions(): Response message for TestIamPermissions method. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource, permissions]) if request is not None and has_flattened_params: raise ValueError( @@ -2208,23 +2365,20 @@ async def sample_test_iam_permissions(): "the individual field arguments should be set." ) - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. if isinstance(request, dict): request = iam_policy_pb2.TestIamPermissionsRequest(**request) elif not request: request = iam_policy_pb2.TestIamPermissionsRequest( - resource=resource, - permissions=permissions, + resource=resource, permissions=permissions ) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.test_iam_permissions, - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.test_iam_permissions + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2232,6 +2386,120 @@ async def sample_test_iam_permissions(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_instance_partition( + self, + request: Optional[ + Union[spanner_instance_admin.GetInstancePartitionRequest, dict] + ] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> spanner_instance_admin.InstancePartition: + r"""Gets information about a particular instance + partition. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + async def sample_get_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.GetInstancePartitionRequest( + name="name_value", + ) + + # Make the request + response = await client.get_instance_partition(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.spanner_admin_instance_v1.types.GetInstancePartitionRequest, dict]]): + The request object. The request for + [GetInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.GetInstancePartition]. + name (:class:`str`): + Required. The name of the requested instance partition. + Values are of the form + ``projects/{project}/instances/{instance}/instancePartitions/{instance_partition}``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.spanner_admin_instance_v1.types.InstancePartition: + An isolated set of Cloud Spanner + resources that databases can define + placements on. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.GetInstancePartitionRequest): + request = spanner_instance_admin.GetInstancePartitionRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_instance_partition + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2243,6 +2511,648 @@ async def sample_test_iam_permissions(): # Done; return the response. return response + async def create_instance_partition( + self, + request: Optional[ + Union[spanner_instance_admin.CreateInstancePartitionRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + instance_partition: Optional[spanner_instance_admin.InstancePartition] = None, + instance_partition_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Creates an instance partition and begins preparing it to be + used. The returned [long-running + operation][google.longrunning.Operation] can be used to track + the progress of preparing the new instance partition. The + instance partition name is assigned by the caller. If the named + instance partition already exists, ``CreateInstancePartition`` + returns ``ALREADY_EXISTS``. + + Immediately upon completion of this request: + + - The instance partition is readable via the API, with all + requested attributes but no allocated resources. Its state is + ``CREATING``. + + Until completion of the returned operation: + + - Cancelling the operation renders the instance partition + immediately unreadable via the API. + - The instance partition can be deleted. + - All other attempts to modify the instance partition are + rejected. + + Upon completion of the returned operation: + + - Billing for all successfully-allocated resources begins (some + types may have lower than the requested levels). + - Databases can start using this instance partition. + - The instance partition's allocated resource levels are + readable via the API. + - The instance partition's state becomes ``READY``. + + The returned [long-running + operation][google.longrunning.Operation] will have a name of the + format ``/operations/`` + and can be used to track creation of the instance partition. The + [metadata][google.longrunning.Operation.metadata] field type is + [CreateInstancePartitionMetadata][google.spanner.admin.instance.v1.CreateInstancePartitionMetadata]. + The [response][google.longrunning.Operation.response] field type + is + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], + if successful. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + async def sample_create_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + instance_partition = spanner_admin_instance_v1.InstancePartition() + instance_partition.node_count = 1070 + instance_partition.name = "name_value" + instance_partition.config = "config_value" + instance_partition.display_name = "display_name_value" + + request = spanner_admin_instance_v1.CreateInstancePartitionRequest( + parent="parent_value", + instance_partition_id="instance_partition_id_value", + instance_partition=instance_partition, + ) + + # Make the request + operation = client.create_instance_partition(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.spanner_admin_instance_v1.types.CreateInstancePartitionRequest, dict]]): + The request object. The request for + [CreateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition]. + parent (:class:`str`): + Required. The name of the instance in which to create + the instance partition. Values are of the form + ``projects//instances/``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + instance_partition (:class:`google.cloud.spanner_admin_instance_v1.types.InstancePartition`): + Required. The instance partition to create. The + instance_partition.name may be omitted, but if specified + must be + ``/instancePartitions/``. + + This corresponds to the ``instance_partition`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + instance_partition_id (:class:`str`): + Required. The ID of the instance partition to create. + Valid identifiers are of the form + ``[a-z][-a-z0-9]*[a-z0-9]`` and must be between 2 and 64 + characters in length. + + This corresponds to the ``instance_partition_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.spanner_admin_instance_v1.types.InstancePartition` An isolated set of Cloud Spanner resources that databases can define + placements on. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, instance_partition, instance_partition_id]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.CreateInstancePartitionRequest + ): + request = spanner_instance_admin.CreateInstancePartitionRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if instance_partition is not None: + request.instance_partition = instance_partition + if instance_partition_id is not None: + request.instance_partition_id = instance_partition_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_instance_partition + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + spanner_instance_admin.InstancePartition, + metadata_type=spanner_instance_admin.CreateInstancePartitionMetadata, + ) + + # Done; return the response. + return response + + async def delete_instance_partition( + self, + request: Optional[ + Union[spanner_instance_admin.DeleteInstancePartitionRequest, dict] + ] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> None: + r"""Deletes an existing instance partition. Requires that the + instance partition is not used by any database or backup and is + not the default instance partition of an instance. + + Authorization requires ``spanner.instancePartitions.delete`` + permission on the resource + [name][google.spanner.admin.instance.v1.InstancePartition.name]. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + async def sample_delete_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.DeleteInstancePartitionRequest( + name="name_value", + ) + + # Make the request + await client.delete_instance_partition(request=request) + + Args: + request (Optional[Union[google.cloud.spanner_admin_instance_v1.types.DeleteInstancePartitionRequest, dict]]): + The request object. The request for + [DeleteInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstancePartition]. + name (:class:`str`): + Required. The name of the instance partition to be + deleted. Values are of the form + ``projects/{project}/instances/{instance}/instancePartitions/{instance_partition}`` + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.DeleteInstancePartitionRequest + ): + request = spanner_instance_admin.DeleteInstancePartitionRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.delete_instance_partition + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def update_instance_partition( + self, + request: Optional[ + Union[spanner_instance_admin.UpdateInstancePartitionRequest, dict] + ] = None, + *, + instance_partition: Optional[spanner_instance_admin.InstancePartition] = None, + field_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Updates an instance partition, and begins allocating or + releasing resources as requested. The returned [long-running + operation][google.longrunning.Operation] can be used to track + the progress of updating the instance partition. If the named + instance partition does not exist, returns ``NOT_FOUND``. + + Immediately upon completion of this request: + + - For resource types for which a decrease in the instance + partition's allocation has been requested, billing is based + on the newly-requested level. + + Until completion of the returned operation: + + - Cancelling the operation sets its metadata's + [cancel_time][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata.cancel_time], + and begins restoring resources to their pre-request values. + The operation is guaranteed to succeed at undoing all + resource changes, after which point it terminates with a + ``CANCELLED`` status. + - All other attempts to modify the instance partition are + rejected. + - Reading the instance partition via the API continues to give + the pre-request resource levels. + + Upon completion of the returned operation: + + - Billing begins for all successfully-allocated resources (some + types may have lower than the requested levels). + - All newly-reserved resources are available for serving the + instance partition's tables. + - The instance partition's new resource levels are readable via + the API. + + The returned [long-running + operation][google.longrunning.Operation] will have a name of the + format ``/operations/`` + and can be used to track the instance partition modification. + The [metadata][google.longrunning.Operation.metadata] field type + is + [UpdateInstancePartitionMetadata][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata]. + The [response][google.longrunning.Operation.response] field type + is + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], + if successful. + + Authorization requires ``spanner.instancePartitions.update`` + permission on the resource + [name][google.spanner.admin.instance.v1.InstancePartition.name]. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + async def sample_update_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + instance_partition = spanner_admin_instance_v1.InstancePartition() + instance_partition.node_count = 1070 + instance_partition.name = "name_value" + instance_partition.config = "config_value" + instance_partition.display_name = "display_name_value" + + request = spanner_admin_instance_v1.UpdateInstancePartitionRequest( + instance_partition=instance_partition, + ) + + # Make the request + operation = client.update_instance_partition(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.spanner_admin_instance_v1.types.UpdateInstancePartitionRequest, dict]]): + The request object. The request for + [UpdateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition]. + instance_partition (:class:`google.cloud.spanner_admin_instance_v1.types.InstancePartition`): + Required. The instance partition to update, which must + always include the instance partition name. Otherwise, + only fields mentioned in + [field_mask][google.spanner.admin.instance.v1.UpdateInstancePartitionRequest.field_mask] + need be included. + + This corresponds to the ``instance_partition`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + field_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Required. A mask specifying which fields in + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition] + should be updated. The field mask must always be + specified; this prevents any future fields in + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition] + from being erased accidentally by clients that do not + know about them. + + This corresponds to the ``field_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.spanner_admin_instance_v1.types.InstancePartition` An isolated set of Cloud Spanner resources that databases can define + placements on. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([instance_partition, field_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.UpdateInstancePartitionRequest + ): + request = spanner_instance_admin.UpdateInstancePartitionRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if instance_partition is not None: + request.instance_partition = instance_partition + if field_mask is not None: + request.field_mask = field_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_instance_partition + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("instance_partition.name", request.instance_partition.name),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + spanner_instance_admin.InstancePartition, + metadata_type=spanner_instance_admin.UpdateInstancePartitionMetadata, + ) + + # Done; return the response. + return response + + async def list_instance_partition_operations( + self, + request: Optional[ + Union[spanner_instance_admin.ListInstancePartitionOperationsRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListInstancePartitionOperationsAsyncPager: + r"""Lists instance partition [long-running + operations][google.longrunning.Operation] in the given instance. + An instance partition operation has a name of the form + ``projects//instances//instancePartitions//operations/``. + The long-running operation + [metadata][google.longrunning.Operation.metadata] field type + ``metadata.type_url`` describes the type of the metadata. + Operations returned include those that have + completed/failed/canceled within the last 7 days, and pending + operations. Operations returned are ordered by + ``operation.metadata.value.start_time`` in descending order + starting from the most recently started operation. + + Authorization requires + ``spanner.instancePartitionOperations.list`` permission on the + resource + [parent][google.spanner.admin.instance.v1.ListInstancePartitionOperationsRequest.parent]. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + async def sample_list_instance_partition_operations(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.ListInstancePartitionOperationsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_instance_partition_operations(request=request) + + # Handle the response + async for response in page_result: + print(response) + + Args: + request (Optional[Union[google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsRequest, dict]]): + The request object. The request for + [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations]. + parent (:class:`str`): + Required. The parent instance of the instance partition + operations. Values are of the form + ``projects//instances/``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstancePartitionOperationsAsyncPager: + The response for + [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations]. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.ListInstancePartitionOperationsRequest + ): + request = spanner_instance_admin.ListInstancePartitionOperationsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_instance_partition_operations + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # This method is paged; wrap the response in a pager, which provides + # an `__aiter__` convenience method. + response = pagers.ListInstancePartitionOperationsAsyncPager( + method=rpc, + request=request, + response=response, + metadata=metadata, + ) + + # Done; return the response. + return response + async def __aenter__(self) -> "InstanceAdminAsyncClient": return self diff --git a/google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py b/google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py index cab796f644..cb3664e0d2 100644 --- a/google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py +++ b/google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ import re from typing import ( Dict, + Callable, Mapping, MutableMapping, MutableSequence, @@ -28,6 +29,7 @@ Union, cast, ) +import warnings from google.cloud.spanner_admin_instance_v1 import gapic_version as package_version @@ -42,9 +44,9 @@ from google.oauth2 import service_account # type: ignore try: - OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] except AttributeError: # pragma: NO COVER - OptionalRetry = Union[retries.Retry, object] # type: ignore + OptionalRetry = Union[retries.Retry, object, None] # type: ignore from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore @@ -152,11 +154,15 @@ def _get_default_mtls_endpoint(api_endpoint): return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. DEFAULT_ENDPOINT = "spanner.googleapis.com" DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore DEFAULT_ENDPOINT ) + _DEFAULT_ENDPOINT_TEMPLATE = "spanner.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): """Creates an instance of this client using the provided credentials @@ -241,6 +247,28 @@ def parse_instance_config_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def instance_partition_path( + project: str, + instance: str, + instance_partition: str, + ) -> str: + """Returns a fully-qualified instance_partition string.""" + return "projects/{project}/instances/{instance}/instancePartitions/{instance_partition}".format( + project=project, + instance=instance, + instance_partition=instance_partition, + ) + + @staticmethod + def parse_instance_partition_path(path: str) -> Dict[str, str]: + """Parses a instance_partition path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/instances/(?P.+?)/instancePartitions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def common_billing_account_path( billing_account: str, @@ -322,7 +350,7 @@ def parse_common_location_path(path: str) -> Dict[str, str]: def get_mtls_endpoint_and_cert_source( cls, client_options: Optional[client_options_lib.ClientOptions] = None ): - """Return the API endpoint and client cert source for mutual TLS. + """Deprecated. Return the API endpoint and client cert source for mutual TLS. The client cert source is determined in the following order: (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the @@ -352,6 +380,11 @@ def get_mtls_endpoint_and_cert_source( Raises: google.auth.exceptions.MutualTLSChannelError: If any errors happen. """ + + warnings.warn( + "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", + DeprecationWarning, + ) if client_options is None: client_options = client_options_lib.ClientOptions() use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") @@ -385,11 +418,185 @@ def get_mtls_endpoint_and_cert_source( return api_endpoint, client_cert_source + @staticmethod + def _read_environment_variables(): + """Returns the environment variables used by the client. + + Returns: + Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, + GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. + + Raises: + ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not + any of ["true", "false"]. + google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT + is not any of ["auto", "never", "always"]. + """ + use_client_cert = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + return use_client_cert == "true", use_mtls_endpoint, universe_domain_env + + @staticmethod + def _get_client_cert_source(provided_cert_source, use_cert_flag): + """Return the client cert source to be used by the client. + + Args: + provided_cert_source (bytes): The client certificate source provided. + use_cert_flag (bool): A flag indicating whether to use the client certificate. + + Returns: + bytes or None: The client cert source to be used by the client. + """ + client_cert_source = None + if use_cert_flag: + if provided_cert_source: + client_cert_source = provided_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + return client_cert_source + + @staticmethod + def _get_api_endpoint( + api_override, client_cert_source, universe_domain, use_mtls_endpoint + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = InstanceAdminClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = InstanceAdminClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = InstanceAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], universe_domain_env: Optional[str] + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = InstanceAdminClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + @staticmethod + def _compare_universes( + client_universe: str, credentials: ga_credentials.Credentials + ) -> bool: + """Returns True iff the universe domains used by the client and credentials match. + + Args: + client_universe (str): The universe domain configured via the client options. + credentials (ga_credentials.Credentials): The credentials being used in the client. + + Returns: + bool: True iff client_universe matches the universe in credentials. + + Raises: + ValueError: when client_universe does not match the universe in credentials. + """ + + default_universe = InstanceAdminClient._DEFAULT_UNIVERSE + credentials_universe = getattr(credentials, "universe_domain", default_universe) + + if client_universe != credentials_universe: + raise ValueError( + "The configured universe domain " + f"({client_universe}) does not match the universe domain " + f"found in the credentials ({credentials_universe}). " + "If you haven't configured the universe domain explicitly, " + f"`{default_universe}` is the default." + ) + return True + + def _validate_universe_domain(self): + """Validates client's and credentials' universe domains are consistent. + + Returns: + bool: True iff the configured universe domain is valid. + + Raises: + ValueError: If the configured universe domain is not valid. + """ + self._is_universe_domain_valid = ( + self._is_universe_domain_valid + or InstanceAdminClient._compare_universes( + self.universe_domain, self.transport._credentials + ) + ) + return self._is_universe_domain_valid + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + def __init__( self, *, credentials: Optional[ga_credentials.Credentials] = None, - transport: Optional[Union[str, InstanceAdminTransport]] = None, + transport: Optional[ + Union[str, InstanceAdminTransport, Callable[..., InstanceAdminTransport]] + ] = None, client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -401,25 +608,37 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, InstanceAdminTransport]): The - transport to use. If set to None, a transport is chosen - automatically. - client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the - client. It won't take effect if a ``transport`` instance is provided. - (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT - environment variable can also be used to override the endpoint: + transport (Optional[Union[str,InstanceAdminTransport,Callable[..., InstanceAdminTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the InstanceAdminTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint) and "auto" (auto switch to the - default mTLS endpoint if client certificate is present, this is - the default value). However, the ``api_endpoint`` property takes - precedence if provided. - (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable is "true", then the ``client_cert_source`` property can be used - to provide client certificate for mutual TLS transport. If + to provide a client certificate for mTLS transport. If not provided, the default SSL client certificate will be used if present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): The client info used to send a user-agent string along with API requests. If ``None``, then default info will be used. @@ -430,17 +649,34 @@ def __init__( google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ - if isinstance(client_options, dict): - client_options = client_options_lib.from_dict(client_options) - if client_options is None: - client_options = client_options_lib.ClientOptions() - client_options = cast(client_options_lib.ClientOptions, client_options) + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) - api_endpoint, client_cert_source_func = self.get_mtls_endpoint_and_cert_source( - client_options + universe_domain_opt = getattr(self._client_options, "universe_domain", None) + + ( + self._use_client_cert, + self._use_mtls_endpoint, + self._universe_domain_env, + ) = InstanceAdminClient._read_environment_variables() + self._client_cert_source = InstanceAdminClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = InstanceAdminClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env ) + self._api_endpoint = None # updated below, depending on `transport` - api_key_value = getattr(client_options, "api_key", None) + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + api_key_value = getattr(self._client_options, "api_key", None) if api_key_value and credentials: raise ValueError( "client_options.api_key and credentials are mutually exclusive" @@ -449,20 +685,33 @@ def __init__( # Save or instantiate the transport. # Ordinarily, we provide the transport, but allowing a custom transport # instance provides an extensibility point for unusual situations. - if isinstance(transport, InstanceAdminTransport): + transport_provided = isinstance(transport, InstanceAdminTransport) + if transport_provided: # transport is a InstanceAdminTransport instance. - if credentials or client_options.credentials_file or api_key_value: + if credentials or self._client_options.credentials_file or api_key_value: raise ValueError( "When providing a transport instance, " "provide its credentials directly." ) - if client_options.scopes: + if self._client_options.scopes: raise ValueError( "When providing a transport instance, provide its scopes " "directly." ) - self._transport = transport - else: + self._transport = cast(InstanceAdminTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or InstanceAdminClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: import google.auth._default # type: ignore if api_key_value and hasattr( @@ -472,17 +721,24 @@ def __init__( api_key_value ) - Transport = type(self).get_transport_class(transport) - self._transport = Transport( + transport_init: Union[ + Type[InstanceAdminTransport], Callable[..., InstanceAdminTransport] + ] = ( + type(self).get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., InstanceAdminTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( credentials=credentials, - credentials_file=client_options.credentials_file, - host=api_endpoint, - scopes=client_options.scopes, - client_cert_source_for_mtls=client_cert_source_func, - quota_project_id=client_options.quota_project_id, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, client_info=client_info, always_use_jwt_access=True, - api_audience=client_options.api_audience, + api_audience=self._client_options.api_audience, ) def list_instance_configs( @@ -554,8 +810,8 @@ def sample_list_instance_configs(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -563,10 +819,8 @@ def sample_list_instance_configs(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.ListInstanceConfigsRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.ListInstanceConfigsRequest): request = spanner_instance_admin.ListInstanceConfigsRequest(request) # If we have keyword arguments corresponding to fields on the @@ -584,6 +838,9 @@ def sample_list_instance_configs(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -671,8 +928,8 @@ def sample_get_instance_config(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -680,10 +937,8 @@ def sample_get_instance_config(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.GetInstanceConfigRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.GetInstanceConfigRequest): request = spanner_instance_admin.GetInstanceConfigRequest(request) # If we have keyword arguments corresponding to fields on the @@ -701,6 +956,9 @@ def sample_get_instance_config(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -850,8 +1108,8 @@ def sample_create_instance_config(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, instance_config, instance_config_id]) if request is not None and has_flattened_params: raise ValueError( @@ -859,10 +1117,8 @@ def sample_create_instance_config(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.CreateInstanceConfigRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.CreateInstanceConfigRequest): request = spanner_instance_admin.CreateInstanceConfigRequest(request) # If we have keyword arguments corresponding to fields on the @@ -884,6 +1140,9 @@ def sample_create_instance_config(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1039,8 +1298,8 @@ def sample_update_instance_config(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([instance_config, update_mask]) if request is not None and has_flattened_params: raise ValueError( @@ -1048,10 +1307,8 @@ def sample_update_instance_config(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.UpdateInstanceConfigRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.UpdateInstanceConfigRequest): request = spanner_instance_admin.UpdateInstanceConfigRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1073,6 +1330,9 @@ def sample_update_instance_config(): ), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1155,8 +1415,8 @@ def sample_delete_instance_config(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -1164,10 +1424,8 @@ def sample_delete_instance_config(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.DeleteInstanceConfigRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.DeleteInstanceConfigRequest): request = spanner_instance_admin.DeleteInstanceConfigRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1185,6 +1443,9 @@ def sample_delete_instance_config(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. rpc( request, @@ -1271,8 +1532,8 @@ def sample_list_instance_config_operations(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -1280,10 +1541,8 @@ def sample_list_instance_config_operations(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.ListInstanceConfigOperationsRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance( request, spanner_instance_admin.ListInstanceConfigOperationsRequest ): @@ -1307,6 +1566,9 @@ def sample_list_instance_config_operations(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1395,8 +1657,8 @@ def sample_list_instances(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent]) if request is not None and has_flattened_params: raise ValueError( @@ -1404,10 +1666,8 @@ def sample_list_instances(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.ListInstancesRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.ListInstancesRequest): request = spanner_instance_admin.ListInstancesRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1425,6 +1685,9 @@ def sample_list_instances(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1445,6 +1708,127 @@ def sample_list_instances(): # Done; return the response. return response + def list_instance_partitions( + self, + request: Optional[ + Union[spanner_instance_admin.ListInstancePartitionsRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListInstancePartitionsPager: + r"""Lists all instance partitions for the given instance. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + def sample_list_instance_partitions(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.ListInstancePartitionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_instance_partitions(request=request) + + # Handle the response + for response in page_result: + print(response) + + Args: + request (Union[google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsRequest, dict]): + The request object. The request for + [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions]. + parent (str): + Required. The instance whose instance partitions should + be listed. Values are of the form + ``projects//instances/``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstancePartitionsPager: + The response for + [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions]. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.ListInstancePartitionsRequest + ): + request = spanner_instance_admin.ListInstancePartitionsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.list_instance_partitions] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # This method is paged; wrap the response in a pager, which provides + # an `__iter__` convenience method. + response = pagers.ListInstancePartitionsPager( + method=rpc, + request=request, + response=response, + metadata=metadata, + ) + + # Done; return the response. + return response + def get_instance( self, request: Optional[ @@ -1509,8 +1893,8 @@ def sample_get_instance(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -1518,10 +1902,8 @@ def sample_get_instance(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.GetInstanceRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.GetInstanceRequest): request = spanner_instance_admin.GetInstanceRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1539,6 +1921,9 @@ def sample_get_instance(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1683,8 +2068,8 @@ def sample_create_instance(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([parent, instance_id, instance]) if request is not None and has_flattened_params: raise ValueError( @@ -1692,10 +2077,8 @@ def sample_create_instance(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.CreateInstanceRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.CreateInstanceRequest): request = spanner_instance_admin.CreateInstanceRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1717,6 +2100,9 @@ def sample_create_instance(): gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1872,8 +2258,8 @@ def sample_update_instance(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([instance, field_mask]) if request is not None and has_flattened_params: raise ValueError( @@ -1881,10 +2267,8 @@ def sample_update_instance(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.UpdateInstanceRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.UpdateInstanceRequest): request = spanner_instance_admin.UpdateInstanceRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1906,6 +2290,9 @@ def sample_update_instance(): ), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1990,8 +2377,8 @@ def sample_delete_instance(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -1999,10 +2386,8 @@ def sample_delete_instance(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner_instance_admin.DeleteInstanceRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner_instance_admin.DeleteInstanceRequest): request = spanner_instance_admin.DeleteInstanceRequest(request) # If we have keyword arguments corresponding to fields on the @@ -2020,6 +2405,9 @@ def sample_delete_instance(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. rpc( request, @@ -2123,8 +2511,8 @@ def sample_set_iam_policy(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource]) if request is not None and has_flattened_params: raise ValueError( @@ -2133,8 +2521,8 @@ def sample_set_iam_policy(): ) if isinstance(request, dict): - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. request = iam_policy_pb2.SetIamPolicyRequest(**request) elif not request: # Null request, just make one. @@ -2152,6 +2540,9 @@ def sample_set_iam_policy(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2259,8 +2650,8 @@ def sample_get_iam_policy(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource]) if request is not None and has_flattened_params: raise ValueError( @@ -2269,8 +2660,8 @@ def sample_get_iam_policy(): ) if isinstance(request, dict): - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. request = iam_policy_pb2.GetIamPolicyRequest(**request) elif not request: # Null request, just make one. @@ -2288,6 +2679,9 @@ def sample_get_iam_policy(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2377,8 +2771,8 @@ def sample_test_iam_permissions(): Response message for TestIamPermissions method. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([resource, permissions]) if request is not None and has_flattened_params: raise ValueError( @@ -2387,8 +2781,8 @@ def sample_test_iam_permissions(): ) if isinstance(request, dict): - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. + # - The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. request = iam_policy_pb2.TestIamPermissionsRequest(**request) elif not request: # Null request, just make one. @@ -2408,6 +2802,9 @@ def sample_test_iam_permissions(): gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2419,6 +2816,752 @@ def sample_test_iam_permissions(): # Done; return the response. return response + def get_instance_partition( + self, + request: Optional[ + Union[spanner_instance_admin.GetInstancePartitionRequest, dict] + ] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> spanner_instance_admin.InstancePartition: + r"""Gets information about a particular instance + partition. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + def sample_get_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.GetInstancePartitionRequest( + name="name_value", + ) + + # Make the request + response = client.get_instance_partition(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.spanner_admin_instance_v1.types.GetInstancePartitionRequest, dict]): + The request object. The request for + [GetInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.GetInstancePartition]. + name (str): + Required. The name of the requested instance partition. + Values are of the form + ``projects/{project}/instances/{instance}/instancePartitions/{instance_partition}``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.spanner_admin_instance_v1.types.InstancePartition: + An isolated set of Cloud Spanner + resources that databases can define + placements on. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner_instance_admin.GetInstancePartitionRequest): + request = spanner_instance_admin.GetInstancePartitionRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.get_instance_partition] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def create_instance_partition( + self, + request: Optional[ + Union[spanner_instance_admin.CreateInstancePartitionRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + instance_partition: Optional[spanner_instance_admin.InstancePartition] = None, + instance_partition_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Creates an instance partition and begins preparing it to be + used. The returned [long-running + operation][google.longrunning.Operation] can be used to track + the progress of preparing the new instance partition. The + instance partition name is assigned by the caller. If the named + instance partition already exists, ``CreateInstancePartition`` + returns ``ALREADY_EXISTS``. + + Immediately upon completion of this request: + + - The instance partition is readable via the API, with all + requested attributes but no allocated resources. Its state is + ``CREATING``. + + Until completion of the returned operation: + + - Cancelling the operation renders the instance partition + immediately unreadable via the API. + - The instance partition can be deleted. + - All other attempts to modify the instance partition are + rejected. + + Upon completion of the returned operation: + + - Billing for all successfully-allocated resources begins (some + types may have lower than the requested levels). + - Databases can start using this instance partition. + - The instance partition's allocated resource levels are + readable via the API. + - The instance partition's state becomes ``READY``. + + The returned [long-running + operation][google.longrunning.Operation] will have a name of the + format ``/operations/`` + and can be used to track creation of the instance partition. The + [metadata][google.longrunning.Operation.metadata] field type is + [CreateInstancePartitionMetadata][google.spanner.admin.instance.v1.CreateInstancePartitionMetadata]. + The [response][google.longrunning.Operation.response] field type + is + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], + if successful. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + def sample_create_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + instance_partition = spanner_admin_instance_v1.InstancePartition() + instance_partition.node_count = 1070 + instance_partition.name = "name_value" + instance_partition.config = "config_value" + instance_partition.display_name = "display_name_value" + + request = spanner_admin_instance_v1.CreateInstancePartitionRequest( + parent="parent_value", + instance_partition_id="instance_partition_id_value", + instance_partition=instance_partition, + ) + + # Make the request + operation = client.create_instance_partition(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.spanner_admin_instance_v1.types.CreateInstancePartitionRequest, dict]): + The request object. The request for + [CreateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition]. + parent (str): + Required. The name of the instance in which to create + the instance partition. Values are of the form + ``projects//instances/``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + instance_partition (google.cloud.spanner_admin_instance_v1.types.InstancePartition): + Required. The instance partition to create. The + instance_partition.name may be omitted, but if specified + must be + ``/instancePartitions/``. + + This corresponds to the ``instance_partition`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + instance_partition_id (str): + Required. The ID of the instance partition to create. + Valid identifiers are of the form + ``[a-z][-a-z0-9]*[a-z0-9]`` and must be between 2 and 64 + characters in length. + + This corresponds to the ``instance_partition_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.spanner_admin_instance_v1.types.InstancePartition` An isolated set of Cloud Spanner resources that databases can define + placements on. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, instance_partition, instance_partition_id]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.CreateInstancePartitionRequest + ): + request = spanner_instance_admin.CreateInstancePartitionRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if instance_partition is not None: + request.instance_partition = instance_partition + if instance_partition_id is not None: + request.instance_partition_id = instance_partition_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.create_instance_partition + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + spanner_instance_admin.InstancePartition, + metadata_type=spanner_instance_admin.CreateInstancePartitionMetadata, + ) + + # Done; return the response. + return response + + def delete_instance_partition( + self, + request: Optional[ + Union[spanner_instance_admin.DeleteInstancePartitionRequest, dict] + ] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> None: + r"""Deletes an existing instance partition. Requires that the + instance partition is not used by any database or backup and is + not the default instance partition of an instance. + + Authorization requires ``spanner.instancePartitions.delete`` + permission on the resource + [name][google.spanner.admin.instance.v1.InstancePartition.name]. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + def sample_delete_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.DeleteInstancePartitionRequest( + name="name_value", + ) + + # Make the request + client.delete_instance_partition(request=request) + + Args: + request (Union[google.cloud.spanner_admin_instance_v1.types.DeleteInstancePartitionRequest, dict]): + The request object. The request for + [DeleteInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstancePartition]. + name (str): + Required. The name of the instance partition to be + deleted. Values are of the form + ``projects/{project}/instances/{instance}/instancePartitions/{instance_partition}`` + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.DeleteInstancePartitionRequest + ): + request = spanner_instance_admin.DeleteInstancePartitionRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.delete_instance_partition + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + def update_instance_partition( + self, + request: Optional[ + Union[spanner_instance_admin.UpdateInstancePartitionRequest, dict] + ] = None, + *, + instance_partition: Optional[spanner_instance_admin.InstancePartition] = None, + field_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Updates an instance partition, and begins allocating or + releasing resources as requested. The returned [long-running + operation][google.longrunning.Operation] can be used to track + the progress of updating the instance partition. If the named + instance partition does not exist, returns ``NOT_FOUND``. + + Immediately upon completion of this request: + + - For resource types for which a decrease in the instance + partition's allocation has been requested, billing is based + on the newly-requested level. + + Until completion of the returned operation: + + - Cancelling the operation sets its metadata's + [cancel_time][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata.cancel_time], + and begins restoring resources to their pre-request values. + The operation is guaranteed to succeed at undoing all + resource changes, after which point it terminates with a + ``CANCELLED`` status. + - All other attempts to modify the instance partition are + rejected. + - Reading the instance partition via the API continues to give + the pre-request resource levels. + + Upon completion of the returned operation: + + - Billing begins for all successfully-allocated resources (some + types may have lower than the requested levels). + - All newly-reserved resources are available for serving the + instance partition's tables. + - The instance partition's new resource levels are readable via + the API. + + The returned [long-running + operation][google.longrunning.Operation] will have a name of the + format ``/operations/`` + and can be used to track the instance partition modification. + The [metadata][google.longrunning.Operation.metadata] field type + is + [UpdateInstancePartitionMetadata][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata]. + The [response][google.longrunning.Operation.response] field type + is + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], + if successful. + + Authorization requires ``spanner.instancePartitions.update`` + permission on the resource + [name][google.spanner.admin.instance.v1.InstancePartition.name]. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + def sample_update_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + instance_partition = spanner_admin_instance_v1.InstancePartition() + instance_partition.node_count = 1070 + instance_partition.name = "name_value" + instance_partition.config = "config_value" + instance_partition.display_name = "display_name_value" + + request = spanner_admin_instance_v1.UpdateInstancePartitionRequest( + instance_partition=instance_partition, + ) + + # Make the request + operation = client.update_instance_partition(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.spanner_admin_instance_v1.types.UpdateInstancePartitionRequest, dict]): + The request object. The request for + [UpdateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition]. + instance_partition (google.cloud.spanner_admin_instance_v1.types.InstancePartition): + Required. The instance partition to update, which must + always include the instance partition name. Otherwise, + only fields mentioned in + [field_mask][google.spanner.admin.instance.v1.UpdateInstancePartitionRequest.field_mask] + need be included. + + This corresponds to the ``instance_partition`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + field_mask (google.protobuf.field_mask_pb2.FieldMask): + Required. A mask specifying which fields in + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition] + should be updated. The field mask must always be + specified; this prevents any future fields in + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition] + from being erased accidentally by clients that do not + know about them. + + This corresponds to the ``field_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.spanner_admin_instance_v1.types.InstancePartition` An isolated set of Cloud Spanner resources that databases can define + placements on. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([instance_partition, field_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.UpdateInstancePartitionRequest + ): + request = spanner_instance_admin.UpdateInstancePartitionRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if instance_partition is not None: + request.instance_partition = instance_partition + if field_mask is not None: + request.field_mask = field_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.update_instance_partition + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("instance_partition.name", request.instance_partition.name),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + spanner_instance_admin.InstancePartition, + metadata_type=spanner_instance_admin.UpdateInstancePartitionMetadata, + ) + + # Done; return the response. + return response + + def list_instance_partition_operations( + self, + request: Optional[ + Union[spanner_instance_admin.ListInstancePartitionOperationsRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListInstancePartitionOperationsPager: + r"""Lists instance partition [long-running + operations][google.longrunning.Operation] in the given instance. + An instance partition operation has a name of the form + ``projects//instances//instancePartitions//operations/``. + The long-running operation + [metadata][google.longrunning.Operation.metadata] field type + ``metadata.type_url`` describes the type of the metadata. + Operations returned include those that have + completed/failed/canceled within the last 7 days, and pending + operations. Operations returned are ordered by + ``operation.metadata.value.start_time`` in descending order + starting from the most recently started operation. + + Authorization requires + ``spanner.instancePartitionOperations.list`` permission on the + resource + [parent][google.spanner.admin.instance.v1.ListInstancePartitionOperationsRequest.parent]. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import spanner_admin_instance_v1 + + def sample_list_instance_partition_operations(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.ListInstancePartitionOperationsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_instance_partition_operations(request=request) + + # Handle the response + for response in page_result: + print(response) + + Args: + request (Union[google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsRequest, dict]): + The request object. The request for + [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations]. + parent (str): + Required. The parent instance of the instance partition + operations. Values are of the form + ``projects//instances/``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstancePartitionOperationsPager: + The response for + [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations]. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, spanner_instance_admin.ListInstancePartitionOperationsRequest + ): + request = spanner_instance_admin.ListInstancePartitionOperationsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_instance_partition_operations + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # This method is paged; wrap the response in a pager, which provides + # an `__iter__` convenience method. + response = pagers.ListInstancePartitionOperationsPager( + method=rpc, + request=request, + response=response, + metadata=metadata, + ) + + # Done; return the response. + return response + def __enter__(self) -> "InstanceAdminClient": return self diff --git a/google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py b/google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py index e8f26832c0..d0cd7eec47 100644 --- a/google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py +++ b/google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -428,3 +428,276 @@ async def async_generator(): def __repr__(self) -> str: return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListInstancePartitionsPager: + """A pager for iterating through ``list_instance_partitions`` requests. + + This class thinly wraps an initial + :class:`google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``instance_partitions`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListInstancePartitions`` requests and continue to iterate + through the ``instance_partitions`` field on the + corresponding responses. + + All the usual :class:`google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., spanner_instance_admin.ListInstancePartitionsResponse], + request: spanner_instance_admin.ListInstancePartitionsRequest, + response: spanner_instance_admin.ListInstancePartitionsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsRequest): + The initial request object. + response (google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = spanner_instance_admin.ListInstancePartitionsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterator[spanner_instance_admin.ListInstancePartitionsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method(self._request, metadata=self._metadata) + yield self._response + + def __iter__(self) -> Iterator[spanner_instance_admin.InstancePartition]: + for page in self.pages: + yield from page.instance_partitions + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListInstancePartitionsAsyncPager: + """A pager for iterating through ``list_instance_partitions`` requests. + + This class thinly wraps an initial + :class:`google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``instance_partitions`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListInstancePartitions`` requests and continue to iterate + through the ``instance_partitions`` field on the + corresponding responses. + + All the usual :class:`google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[ + ..., Awaitable[spanner_instance_admin.ListInstancePartitionsResponse] + ], + request: spanner_instance_admin.ListInstancePartitionsRequest, + response: spanner_instance_admin.ListInstancePartitionsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiates the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsRequest): + The initial request object. + response (google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = spanner_instance_admin.ListInstancePartitionsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages( + self, + ) -> AsyncIterator[spanner_instance_admin.ListInstancePartitionsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = await self._method(self._request, metadata=self._metadata) + yield self._response + + def __aiter__(self) -> AsyncIterator[spanner_instance_admin.InstancePartition]: + async def async_generator(): + async for page in self.pages: + for response in page.instance_partitions: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListInstancePartitionOperationsPager: + """A pager for iterating through ``list_instance_partition_operations`` requests. + + This class thinly wraps an initial + :class:`google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``operations`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListInstancePartitionOperations`` requests and continue to iterate + through the ``operations`` field on the + corresponding responses. + + All the usual :class:`google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[ + ..., spanner_instance_admin.ListInstancePartitionOperationsResponse + ], + request: spanner_instance_admin.ListInstancePartitionOperationsRequest, + response: spanner_instance_admin.ListInstancePartitionOperationsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsRequest): + The initial request object. + response (google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = spanner_instance_admin.ListInstancePartitionOperationsRequest( + request + ) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages( + self, + ) -> Iterator[spanner_instance_admin.ListInstancePartitionOperationsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method(self._request, metadata=self._metadata) + yield self._response + + def __iter__(self) -> Iterator[operations_pb2.Operation]: + for page in self.pages: + yield from page.operations + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListInstancePartitionOperationsAsyncPager: + """A pager for iterating through ``list_instance_partition_operations`` requests. + + This class thinly wraps an initial + :class:`google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``operations`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListInstancePartitionOperations`` requests and continue to iterate + through the ``operations`` field on the + corresponding responses. + + All the usual :class:`google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[ + ..., + Awaitable[spanner_instance_admin.ListInstancePartitionOperationsResponse], + ], + request: spanner_instance_admin.ListInstancePartitionOperationsRequest, + response: spanner_instance_admin.ListInstancePartitionOperationsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiates the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsRequest): + The initial request object. + response (google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = spanner_instance_admin.ListInstancePartitionOperationsRequest( + request + ) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages( + self, + ) -> AsyncIterator[spanner_instance_admin.ListInstancePartitionOperationsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = await self._method(self._request, metadata=self._metadata) + yield self._response + + def __aiter__(self) -> AsyncIterator[operations_pb2.Operation]: + async def async_generator(): + async for page in self.pages: + for response in page.operations: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/__init__.py b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/__init__.py index ef13373d1b..b25510676e 100644 --- a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/__init__.py +++ b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/base.py b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/base.py index 7a7599b8fc..c32f583282 100644 --- a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/base.py +++ b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/base.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -65,7 +65,7 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -128,6 +128,10 @@ def __init__( host += ":443" self._host = host + @property + def host(self): + return self._host + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -196,6 +200,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=3600.0, client_info=client_info, ), + self.list_instance_partitions: gapic_v1.method.wrap_method( + self.list_instance_partitions, + default_timeout=None, + client_info=client_info, + ), self.get_instance: gapic_v1.method.wrap_method( self.get_instance, default_retry=retries.Retry( @@ -261,6 +270,31 @@ def _prep_wrapped_messages(self, client_info): default_timeout=30.0, client_info=client_info, ), + self.get_instance_partition: gapic_v1.method.wrap_method( + self.get_instance_partition, + default_timeout=None, + client_info=client_info, + ), + self.create_instance_partition: gapic_v1.method.wrap_method( + self.create_instance_partition, + default_timeout=None, + client_info=client_info, + ), + self.delete_instance_partition: gapic_v1.method.wrap_method( + self.delete_instance_partition, + default_timeout=None, + client_info=client_info, + ), + self.update_instance_partition: gapic_v1.method.wrap_method( + self.update_instance_partition, + default_timeout=None, + client_info=client_info, + ), + self.list_instance_partition_operations: gapic_v1.method.wrap_method( + self.list_instance_partition_operations, + default_timeout=None, + client_info=client_info, + ), } def close(self): @@ -352,6 +386,18 @@ def list_instances( ]: raise NotImplementedError() + @property + def list_instance_partitions( + self, + ) -> Callable[ + [spanner_instance_admin.ListInstancePartitionsRequest], + Union[ + spanner_instance_admin.ListInstancePartitionsResponse, + Awaitable[spanner_instance_admin.ListInstancePartitionsResponse], + ], + ]: + raise NotImplementedError() + @property def get_instance( self, @@ -420,6 +466,57 @@ def test_iam_permissions( ]: raise NotImplementedError() + @property + def get_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.GetInstancePartitionRequest], + Union[ + spanner_instance_admin.InstancePartition, + Awaitable[spanner_instance_admin.InstancePartition], + ], + ]: + raise NotImplementedError() + + @property + def create_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.CreateInstancePartitionRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def delete_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.DeleteInstancePartitionRequest], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], + ]: + raise NotImplementedError() + + @property + def update_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.UpdateInstancePartitionRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def list_instance_partition_operations( + self, + ) -> Callable[ + [spanner_instance_admin.ListInstancePartitionOperationsRequest], + Union[ + spanner_instance_admin.ListInstancePartitionOperationsResponse, + Awaitable[spanner_instance_admin.ListInstancePartitionOperationsResponse], + ], + ]: + raise NotImplementedError() + @property def kind(self) -> str: raise NotImplementedError() diff --git a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc.py b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc.py index 03fef980e6..5fb9f55688 100644 --- a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc.py +++ b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -77,7 +77,7 @@ def __init__( credentials: Optional[ga_credentials.Credentials] = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, - channel: Optional[grpc.Channel] = None, + channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None, api_mtls_endpoint: Optional[str] = None, client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, @@ -91,20 +91,23 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. scopes (Optional(Sequence[str])): A list of scopes. This argument is - ignored if ``channel`` is provided. - channel (Optional[grpc.Channel]): A ``Channel`` instance through - which to make calls. + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from @@ -114,11 +117,11 @@ def __init__( private key bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials - for the grpc channel. It is ignored if ``channel`` is provided. + for the grpc channel. It is ignored if a ``channel`` instance is provided. client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): A callback to provide client certificate bytes and private key bytes, both in PEM format. It is used to configure a mutual TLS channel. It is - ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -145,7 +148,7 @@ def __init__( if client_cert_source: warnings.warn("client_cert_source is deprecated", DeprecationWarning) - if channel: + if isinstance(channel, grpc.Channel): # Ignore credentials if a channel was passed. credentials = False # If a channel was explicitly provided, set it. @@ -186,7 +189,9 @@ def __init__( ) if not self._grpc_channel: - self._grpc_channel = type(self).create_channel( + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( self._host, # use the credentials which are saved credentials=self._credentials, @@ -584,6 +589,35 @@ def list_instances( ) return self._stubs["list_instances"] + @property + def list_instance_partitions( + self, + ) -> Callable[ + [spanner_instance_admin.ListInstancePartitionsRequest], + spanner_instance_admin.ListInstancePartitionsResponse, + ]: + r"""Return a callable for the list instance partitions method over gRPC. + + Lists all instance partitions for the given instance. + + Returns: + Callable[[~.ListInstancePartitionsRequest], + ~.ListInstancePartitionsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_instance_partitions" not in self._stubs: + self._stubs["list_instance_partitions"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/ListInstancePartitions", + request_serializer=spanner_instance_admin.ListInstancePartitionsRequest.serialize, + response_deserializer=spanner_instance_admin.ListInstancePartitionsResponse.deserialize, + ) + return self._stubs["list_instance_partitions"] + @property def get_instance( self, @@ -881,6 +915,264 @@ def test_iam_permissions( ) return self._stubs["test_iam_permissions"] + @property + def get_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.GetInstancePartitionRequest], + spanner_instance_admin.InstancePartition, + ]: + r"""Return a callable for the get instance partition method over gRPC. + + Gets information about a particular instance + partition. + + Returns: + Callable[[~.GetInstancePartitionRequest], + ~.InstancePartition]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_instance_partition" not in self._stubs: + self._stubs["get_instance_partition"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/GetInstancePartition", + request_serializer=spanner_instance_admin.GetInstancePartitionRequest.serialize, + response_deserializer=spanner_instance_admin.InstancePartition.deserialize, + ) + return self._stubs["get_instance_partition"] + + @property + def create_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.CreateInstancePartitionRequest], + operations_pb2.Operation, + ]: + r"""Return a callable for the create instance partition method over gRPC. + + Creates an instance partition and begins preparing it to be + used. The returned [long-running + operation][google.longrunning.Operation] can be used to track + the progress of preparing the new instance partition. The + instance partition name is assigned by the caller. If the named + instance partition already exists, ``CreateInstancePartition`` + returns ``ALREADY_EXISTS``. + + Immediately upon completion of this request: + + - The instance partition is readable via the API, with all + requested attributes but no allocated resources. Its state is + ``CREATING``. + + Until completion of the returned operation: + + - Cancelling the operation renders the instance partition + immediately unreadable via the API. + - The instance partition can be deleted. + - All other attempts to modify the instance partition are + rejected. + + Upon completion of the returned operation: + + - Billing for all successfully-allocated resources begins (some + types may have lower than the requested levels). + - Databases can start using this instance partition. + - The instance partition's allocated resource levels are + readable via the API. + - The instance partition's state becomes ``READY``. + + The returned [long-running + operation][google.longrunning.Operation] will have a name of the + format ``/operations/`` + and can be used to track creation of the instance partition. The + [metadata][google.longrunning.Operation.metadata] field type is + [CreateInstancePartitionMetadata][google.spanner.admin.instance.v1.CreateInstancePartitionMetadata]. + The [response][google.longrunning.Operation.response] field type + is + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], + if successful. + + Returns: + Callable[[~.CreateInstancePartitionRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_instance_partition" not in self._stubs: + self._stubs["create_instance_partition"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/CreateInstancePartition", + request_serializer=spanner_instance_admin.CreateInstancePartitionRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["create_instance_partition"] + + @property + def delete_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.DeleteInstancePartitionRequest], empty_pb2.Empty + ]: + r"""Return a callable for the delete instance partition method over gRPC. + + Deletes an existing instance partition. Requires that the + instance partition is not used by any database or backup and is + not the default instance partition of an instance. + + Authorization requires ``spanner.instancePartitions.delete`` + permission on the resource + [name][google.spanner.admin.instance.v1.InstancePartition.name]. + + Returns: + Callable[[~.DeleteInstancePartitionRequest], + ~.Empty]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "delete_instance_partition" not in self._stubs: + self._stubs["delete_instance_partition"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/DeleteInstancePartition", + request_serializer=spanner_instance_admin.DeleteInstancePartitionRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + return self._stubs["delete_instance_partition"] + + @property + def update_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.UpdateInstancePartitionRequest], + operations_pb2.Operation, + ]: + r"""Return a callable for the update instance partition method over gRPC. + + Updates an instance partition, and begins allocating or + releasing resources as requested. The returned [long-running + operation][google.longrunning.Operation] can be used to track + the progress of updating the instance partition. If the named + instance partition does not exist, returns ``NOT_FOUND``. + + Immediately upon completion of this request: + + - For resource types for which a decrease in the instance + partition's allocation has been requested, billing is based + on the newly-requested level. + + Until completion of the returned operation: + + - Cancelling the operation sets its metadata's + [cancel_time][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata.cancel_time], + and begins restoring resources to their pre-request values. + The operation is guaranteed to succeed at undoing all + resource changes, after which point it terminates with a + ``CANCELLED`` status. + - All other attempts to modify the instance partition are + rejected. + - Reading the instance partition via the API continues to give + the pre-request resource levels. + + Upon completion of the returned operation: + + - Billing begins for all successfully-allocated resources (some + types may have lower than the requested levels). + - All newly-reserved resources are available for serving the + instance partition's tables. + - The instance partition's new resource levels are readable via + the API. + + The returned [long-running + operation][google.longrunning.Operation] will have a name of the + format ``/operations/`` + and can be used to track the instance partition modification. + The [metadata][google.longrunning.Operation.metadata] field type + is + [UpdateInstancePartitionMetadata][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata]. + The [response][google.longrunning.Operation.response] field type + is + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], + if successful. + + Authorization requires ``spanner.instancePartitions.update`` + permission on the resource + [name][google.spanner.admin.instance.v1.InstancePartition.name]. + + Returns: + Callable[[~.UpdateInstancePartitionRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_instance_partition" not in self._stubs: + self._stubs["update_instance_partition"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/UpdateInstancePartition", + request_serializer=spanner_instance_admin.UpdateInstancePartitionRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["update_instance_partition"] + + @property + def list_instance_partition_operations( + self, + ) -> Callable[ + [spanner_instance_admin.ListInstancePartitionOperationsRequest], + spanner_instance_admin.ListInstancePartitionOperationsResponse, + ]: + r"""Return a callable for the list instance partition + operations method over gRPC. + + Lists instance partition [long-running + operations][google.longrunning.Operation] in the given instance. + An instance partition operation has a name of the form + ``projects//instances//instancePartitions//operations/``. + The long-running operation + [metadata][google.longrunning.Operation.metadata] field type + ``metadata.type_url`` describes the type of the metadata. + Operations returned include those that have + completed/failed/canceled within the last 7 days, and pending + operations. Operations returned are ordered by + ``operation.metadata.value.start_time`` in descending order + starting from the most recently started operation. + + Authorization requires + ``spanner.instancePartitionOperations.list`` permission on the + resource + [parent][google.spanner.admin.instance.v1.ListInstancePartitionOperationsRequest.parent]. + + Returns: + Callable[[~.ListInstancePartitionOperationsRequest], + ~.ListInstancePartitionOperationsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_instance_partition_operations" not in self._stubs: + self._stubs[ + "list_instance_partition_operations" + ] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/ListInstancePartitionOperations", + request_serializer=spanner_instance_admin.ListInstancePartitionOperationsRequest.serialize, + response_deserializer=spanner_instance_admin.ListInstancePartitionOperationsResponse.deserialize, + ) + return self._stubs["list_instance_partition_operations"] + def close(self): self.grpc_channel.close() diff --git a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc_asyncio.py b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc_asyncio.py index a5ff6d1635..99ac7f443a 100644 --- a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc_asyncio.py +++ b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc_asyncio.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers_async +from google.api_core import exceptions as core_exceptions +from google.api_core import retry_async as retries from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -92,7 +94,6 @@ def create_channel( the credentials from the environment. credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. scopes (Optional[Sequence[str]]): A optional list of scopes needed for this service. These are only used when credentials are not specified and are passed to :func:`google.auth.default`. @@ -122,7 +123,7 @@ def __init__( credentials: Optional[ga_credentials.Credentials] = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, - channel: Optional[aio.Channel] = None, + channel: Optional[Union[aio.Channel, Callable[..., aio.Channel]]] = None, api_mtls_endpoint: Optional[str] = None, client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, @@ -136,21 +137,24 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. scopes (Optional[Sequence[str]]): A optional list of scopes needed for this service. These are only used when credentials are not specified and are passed to :func:`google.auth.default`. - channel (Optional[aio.Channel]): A ``Channel`` instance through - which to make calls. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from @@ -160,11 +164,11 @@ def __init__( private key bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials - for the grpc channel. It is ignored if ``channel`` is provided. + for the grpc channel. It is ignored if a ``channel`` instance is provided. client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): A callback to provide client certificate bytes and private key bytes, both in PEM format. It is used to configure a mutual TLS channel. It is - ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -191,7 +195,7 @@ def __init__( if client_cert_source: warnings.warn("client_cert_source is deprecated", DeprecationWarning) - if channel: + if isinstance(channel, aio.Channel): # Ignore credentials if a channel was passed. credentials = False # If a channel was explicitly provided, set it. @@ -231,7 +235,9 @@ def __init__( ) if not self._grpc_channel: - self._grpc_channel = type(self).create_channel( + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( self._host, # use the credentials which are saved credentials=self._credentials, @@ -591,6 +597,35 @@ def list_instances( ) return self._stubs["list_instances"] + @property + def list_instance_partitions( + self, + ) -> Callable[ + [spanner_instance_admin.ListInstancePartitionsRequest], + Awaitable[spanner_instance_admin.ListInstancePartitionsResponse], + ]: + r"""Return a callable for the list instance partitions method over gRPC. + + Lists all instance partitions for the given instance. + + Returns: + Callable[[~.ListInstancePartitionsRequest], + Awaitable[~.ListInstancePartitionsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_instance_partitions" not in self._stubs: + self._stubs["list_instance_partitions"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/ListInstancePartitions", + request_serializer=spanner_instance_admin.ListInstancePartitionsRequest.serialize, + response_deserializer=spanner_instance_admin.ListInstancePartitionsResponse.deserialize, + ) + return self._stubs["list_instance_partitions"] + @property def get_instance( self, @@ -893,6 +928,430 @@ def test_iam_permissions( ) return self._stubs["test_iam_permissions"] + @property + def get_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.GetInstancePartitionRequest], + Awaitable[spanner_instance_admin.InstancePartition], + ]: + r"""Return a callable for the get instance partition method over gRPC. + + Gets information about a particular instance + partition. + + Returns: + Callable[[~.GetInstancePartitionRequest], + Awaitable[~.InstancePartition]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_instance_partition" not in self._stubs: + self._stubs["get_instance_partition"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/GetInstancePartition", + request_serializer=spanner_instance_admin.GetInstancePartitionRequest.serialize, + response_deserializer=spanner_instance_admin.InstancePartition.deserialize, + ) + return self._stubs["get_instance_partition"] + + @property + def create_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.CreateInstancePartitionRequest], + Awaitable[operations_pb2.Operation], + ]: + r"""Return a callable for the create instance partition method over gRPC. + + Creates an instance partition and begins preparing it to be + used. The returned [long-running + operation][google.longrunning.Operation] can be used to track + the progress of preparing the new instance partition. The + instance partition name is assigned by the caller. If the named + instance partition already exists, ``CreateInstancePartition`` + returns ``ALREADY_EXISTS``. + + Immediately upon completion of this request: + + - The instance partition is readable via the API, with all + requested attributes but no allocated resources. Its state is + ``CREATING``. + + Until completion of the returned operation: + + - Cancelling the operation renders the instance partition + immediately unreadable via the API. + - The instance partition can be deleted. + - All other attempts to modify the instance partition are + rejected. + + Upon completion of the returned operation: + + - Billing for all successfully-allocated resources begins (some + types may have lower than the requested levels). + - Databases can start using this instance partition. + - The instance partition's allocated resource levels are + readable via the API. + - The instance partition's state becomes ``READY``. + + The returned [long-running + operation][google.longrunning.Operation] will have a name of the + format ``/operations/`` + and can be used to track creation of the instance partition. The + [metadata][google.longrunning.Operation.metadata] field type is + [CreateInstancePartitionMetadata][google.spanner.admin.instance.v1.CreateInstancePartitionMetadata]. + The [response][google.longrunning.Operation.response] field type + is + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], + if successful. + + Returns: + Callable[[~.CreateInstancePartitionRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_instance_partition" not in self._stubs: + self._stubs["create_instance_partition"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/CreateInstancePartition", + request_serializer=spanner_instance_admin.CreateInstancePartitionRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["create_instance_partition"] + + @property + def delete_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.DeleteInstancePartitionRequest], + Awaitable[empty_pb2.Empty], + ]: + r"""Return a callable for the delete instance partition method over gRPC. + + Deletes an existing instance partition. Requires that the + instance partition is not used by any database or backup and is + not the default instance partition of an instance. + + Authorization requires ``spanner.instancePartitions.delete`` + permission on the resource + [name][google.spanner.admin.instance.v1.InstancePartition.name]. + + Returns: + Callable[[~.DeleteInstancePartitionRequest], + Awaitable[~.Empty]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "delete_instance_partition" not in self._stubs: + self._stubs["delete_instance_partition"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/DeleteInstancePartition", + request_serializer=spanner_instance_admin.DeleteInstancePartitionRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + return self._stubs["delete_instance_partition"] + + @property + def update_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.UpdateInstancePartitionRequest], + Awaitable[operations_pb2.Operation], + ]: + r"""Return a callable for the update instance partition method over gRPC. + + Updates an instance partition, and begins allocating or + releasing resources as requested. The returned [long-running + operation][google.longrunning.Operation] can be used to track + the progress of updating the instance partition. If the named + instance partition does not exist, returns ``NOT_FOUND``. + + Immediately upon completion of this request: + + - For resource types for which a decrease in the instance + partition's allocation has been requested, billing is based + on the newly-requested level. + + Until completion of the returned operation: + + - Cancelling the operation sets its metadata's + [cancel_time][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata.cancel_time], + and begins restoring resources to their pre-request values. + The operation is guaranteed to succeed at undoing all + resource changes, after which point it terminates with a + ``CANCELLED`` status. + - All other attempts to modify the instance partition are + rejected. + - Reading the instance partition via the API continues to give + the pre-request resource levels. + + Upon completion of the returned operation: + + - Billing begins for all successfully-allocated resources (some + types may have lower than the requested levels). + - All newly-reserved resources are available for serving the + instance partition's tables. + - The instance partition's new resource levels are readable via + the API. + + The returned [long-running + operation][google.longrunning.Operation] will have a name of the + format ``/operations/`` + and can be used to track the instance partition modification. + The [metadata][google.longrunning.Operation.metadata] field type + is + [UpdateInstancePartitionMetadata][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata]. + The [response][google.longrunning.Operation.response] field type + is + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], + if successful. + + Authorization requires ``spanner.instancePartitions.update`` + permission on the resource + [name][google.spanner.admin.instance.v1.InstancePartition.name]. + + Returns: + Callable[[~.UpdateInstancePartitionRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_instance_partition" not in self._stubs: + self._stubs["update_instance_partition"] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/UpdateInstancePartition", + request_serializer=spanner_instance_admin.UpdateInstancePartitionRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["update_instance_partition"] + + @property + def list_instance_partition_operations( + self, + ) -> Callable[ + [spanner_instance_admin.ListInstancePartitionOperationsRequest], + Awaitable[spanner_instance_admin.ListInstancePartitionOperationsResponse], + ]: + r"""Return a callable for the list instance partition + operations method over gRPC. + + Lists instance partition [long-running + operations][google.longrunning.Operation] in the given instance. + An instance partition operation has a name of the form + ``projects//instances//instancePartitions//operations/``. + The long-running operation + [metadata][google.longrunning.Operation.metadata] field type + ``metadata.type_url`` describes the type of the metadata. + Operations returned include those that have + completed/failed/canceled within the last 7 days, and pending + operations. Operations returned are ordered by + ``operation.metadata.value.start_time`` in descending order + starting from the most recently started operation. + + Authorization requires + ``spanner.instancePartitionOperations.list`` permission on the + resource + [parent][google.spanner.admin.instance.v1.ListInstancePartitionOperationsRequest.parent]. + + Returns: + Callable[[~.ListInstancePartitionOperationsRequest], + Awaitable[~.ListInstancePartitionOperationsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_instance_partition_operations" not in self._stubs: + self._stubs[ + "list_instance_partition_operations" + ] = self.grpc_channel.unary_unary( + "/google.spanner.admin.instance.v1.InstanceAdmin/ListInstancePartitionOperations", + request_serializer=spanner_instance_admin.ListInstancePartitionOperationsRequest.serialize, + response_deserializer=spanner_instance_admin.ListInstancePartitionOperationsResponse.deserialize, + ) + return self._stubs["list_instance_partition_operations"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.list_instance_configs: gapic_v1.method_async.wrap_method( + self.list_instance_configs, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.get_instance_config: gapic_v1.method_async.wrap_method( + self.get_instance_config, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.create_instance_config: gapic_v1.method_async.wrap_method( + self.create_instance_config, + default_timeout=None, + client_info=client_info, + ), + self.update_instance_config: gapic_v1.method_async.wrap_method( + self.update_instance_config, + default_timeout=None, + client_info=client_info, + ), + self.delete_instance_config: gapic_v1.method_async.wrap_method( + self.delete_instance_config, + default_timeout=None, + client_info=client_info, + ), + self.list_instance_config_operations: gapic_v1.method_async.wrap_method( + self.list_instance_config_operations, + default_timeout=None, + client_info=client_info, + ), + self.list_instances: gapic_v1.method_async.wrap_method( + self.list_instances, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.list_instance_partitions: gapic_v1.method_async.wrap_method( + self.list_instance_partitions, + default_timeout=None, + client_info=client_info, + ), + self.get_instance: gapic_v1.method_async.wrap_method( + self.get_instance, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.create_instance: gapic_v1.method_async.wrap_method( + self.create_instance, + default_timeout=3600.0, + client_info=client_info, + ), + self.update_instance: gapic_v1.method_async.wrap_method( + self.update_instance, + default_timeout=3600.0, + client_info=client_info, + ), + self.delete_instance: gapic_v1.method_async.wrap_method( + self.delete_instance, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.set_iam_policy: gapic_v1.method_async.wrap_method( + self.set_iam_policy, + default_timeout=30.0, + client_info=client_info, + ), + self.get_iam_policy: gapic_v1.method_async.wrap_method( + self.get_iam_policy, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.DeadlineExceeded, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.test_iam_permissions: gapic_v1.method_async.wrap_method( + self.test_iam_permissions, + default_timeout=30.0, + client_info=client_info, + ), + self.get_instance_partition: gapic_v1.method_async.wrap_method( + self.get_instance_partition, + default_timeout=None, + client_info=client_info, + ), + self.create_instance_partition: gapic_v1.method_async.wrap_method( + self.create_instance_partition, + default_timeout=None, + client_info=client_info, + ), + self.delete_instance_partition: gapic_v1.method_async.wrap_method( + self.delete_instance_partition, + default_timeout=None, + client_info=client_info, + ), + self.update_instance_partition: gapic_v1.method_async.wrap_method( + self.update_instance_partition, + default_timeout=None, + client_info=client_info, + ), + self.list_instance_partition_operations: gapic_v1.method_async.wrap_method( + self.list_instance_partition_operations, + default_timeout=None, + client_info=client_info, + ), + } + def close(self): return self.grpc_channel.close() diff --git a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest.py b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest.py index 2ba6d65087..ed152b4220 100644 --- a/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest.py +++ b/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -35,9 +35,9 @@ import warnings try: - OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] except AttributeError: # pragma: NO COVER - OptionalRetry = Union[retries.Retry, object] # type: ignore + OptionalRetry = Union[retries.Retry, object, None] # type: ignore from google.cloud.spanner_admin_instance_v1.types import spanner_instance_admin @@ -90,6 +90,14 @@ def post_create_instance_config(self, response): logging.log(f"Received response: {response}") return response + def pre_create_instance_partition(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_create_instance_partition(self, response): + logging.log(f"Received response: {response}") + return response + def pre_delete_instance(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -98,6 +106,10 @@ def pre_delete_instance_config(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata + def pre_delete_instance_partition(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + def pre_get_iam_policy(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -122,6 +134,14 @@ def post_get_instance_config(self, response): logging.log(f"Received response: {response}") return response + def pre_get_instance_partition(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_instance_partition(self, response): + logging.log(f"Received response: {response}") + return response + def pre_list_instance_config_operations(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -138,6 +158,22 @@ def post_list_instance_configs(self, response): logging.log(f"Received response: {response}") return response + def pre_list_instance_partition_operations(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_instance_partition_operations(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_list_instance_partitions(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_instance_partitions(self, response): + logging.log(f"Received response: {response}") + return response + def pre_list_instances(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -178,6 +214,14 @@ def post_update_instance_config(self, response): logging.log(f"Received response: {response}") return response + def pre_update_instance_partition(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_instance_partition(self, response): + logging.log(f"Received response: {response}") + return response + transport = InstanceAdminRestTransport(interceptor=MyCustomInstanceAdminInterceptor()) client = InstanceAdminClient(transport=transport) @@ -232,6 +276,31 @@ def post_create_instance_config( """ return response + def pre_create_instance_partition( + self, + request: spanner_instance_admin.CreateInstancePartitionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + spanner_instance_admin.CreateInstancePartitionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for create_instance_partition + + Override in a subclass to manipulate the request or metadata + before they are sent to the InstanceAdmin server. + """ + return request, metadata + + def post_create_instance_partition( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for create_instance_partition + + Override in a subclass to manipulate the response + after it is returned by the InstanceAdmin server but before + it is returned to user code. + """ + return response + def pre_delete_instance( self, request: spanner_instance_admin.DeleteInstanceRequest, @@ -258,6 +327,20 @@ def pre_delete_instance_config( """ return request, metadata + def pre_delete_instance_partition( + self, + request: spanner_instance_admin.DeleteInstancePartitionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + spanner_instance_admin.DeleteInstancePartitionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for delete_instance_partition + + Override in a subclass to manipulate the request or metadata + before they are sent to the InstanceAdmin server. + """ + return request, metadata + def pre_get_iam_policy( self, request: iam_policy_pb2.GetIamPolicyRequest, @@ -327,6 +410,31 @@ def post_get_instance_config( """ return response + def pre_get_instance_partition( + self, + request: spanner_instance_admin.GetInstancePartitionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + spanner_instance_admin.GetInstancePartitionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for get_instance_partition + + Override in a subclass to manipulate the request or metadata + before they are sent to the InstanceAdmin server. + """ + return request, metadata + + def post_get_instance_partition( + self, response: spanner_instance_admin.InstancePartition + ) -> spanner_instance_admin.InstancePartition: + """Post-rpc interceptor for get_instance_partition + + Override in a subclass to manipulate the response + after it is returned by the InstanceAdmin server but before + it is returned to user code. + """ + return response + def pre_list_instance_config_operations( self, request: spanner_instance_admin.ListInstanceConfigOperationsRequest, @@ -378,6 +486,57 @@ def post_list_instance_configs( """ return response + def pre_list_instance_partition_operations( + self, + request: spanner_instance_admin.ListInstancePartitionOperationsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + spanner_instance_admin.ListInstancePartitionOperationsRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for list_instance_partition_operations + + Override in a subclass to manipulate the request or metadata + before they are sent to the InstanceAdmin server. + """ + return request, metadata + + def post_list_instance_partition_operations( + self, response: spanner_instance_admin.ListInstancePartitionOperationsResponse + ) -> spanner_instance_admin.ListInstancePartitionOperationsResponse: + """Post-rpc interceptor for list_instance_partition_operations + + Override in a subclass to manipulate the response + after it is returned by the InstanceAdmin server but before + it is returned to user code. + """ + return response + + def pre_list_instance_partitions( + self, + request: spanner_instance_admin.ListInstancePartitionsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + spanner_instance_admin.ListInstancePartitionsRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for list_instance_partitions + + Override in a subclass to manipulate the request or metadata + before they are sent to the InstanceAdmin server. + """ + return request, metadata + + def post_list_instance_partitions( + self, response: spanner_instance_admin.ListInstancePartitionsResponse + ) -> spanner_instance_admin.ListInstancePartitionsResponse: + """Post-rpc interceptor for list_instance_partitions + + Override in a subclass to manipulate the response + after it is returned by the InstanceAdmin server but before + it is returned to user code. + """ + return response + def pre_list_instances( self, request: spanner_instance_admin.ListInstancesRequest, @@ -493,6 +652,31 @@ def post_update_instance_config( """ return response + def pre_update_instance_partition( + self, + request: spanner_instance_admin.UpdateInstancePartitionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + spanner_instance_admin.UpdateInstancePartitionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for update_instance_partition + + Override in a subclass to manipulate the request or metadata + before they are sent to the InstanceAdmin server. + """ + return request, metadata + + def post_update_instance_partition( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for update_instance_partition + + Override in a subclass to manipulate the response + after it is returned by the InstanceAdmin server but before + it is returned to user code. + """ + return response + @dataclasses.dataclass class InstanceAdminRestStub: @@ -555,7 +739,7 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -737,9 +921,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -748,7 +930,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -836,9 +1017,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -847,7 +1026,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -877,6 +1055,104 @@ def __call__( resp = self._interceptor.post_create_instance_config(resp) return resp + class _CreateInstancePartition(InstanceAdminRestStub): + def __hash__(self): + return hash("CreateInstancePartition") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: spanner_instance_admin.CreateInstancePartitionRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the create instance partition method over HTTP. + + Args: + request (~.spanner_instance_admin.CreateInstancePartitionRequest): + The request object. The request for + [CreateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.operations_pb2.Operation: + This resource represents a + long-running operation that is the + result of a network API call. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/{parent=projects/*/instances/*}/instancePartitions", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_create_instance_partition( + request, metadata + ) + pb_request = spanner_instance_admin.CreateInstancePartitionRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = operations_pb2.Operation() + json_format.Parse(response.content, resp, ignore_unknown_fields=True) + resp = self._interceptor.post_create_instance_partition(resp) + return resp + class _DeleteInstance(InstanceAdminRestStub): def __hash__(self): return hash("DeleteInstance") @@ -929,7 +1205,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1006,7 +1281,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1029,9 +1303,9 @@ def __call__( if response.status_code >= 400: raise core_exceptions.from_http_response(response) - class _GetIamPolicy(InstanceAdminRestStub): + class _DeleteInstancePartition(InstanceAdminRestStub): def __hash__(self): - return hash("GetIamPolicy") + return hash("DeleteInstancePartition") __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} @@ -1045,39 +1319,117 @@ def _get_unset_required_fields(cls, message_dict): def __call__( self, - request: iam_policy_pb2.GetIamPolicyRequest, + request: spanner_instance_admin.DeleteInstancePartitionRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ) -> policy_pb2.Policy: - r"""Call the get iam policy method over HTTP. + ): + r"""Call the delete instance partition method over HTTP. Args: - request (~.iam_policy_pb2.GetIamPolicyRequest): - The request object. Request message for ``GetIamPolicy`` method. + request (~.spanner_instance_admin.DeleteInstancePartitionRequest): + The request object. The request for + [DeleteInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstancePartition]. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. + """ - Returns: - ~.policy_pb2.Policy: - An Identity and Access Management (IAM) policy, which - specifies access controls for Google Cloud resources. + http_options: List[Dict[str, str]] = [ + { + "method": "delete", + "uri": "/v1/{name=projects/*/instances/*/instancePartitions/*}", + }, + ] + request, metadata = self._interceptor.pre_delete_instance_partition( + request, metadata + ) + pb_request = spanner_instance_admin.DeleteInstancePartitionRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) - A ``Policy`` is a collection of ``bindings``. A - ``binding`` binds one or more ``members``, or - principals, to a single ``role``. Principals can be user - accounts, service accounts, Google groups, and domains - (such as G Suite). A ``role`` is a named list of - permissions; each ``role`` can be an IAM predefined role - or a user-created custom role. + uri = transcoded_request["uri"] + method = transcoded_request["method"] - For some types of Google Cloud resources, a ``binding`` - can also specify a ``condition``, which is a logical - expression that allows access to a resource only if the + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + class _GetIamPolicy(InstanceAdminRestStub): + def __hash__(self): + return hash("GetIamPolicy") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: iam_policy_pb2.GetIamPolicyRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> policy_pb2.Policy: + r"""Call the get iam policy method over HTTP. + + Args: + request (~.iam_policy_pb2.GetIamPolicyRequest): + The request object. Request message for ``GetIamPolicy`` method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.policy_pb2.Policy: + An Identity and Access Management (IAM) policy, which + specifies access controls for Google Cloud resources. + + A ``Policy`` is a collection of ``bindings``. A + ``binding`` binds one or more ``members``, or + principals, to a single ``role``. Principals can be user + accounts, service accounts, Google groups, and domains + (such as G Suite). A ``role`` is a named list of + permissions; each ``role`` can be an IAM predefined role + or a user-created custom role. + + For some types of Google Cloud resources, a ``binding`` + can also specify a ``condition``, which is a logical + expression that allows access to a resource only if the expression evaluates to ``true``. A condition can add constraints based on attributes of the request, the resource, or both. To learn which resources support @@ -1156,9 +1508,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1167,7 +1517,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1192,16 +1541,288 @@ def __call__( raise core_exceptions.from_http_response(response) # Return the response - resp = policy_pb2.Policy() - pb_resp = resp + resp = policy_pb2.Policy() + pb_resp = resp + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_iam_policy(resp) + return resp + + class _GetInstance(InstanceAdminRestStub): + def __hash__(self): + return hash("GetInstance") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: spanner_instance_admin.GetInstanceRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> spanner_instance_admin.Instance: + r"""Call the get instance method over HTTP. + + Args: + request (~.spanner_instance_admin.GetInstanceRequest): + The request object. The request for + [GetInstance][google.spanner.admin.instance.v1.InstanceAdmin.GetInstance]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.spanner_instance_admin.Instance: + An isolated set of Cloud Spanner + resources on which databases can be + hosted. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{name=projects/*/instances/*}", + }, + ] + request, metadata = self._interceptor.pre_get_instance(request, metadata) + pb_request = spanner_instance_admin.GetInstanceRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = spanner_instance_admin.Instance() + pb_resp = spanner_instance_admin.Instance.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_instance(resp) + return resp + + class _GetInstanceConfig(InstanceAdminRestStub): + def __hash__(self): + return hash("GetInstanceConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: spanner_instance_admin.GetInstanceConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> spanner_instance_admin.InstanceConfig: + r"""Call the get instance config method over HTTP. + + Args: + request (~.spanner_instance_admin.GetInstanceConfigRequest): + The request object. The request for + [GetInstanceConfigRequest][google.spanner.admin.instance.v1.InstanceAdmin.GetInstanceConfig]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.spanner_instance_admin.InstanceConfig: + A possible configuration for a Cloud + Spanner instance. Configurations define + the geographic placement of nodes and + their replication. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{name=projects/*/instanceConfigs/*}", + }, + ] + request, metadata = self._interceptor.pre_get_instance_config( + request, metadata + ) + pb_request = spanner_instance_admin.GetInstanceConfigRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = spanner_instance_admin.InstanceConfig() + pb_resp = spanner_instance_admin.InstanceConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_instance_config(resp) + return resp + + class _GetInstancePartition(InstanceAdminRestStub): + def __hash__(self): + return hash("GetInstancePartition") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: spanner_instance_admin.GetInstancePartitionRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> spanner_instance_admin.InstancePartition: + r"""Call the get instance partition method over HTTP. + + Args: + request (~.spanner_instance_admin.GetInstancePartitionRequest): + The request object. The request for + [GetInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.GetInstancePartition]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.spanner_instance_admin.InstancePartition: + An isolated set of Cloud Spanner + resources that databases can define + placements on. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{name=projects/*/instances/*/instancePartitions/*}", + }, + ] + request, metadata = self._interceptor.pre_get_instance_partition( + request, metadata + ) + pb_request = spanner_instance_admin.GetInstancePartitionRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = spanner_instance_admin.InstancePartition() + pb_resp = spanner_instance_admin.InstancePartition.pb(resp) json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) - resp = self._interceptor.post_get_iam_policy(resp) + resp = self._interceptor.post_get_instance_partition(resp) return resp - class _GetInstance(InstanceAdminRestStub): + class _ListInstanceConfigOperations(InstanceAdminRestStub): def __hash__(self): - return hash("GetInstance") + return hash("ListInstanceConfigOperations") __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} @@ -1215,40 +1836,44 @@ def _get_unset_required_fields(cls, message_dict): def __call__( self, - request: spanner_instance_admin.GetInstanceRequest, + request: spanner_instance_admin.ListInstanceConfigOperationsRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ) -> spanner_instance_admin.Instance: - r"""Call the get instance method over HTTP. + ) -> spanner_instance_admin.ListInstanceConfigOperationsResponse: + r"""Call the list instance config + operations method over HTTP. - Args: - request (~.spanner_instance_admin.GetInstanceRequest): - The request object. The request for - [GetInstance][google.spanner.admin.instance.v1.InstanceAdmin.GetInstance]. - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. + Args: + request (~.spanner_instance_admin.ListInstanceConfigOperationsRequest): + The request object. The request for + [ListInstanceConfigOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. - Returns: - ~.spanner_instance_admin.Instance: - An isolated set of Cloud Spanner - resources on which databases can be - hosted. + Returns: + ~.spanner_instance_admin.ListInstanceConfigOperationsResponse: + The response for + [ListInstanceConfigOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations]. """ http_options: List[Dict[str, str]] = [ { "method": "get", - "uri": "/v1/{name=projects/*/instances/*}", + "uri": "/v1/{parent=projects/*}/instanceConfigOperations", }, ] - request, metadata = self._interceptor.pre_get_instance(request, metadata) - pb_request = spanner_instance_admin.GetInstanceRequest.pb(request) + request, metadata = self._interceptor.pre_list_instance_config_operations( + request, metadata + ) + pb_request = spanner_instance_admin.ListInstanceConfigOperationsRequest.pb( + request + ) transcoded_request = path_template.transcode(http_options, pb_request) uri = transcoded_request["uri"] @@ -1258,7 +1883,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1282,16 +1906,18 @@ def __call__( raise core_exceptions.from_http_response(response) # Return the response - resp = spanner_instance_admin.Instance() - pb_resp = spanner_instance_admin.Instance.pb(resp) + resp = spanner_instance_admin.ListInstanceConfigOperationsResponse() + pb_resp = spanner_instance_admin.ListInstanceConfigOperationsResponse.pb( + resp + ) json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) - resp = self._interceptor.post_get_instance(resp) + resp = self._interceptor.post_list_instance_config_operations(resp) return resp - class _GetInstanceConfig(InstanceAdminRestStub): + class _ListInstanceConfigs(InstanceAdminRestStub): def __hash__(self): - return hash("GetInstanceConfig") + return hash("ListInstanceConfigs") __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} @@ -1305,18 +1931,18 @@ def _get_unset_required_fields(cls, message_dict): def __call__( self, - request: spanner_instance_admin.GetInstanceConfigRequest, + request: spanner_instance_admin.ListInstanceConfigsRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ) -> spanner_instance_admin.InstanceConfig: - r"""Call the get instance config method over HTTP. + ) -> spanner_instance_admin.ListInstanceConfigsResponse: + r"""Call the list instance configs method over HTTP. Args: - request (~.spanner_instance_admin.GetInstanceConfigRequest): + request (~.spanner_instance_admin.ListInstanceConfigsRequest): The request object. The request for - [GetInstanceConfigRequest][google.spanner.admin.instance.v1.InstanceAdmin.GetInstanceConfig]. + [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs]. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -1324,24 +1950,22 @@ def __call__( sent along with the request as metadata. Returns: - ~.spanner_instance_admin.InstanceConfig: - A possible configuration for a Cloud - Spanner instance. Configurations define - the geographic placement of nodes and - their replication. + ~.spanner_instance_admin.ListInstanceConfigsResponse: + The response for + [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs]. """ http_options: List[Dict[str, str]] = [ { "method": "get", - "uri": "/v1/{name=projects/*/instanceConfigs/*}", + "uri": "/v1/{parent=projects/*}/instanceConfigs", }, ] - request, metadata = self._interceptor.pre_get_instance_config( + request, metadata = self._interceptor.pre_list_instance_configs( request, metadata ) - pb_request = spanner_instance_admin.GetInstanceConfigRequest.pb(request) + pb_request = spanner_instance_admin.ListInstanceConfigsRequest.pb(request) transcoded_request = path_template.transcode(http_options, pb_request) uri = transcoded_request["uri"] @@ -1351,7 +1975,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1375,16 +1998,16 @@ def __call__( raise core_exceptions.from_http_response(response) # Return the response - resp = spanner_instance_admin.InstanceConfig() - pb_resp = spanner_instance_admin.InstanceConfig.pb(resp) + resp = spanner_instance_admin.ListInstanceConfigsResponse() + pb_resp = spanner_instance_admin.ListInstanceConfigsResponse.pb(resp) json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) - resp = self._interceptor.post_get_instance_config(resp) + resp = self._interceptor.post_list_instance_configs(resp) return resp - class _ListInstanceConfigOperations(InstanceAdminRestStub): + class _ListInstancePartitionOperations(InstanceAdminRestStub): def __hash__(self): - return hash("ListInstanceConfigOperations") + return hash("ListInstancePartitionOperations") __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} @@ -1398,19 +2021,19 @@ def _get_unset_required_fields(cls, message_dict): def __call__( self, - request: spanner_instance_admin.ListInstanceConfigOperationsRequest, + request: spanner_instance_admin.ListInstancePartitionOperationsRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ) -> spanner_instance_admin.ListInstanceConfigOperationsResponse: - r"""Call the list instance config + ) -> spanner_instance_admin.ListInstancePartitionOperationsResponse: + r"""Call the list instance partition operations method over HTTP. Args: - request (~.spanner_instance_admin.ListInstanceConfigOperationsRequest): + request (~.spanner_instance_admin.ListInstancePartitionOperationsRequest): The request object. The request for - [ListInstanceConfigOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations]. + [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations]. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -1418,23 +2041,28 @@ def __call__( sent along with the request as metadata. Returns: - ~.spanner_instance_admin.ListInstanceConfigOperationsResponse: + ~.spanner_instance_admin.ListInstancePartitionOperationsResponse: The response for - [ListInstanceConfigOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations]. + [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations]. """ http_options: List[Dict[str, str]] = [ { "method": "get", - "uri": "/v1/{parent=projects/*}/instanceConfigOperations", + "uri": "/v1/{parent=projects/*/instances/*}/instancePartitionOperations", }, ] - request, metadata = self._interceptor.pre_list_instance_config_operations( + ( + request, + metadata, + ) = self._interceptor.pre_list_instance_partition_operations( request, metadata ) - pb_request = spanner_instance_admin.ListInstanceConfigOperationsRequest.pb( - request + pb_request = ( + spanner_instance_admin.ListInstancePartitionOperationsRequest.pb( + request + ) ) transcoded_request = path_template.transcode(http_options, pb_request) @@ -1445,7 +2073,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1469,18 +2096,18 @@ def __call__( raise core_exceptions.from_http_response(response) # Return the response - resp = spanner_instance_admin.ListInstanceConfigOperationsResponse() - pb_resp = spanner_instance_admin.ListInstanceConfigOperationsResponse.pb( + resp = spanner_instance_admin.ListInstancePartitionOperationsResponse() + pb_resp = spanner_instance_admin.ListInstancePartitionOperationsResponse.pb( resp ) json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) - resp = self._interceptor.post_list_instance_config_operations(resp) + resp = self._interceptor.post_list_instance_partition_operations(resp) return resp - class _ListInstanceConfigs(InstanceAdminRestStub): + class _ListInstancePartitions(InstanceAdminRestStub): def __hash__(self): - return hash("ListInstanceConfigs") + return hash("ListInstancePartitions") __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} @@ -1494,18 +2121,18 @@ def _get_unset_required_fields(cls, message_dict): def __call__( self, - request: spanner_instance_admin.ListInstanceConfigsRequest, + request: spanner_instance_admin.ListInstancePartitionsRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ) -> spanner_instance_admin.ListInstanceConfigsResponse: - r"""Call the list instance configs method over HTTP. + ) -> spanner_instance_admin.ListInstancePartitionsResponse: + r"""Call the list instance partitions method over HTTP. Args: - request (~.spanner_instance_admin.ListInstanceConfigsRequest): + request (~.spanner_instance_admin.ListInstancePartitionsRequest): The request object. The request for - [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs]. + [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions]. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -1513,22 +2140,24 @@ def __call__( sent along with the request as metadata. Returns: - ~.spanner_instance_admin.ListInstanceConfigsResponse: + ~.spanner_instance_admin.ListInstancePartitionsResponse: The response for - [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs]. + [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions]. """ http_options: List[Dict[str, str]] = [ { "method": "get", - "uri": "/v1/{parent=projects/*}/instanceConfigs", + "uri": "/v1/{parent=projects/*/instances/*}/instancePartitions", }, ] - request, metadata = self._interceptor.pre_list_instance_configs( + request, metadata = self._interceptor.pre_list_instance_partitions( request, metadata ) - pb_request = spanner_instance_admin.ListInstanceConfigsRequest.pb(request) + pb_request = spanner_instance_admin.ListInstancePartitionsRequest.pb( + request + ) transcoded_request = path_template.transcode(http_options, pb_request) uri = transcoded_request["uri"] @@ -1538,7 +2167,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1562,11 +2190,11 @@ def __call__( raise core_exceptions.from_http_response(response) # Return the response - resp = spanner_instance_admin.ListInstanceConfigsResponse() - pb_resp = spanner_instance_admin.ListInstanceConfigsResponse.pb(resp) + resp = spanner_instance_admin.ListInstancePartitionsResponse() + pb_resp = spanner_instance_admin.ListInstancePartitionsResponse.pb(resp) json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) - resp = self._interceptor.post_list_instance_configs(resp) + resp = self._interceptor.post_list_instance_partitions(resp) return resp class _ListInstances(InstanceAdminRestStub): @@ -1627,7 +2255,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1785,9 +2412,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1796,7 +2421,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1882,9 +2506,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1893,7 +2515,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1981,9 +2602,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1992,7 +2611,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2080,9 +2698,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -2091,7 +2707,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2121,6 +2736,104 @@ def __call__( resp = self._interceptor.post_update_instance_config(resp) return resp + class _UpdateInstancePartition(InstanceAdminRestStub): + def __hash__(self): + return hash("UpdateInstancePartition") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: spanner_instance_admin.UpdateInstancePartitionRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the update instance partition method over HTTP. + + Args: + request (~.spanner_instance_admin.UpdateInstancePartitionRequest): + The request object. The request for + [UpdateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.operations_pb2.Operation: + This resource represents a + long-running operation that is the + result of a network API call. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v1/{instance_partition.name=projects/*/instances/*/instancePartitions/*}", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_update_instance_partition( + request, metadata + ) + pb_request = spanner_instance_admin.UpdateInstancePartitionRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = operations_pb2.Operation() + json_format.Parse(response.content, resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_instance_partition(resp) + return resp + @property def create_instance( self, @@ -2141,6 +2854,17 @@ def create_instance_config( # In C++ this would require a dynamic_cast return self._CreateInstanceConfig(self._session, self._host, self._interceptor) # type: ignore + @property + def create_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.CreateInstancePartitionRequest], + operations_pb2.Operation, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._CreateInstancePartition(self._session, self._host, self._interceptor) # type: ignore + @property def delete_instance( self, @@ -2159,6 +2883,16 @@ def delete_instance_config( # In C++ this would require a dynamic_cast return self._DeleteInstanceConfig(self._session, self._host, self._interceptor) # type: ignore + @property + def delete_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.DeleteInstancePartitionRequest], empty_pb2.Empty + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._DeleteInstancePartition(self._session, self._host, self._interceptor) # type: ignore + @property def get_iam_policy( self, @@ -2188,6 +2922,17 @@ def get_instance_config( # In C++ this would require a dynamic_cast return self._GetInstanceConfig(self._session, self._host, self._interceptor) # type: ignore + @property + def get_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.GetInstancePartitionRequest], + spanner_instance_admin.InstancePartition, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._GetInstancePartition(self._session, self._host, self._interceptor) # type: ignore + @property def list_instance_config_operations( self, @@ -2210,6 +2955,28 @@ def list_instance_configs( # In C++ this would require a dynamic_cast return self._ListInstanceConfigs(self._session, self._host, self._interceptor) # type: ignore + @property + def list_instance_partition_operations( + self, + ) -> Callable[ + [spanner_instance_admin.ListInstancePartitionOperationsRequest], + spanner_instance_admin.ListInstancePartitionOperationsResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ListInstancePartitionOperations(self._session, self._host, self._interceptor) # type: ignore + + @property + def list_instance_partitions( + self, + ) -> Callable[ + [spanner_instance_admin.ListInstancePartitionsRequest], + spanner_instance_admin.ListInstancePartitionsResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ListInstancePartitions(self._session, self._host, self._interceptor) # type: ignore + @property def list_instances( self, @@ -2260,6 +3027,17 @@ def update_instance_config( # In C++ this would require a dynamic_cast return self._UpdateInstanceConfig(self._session, self._host, self._interceptor) # type: ignore + @property + def update_instance_partition( + self, + ) -> Callable[ + [spanner_instance_admin.UpdateInstancePartitionRequest], + operations_pb2.Operation, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._UpdateInstancePartition(self._session, self._host, self._interceptor) # type: ignore + @property def kind(self) -> str: return "rest" diff --git a/google/cloud/spanner_admin_instance_v1/types/__init__.py b/google/cloud/spanner_admin_instance_v1/types/__init__.py index b4eaac8066..a3d1028ce9 100644 --- a/google/cloud/spanner_admin_instance_v1/types/__init__.py +++ b/google/cloud/spanner_admin_instance_v1/types/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,54 +15,78 @@ # from .common import ( OperationProgress, + FulfillmentPeriod, ) from .spanner_instance_admin import ( AutoscalingConfig, CreateInstanceConfigMetadata, CreateInstanceConfigRequest, CreateInstanceMetadata, + CreateInstancePartitionMetadata, + CreateInstancePartitionRequest, CreateInstanceRequest, DeleteInstanceConfigRequest, + DeleteInstancePartitionRequest, DeleteInstanceRequest, GetInstanceConfigRequest, + GetInstancePartitionRequest, GetInstanceRequest, Instance, InstanceConfig, + InstancePartition, ListInstanceConfigOperationsRequest, ListInstanceConfigOperationsResponse, ListInstanceConfigsRequest, ListInstanceConfigsResponse, + ListInstancePartitionOperationsRequest, + ListInstancePartitionOperationsResponse, + ListInstancePartitionsRequest, + ListInstancePartitionsResponse, ListInstancesRequest, ListInstancesResponse, ReplicaInfo, UpdateInstanceConfigMetadata, UpdateInstanceConfigRequest, UpdateInstanceMetadata, + UpdateInstancePartitionMetadata, + UpdateInstancePartitionRequest, UpdateInstanceRequest, ) __all__ = ( "OperationProgress", + "FulfillmentPeriod", "AutoscalingConfig", "CreateInstanceConfigMetadata", "CreateInstanceConfigRequest", "CreateInstanceMetadata", + "CreateInstancePartitionMetadata", + "CreateInstancePartitionRequest", "CreateInstanceRequest", "DeleteInstanceConfigRequest", + "DeleteInstancePartitionRequest", "DeleteInstanceRequest", "GetInstanceConfigRequest", + "GetInstancePartitionRequest", "GetInstanceRequest", "Instance", "InstanceConfig", + "InstancePartition", "ListInstanceConfigOperationsRequest", "ListInstanceConfigOperationsResponse", "ListInstanceConfigsRequest", "ListInstanceConfigsResponse", + "ListInstancePartitionOperationsRequest", + "ListInstancePartitionOperationsResponse", + "ListInstancePartitionsRequest", + "ListInstancePartitionsResponse", "ListInstancesRequest", "ListInstancesResponse", "ReplicaInfo", "UpdateInstanceConfigMetadata", "UpdateInstanceConfigRequest", "UpdateInstanceMetadata", + "UpdateInstancePartitionMetadata", + "UpdateInstancePartitionRequest", "UpdateInstanceRequest", ) diff --git a/google/cloud/spanner_admin_instance_v1/types/common.py b/google/cloud/spanner_admin_instance_v1/types/common.py index e1b6734ff9..f404ee219d 100644 --- a/google/cloud/spanner_admin_instance_v1/types/common.py +++ b/google/cloud/spanner_admin_instance_v1/types/common.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -25,11 +25,30 @@ __protobuf__ = proto.module( package="google.spanner.admin.instance.v1", manifest={ + "FulfillmentPeriod", "OperationProgress", }, ) +class FulfillmentPeriod(proto.Enum): + r"""Indicates the expected fulfillment period of an operation. + + Values: + FULFILLMENT_PERIOD_UNSPECIFIED (0): + Not specified. + FULFILLMENT_PERIOD_NORMAL (1): + Normal fulfillment period. The operation is + expected to complete within minutes. + FULFILLMENT_PERIOD_EXTENDED (2): + Extended fulfillment period. It can take up + to an hour for the operation to complete. + """ + FULFILLMENT_PERIOD_UNSPECIFIED = 0 + FULFILLMENT_PERIOD_NORMAL = 1 + FULFILLMENT_PERIOD_EXTENDED = 2 + + class OperationProgress(proto.Message): r"""Encapsulates progress related information for a Cloud Spanner long running instance operations. diff --git a/google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py b/google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py index b4c18b85f2..171bf48618 100644 --- a/google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py +++ b/google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -50,6 +50,17 @@ "UpdateInstanceMetadata", "CreateInstanceConfigMetadata", "UpdateInstanceConfigMetadata", + "InstancePartition", + "CreateInstancePartitionMetadata", + "CreateInstancePartitionRequest", + "DeleteInstancePartitionRequest", + "GetInstancePartitionRequest", + "UpdateInstancePartitionRequest", + "UpdateInstancePartitionMetadata", + "ListInstancePartitionsRequest", + "ListInstancePartitionsResponse", + "ListInstancePartitionOperationsRequest", + "ListInstancePartitionOperationsResponse", }, ) @@ -1012,6 +1023,13 @@ class ListInstancesRequest(proto.Message): - ``name:howl labels.env:dev`` --> The instance's name contains "howl" and it has the label "env" with its value containing "dev". + instance_deadline (google.protobuf.timestamp_pb2.Timestamp): + Deadline used while retrieving metadata for instances. + Instances whose metadata cannot be retrieved within this + deadline will be added to + [unreachable][google.spanner.admin.instance.v1.ListInstancesResponse.unreachable] + in + [ListInstancesResponse][google.spanner.admin.instance.v1.ListInstancesResponse]. """ parent: str = proto.Field( @@ -1030,6 +1048,11 @@ class ListInstancesRequest(proto.Message): proto.STRING, number=4, ) + instance_deadline: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=5, + message=timestamp_pb2.Timestamp, + ) class ListInstancesResponse(proto.Message): @@ -1043,6 +1066,10 @@ class ListInstancesResponse(proto.Message): ``next_page_token`` can be sent in a subsequent [ListInstances][google.spanner.admin.instance.v1.InstanceAdmin.ListInstances] call to fetch more of the matching instances. + unreachable (MutableSequence[str]): + The list of unreachable instances. It includes the names of + instances whose metadata could not be retrieved within + [instance_deadline][google.spanner.admin.instance.v1.ListInstancesRequest.instance_deadline]. """ @property @@ -1058,6 +1085,10 @@ def raw_page(self): proto.STRING, number=2, ) + unreachable: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) class UpdateInstanceRequest(proto.Message): @@ -1127,6 +1158,9 @@ class CreateInstanceMetadata(proto.Message): end_time (google.protobuf.timestamp_pb2.Timestamp): The time at which this operation failed or was completed successfully. + expected_fulfillment_period (google.cloud.spanner_admin_instance_v1.types.FulfillmentPeriod): + The expected fulfillment period of this + create operation. """ instance: "Instance" = proto.Field( @@ -1149,6 +1183,11 @@ class CreateInstanceMetadata(proto.Message): number=4, message=timestamp_pb2.Timestamp, ) + expected_fulfillment_period: common.FulfillmentPeriod = proto.Field( + proto.ENUM, + number=5, + enum=common.FulfillmentPeriod, + ) class UpdateInstanceMetadata(proto.Message): @@ -1170,6 +1209,9 @@ class UpdateInstanceMetadata(proto.Message): end_time (google.protobuf.timestamp_pb2.Timestamp): The time at which this operation failed or was completed successfully. + expected_fulfillment_period (google.cloud.spanner_admin_instance_v1.types.FulfillmentPeriod): + The expected fulfillment period of this + update operation. """ instance: "Instance" = proto.Field( @@ -1192,6 +1234,11 @@ class UpdateInstanceMetadata(proto.Message): number=4, message=timestamp_pb2.Timestamp, ) + expected_fulfillment_period: common.FulfillmentPeriod = proto.Field( + proto.ENUM, + number=5, + enum=common.FulfillmentPeriod, + ) class CreateInstanceConfigMetadata(proto.Message): @@ -1260,4 +1307,595 @@ class UpdateInstanceConfigMetadata(proto.Message): ) +class InstancePartition(proto.Message): + r"""An isolated set of Cloud Spanner resources that databases can + define placements on. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + name (str): + Required. A unique identifier for the instance partition. + Values are of the form + ``projects//instances//instancePartitions/[a-z][-a-z0-9]*[a-z0-9]``. + The final segment of the name must be between 2 and 64 + characters in length. An instance partition's name cannot be + changed after the instance partition is created. + config (str): + Required. The name of the instance partition's + configuration. Values are of the form + ``projects//instanceConfigs/``. See + also + [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig] + and + [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs]. + display_name (str): + Required. The descriptive name for this + instance partition as it appears in UIs. Must be + unique per project and between 4 and 30 + characters in length. + node_count (int): + The number of nodes allocated to this instance partition. + + Users can set the node_count field to specify the target + number of nodes allocated to the instance partition. + + This may be zero in API responses for instance partitions + that are not yet in state ``READY``. + + This field is a member of `oneof`_ ``compute_capacity``. + processing_units (int): + The number of processing units allocated to this instance + partition. + + Users can set the processing_units field to specify the + target number of processing units allocated to the instance + partition. + + This may be zero in API responses for instance partitions + that are not yet in state ``READY``. + + This field is a member of `oneof`_ ``compute_capacity``. + state (google.cloud.spanner_admin_instance_v1.types.InstancePartition.State): + Output only. The current instance partition + state. + create_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time at which the instance + partition was created. + update_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time at which the instance + partition was most recently updated. + referencing_databases (MutableSequence[str]): + Output only. The names of the databases that + reference this instance partition. Referencing + databases should share the parent instance. The + existence of any referencing database prevents + the instance partition from being deleted. + referencing_backups (MutableSequence[str]): + Output only. The names of the backups that + reference this instance partition. Referencing + backups should share the parent instance. The + existence of any referencing backup prevents the + instance partition from being deleted. + etag (str): + Used for optimistic concurrency control as a + way to help prevent simultaneous updates of a + instance partition from overwriting each other. + It is strongly suggested that systems make use + of the etag in the read-modify-write cycle to + perform instance partition updates in order to + avoid race conditions: An etag is returned in + the response which contains instance partitions, + and systems are expected to put that etag in the + request to update instance partitions to ensure + that their change will be applied to the same + version of the instance partition. If no etag is + provided in the call to update instance + partition, then the existing instance partition + is overwritten blindly. + """ + + class State(proto.Enum): + r"""Indicates the current state of the instance partition. + + Values: + STATE_UNSPECIFIED (0): + Not specified. + CREATING (1): + The instance partition is still being + created. Resources may not be available yet, and + operations such as creating placements using + this instance partition may not work. + READY (2): + The instance partition is fully created and + ready to do work such as creating placements and + using in databases. + """ + STATE_UNSPECIFIED = 0 + CREATING = 1 + READY = 2 + + name: str = proto.Field( + proto.STRING, + number=1, + ) + config: str = proto.Field( + proto.STRING, + number=2, + ) + display_name: str = proto.Field( + proto.STRING, + number=3, + ) + node_count: int = proto.Field( + proto.INT32, + number=5, + oneof="compute_capacity", + ) + processing_units: int = proto.Field( + proto.INT32, + number=6, + oneof="compute_capacity", + ) + state: State = proto.Field( + proto.ENUM, + number=7, + enum=State, + ) + create_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=8, + message=timestamp_pb2.Timestamp, + ) + update_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=9, + message=timestamp_pb2.Timestamp, + ) + referencing_databases: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=10, + ) + referencing_backups: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=11, + ) + etag: str = proto.Field( + proto.STRING, + number=12, + ) + + +class CreateInstancePartitionMetadata(proto.Message): + r"""Metadata type for the operation returned by + [CreateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition]. + + Attributes: + instance_partition (google.cloud.spanner_admin_instance_v1.types.InstancePartition): + The instance partition being created. + start_time (google.protobuf.timestamp_pb2.Timestamp): + The time at which the + [CreateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition] + request was received. + cancel_time (google.protobuf.timestamp_pb2.Timestamp): + The time at which this operation was + cancelled. If set, this operation is in the + process of undoing itself (which is guaranteed + to succeed) and cannot be cancelled again. + end_time (google.protobuf.timestamp_pb2.Timestamp): + The time at which this operation failed or + was completed successfully. + """ + + instance_partition: "InstancePartition" = proto.Field( + proto.MESSAGE, + number=1, + message="InstancePartition", + ) + start_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=2, + message=timestamp_pb2.Timestamp, + ) + cancel_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=3, + message=timestamp_pb2.Timestamp, + ) + end_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=4, + message=timestamp_pb2.Timestamp, + ) + + +class CreateInstancePartitionRequest(proto.Message): + r"""The request for + [CreateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition]. + + Attributes: + parent (str): + Required. The name of the instance in which to create the + instance partition. Values are of the form + ``projects//instances/``. + instance_partition_id (str): + Required. The ID of the instance partition to create. Valid + identifiers are of the form ``[a-z][-a-z0-9]*[a-z0-9]`` and + must be between 2 and 64 characters in length. + instance_partition (google.cloud.spanner_admin_instance_v1.types.InstancePartition): + Required. The instance partition to create. The + instance_partition.name may be omitted, but if specified + must be + ``/instancePartitions/``. + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + instance_partition_id: str = proto.Field( + proto.STRING, + number=2, + ) + instance_partition: "InstancePartition" = proto.Field( + proto.MESSAGE, + number=3, + message="InstancePartition", + ) + + +class DeleteInstancePartitionRequest(proto.Message): + r"""The request for + [DeleteInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstancePartition]. + + Attributes: + name (str): + Required. The name of the instance partition to be deleted. + Values are of the form + ``projects/{project}/instances/{instance}/instancePartitions/{instance_partition}`` + etag (str): + Optional. If not empty, the API only deletes + the instance partition when the etag provided + matches the current status of the requested + instance partition. Otherwise, deletes the + instance partition without checking the current + status of the requested instance partition. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + etag: str = proto.Field( + proto.STRING, + number=2, + ) + + +class GetInstancePartitionRequest(proto.Message): + r"""The request for + [GetInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.GetInstancePartition]. + + Attributes: + name (str): + Required. The name of the requested instance partition. + Values are of the form + ``projects/{project}/instances/{instance}/instancePartitions/{instance_partition}``. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class UpdateInstancePartitionRequest(proto.Message): + r"""The request for + [UpdateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition]. + + Attributes: + instance_partition (google.cloud.spanner_admin_instance_v1.types.InstancePartition): + Required. The instance partition to update, which must + always include the instance partition name. Otherwise, only + fields mentioned in + [field_mask][google.spanner.admin.instance.v1.UpdateInstancePartitionRequest.field_mask] + need be included. + field_mask (google.protobuf.field_mask_pb2.FieldMask): + Required. A mask specifying which fields in + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition] + should be updated. The field mask must always be specified; + this prevents any future fields in + [InstancePartition][google.spanner.admin.instance.v1.InstancePartition] + from being erased accidentally by clients that do not know + about them. + """ + + instance_partition: "InstancePartition" = proto.Field( + proto.MESSAGE, + number=1, + message="InstancePartition", + ) + field_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + + +class UpdateInstancePartitionMetadata(proto.Message): + r"""Metadata type for the operation returned by + [UpdateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition]. + + Attributes: + instance_partition (google.cloud.spanner_admin_instance_v1.types.InstancePartition): + The desired end state of the update. + start_time (google.protobuf.timestamp_pb2.Timestamp): + The time at which + [UpdateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition] + request was received. + cancel_time (google.protobuf.timestamp_pb2.Timestamp): + The time at which this operation was + cancelled. If set, this operation is in the + process of undoing itself (which is guaranteed + to succeed) and cannot be cancelled again. + end_time (google.protobuf.timestamp_pb2.Timestamp): + The time at which this operation failed or + was completed successfully. + """ + + instance_partition: "InstancePartition" = proto.Field( + proto.MESSAGE, + number=1, + message="InstancePartition", + ) + start_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=2, + message=timestamp_pb2.Timestamp, + ) + cancel_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=3, + message=timestamp_pb2.Timestamp, + ) + end_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=4, + message=timestamp_pb2.Timestamp, + ) + + +class ListInstancePartitionsRequest(proto.Message): + r"""The request for + [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions]. + + Attributes: + parent (str): + Required. The instance whose instance partitions should be + listed. Values are of the form + ``projects//instances/``. + page_size (int): + Number of instance partitions to be returned + in the response. If 0 or less, defaults to the + server's maximum allowed page size. + page_token (str): + If non-empty, ``page_token`` should contain a + [next_page_token][google.spanner.admin.instance.v1.ListInstancePartitionsResponse.next_page_token] + from a previous + [ListInstancePartitionsResponse][google.spanner.admin.instance.v1.ListInstancePartitionsResponse]. + instance_partition_deadline (google.protobuf.timestamp_pb2.Timestamp): + Optional. Deadline used while retrieving metadata for + instance partitions. Instance partitions whose metadata + cannot be retrieved within this deadline will be added to + [unreachable][google.spanner.admin.instance.v1.ListInstancePartitionsResponse.unreachable] + in + [ListInstancePartitionsResponse][google.spanner.admin.instance.v1.ListInstancePartitionsResponse]. + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + page_size: int = proto.Field( + proto.INT32, + number=2, + ) + page_token: str = proto.Field( + proto.STRING, + number=3, + ) + instance_partition_deadline: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=4, + message=timestamp_pb2.Timestamp, + ) + + +class ListInstancePartitionsResponse(proto.Message): + r"""The response for + [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions]. + + Attributes: + instance_partitions (MutableSequence[google.cloud.spanner_admin_instance_v1.types.InstancePartition]): + The list of requested instancePartitions. + next_page_token (str): + ``next_page_token`` can be sent in a subsequent + [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions] + call to fetch more of the matching instance partitions. + unreachable (MutableSequence[str]): + The list of unreachable instance partitions. It includes the + names of instance partitions whose metadata could not be + retrieved within + [instance_partition_deadline][google.spanner.admin.instance.v1.ListInstancePartitionsRequest.instance_partition_deadline]. + """ + + @property + def raw_page(self): + return self + + instance_partitions: MutableSequence["InstancePartition"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="InstancePartition", + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + unreachable: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + + +class ListInstancePartitionOperationsRequest(proto.Message): + r"""The request for + [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations]. + + Attributes: + parent (str): + Required. The parent instance of the instance partition + operations. Values are of the form + ``projects//instances/``. + filter (str): + Optional. An expression that filters the list of returned + operations. + + A filter expression consists of a field name, a comparison + operator, and a value for filtering. The value must be a + string, a number, or a boolean. The comparison operator must + be one of: ``<``, ``>``, ``<=``, ``>=``, ``!=``, ``=``, or + ``:``. Colon ``:`` is the contains operator. Filter rules + are not case sensitive. + + The following fields in the + [Operation][google.longrunning.Operation] are eligible for + filtering: + + - ``name`` - The name of the long-running operation + - ``done`` - False if the operation is in progress, else + true. + - ``metadata.@type`` - the type of metadata. For example, + the type string for + [CreateInstancePartitionMetadata][google.spanner.admin.instance.v1.CreateInstancePartitionMetadata] + is + ``type.googleapis.com/google.spanner.admin.instance.v1.CreateInstancePartitionMetadata``. + - ``metadata.`` - any field in metadata.value. + ``metadata.@type`` must be specified first, if filtering + on metadata fields. + - ``error`` - Error associated with the long-running + operation. + - ``response.@type`` - the type of response. + - ``response.`` - any field in response.value. + + You can combine multiple expressions by enclosing each + expression in parentheses. By default, expressions are + combined with AND logic. However, you can specify AND, OR, + and NOT logic explicitly. + + Here are a few examples: + + - ``done:true`` - The operation is complete. + - ``(metadata.@type=`` + ``type.googleapis.com/google.spanner.admin.instance.v1.CreateInstancePartitionMetadata) AND`` + ``(metadata.instance_partition.name:custom-instance-partition) AND`` + ``(metadata.start_time < \"2021-03-28T14:50:00Z\") AND`` + ``(error:*)`` - Return operations where: + + - The operation's metadata type is + [CreateInstancePartitionMetadata][google.spanner.admin.instance.v1.CreateInstancePartitionMetadata]. + - The instance partition name contains + "custom-instance-partition". + - The operation started before 2021-03-28T14:50:00Z. + - The operation resulted in an error. + page_size (int): + Optional. Number of operations to be returned + in the response. If 0 or less, defaults to the + server's maximum allowed page size. + page_token (str): + Optional. If non-empty, ``page_token`` should contain a + [next_page_token][google.spanner.admin.instance.v1.ListInstancePartitionOperationsResponse.next_page_token] + from a previous + [ListInstancePartitionOperationsResponse][google.spanner.admin.instance.v1.ListInstancePartitionOperationsResponse] + to the same ``parent`` and with the same ``filter``. + instance_partition_deadline (google.protobuf.timestamp_pb2.Timestamp): + Optional. Deadline used while retrieving metadata for + instance partition operations. Instance partitions whose + operation metadata cannot be retrieved within this deadline + will be added to + [unreachable][ListInstancePartitionOperationsResponse.unreachable] + in + [ListInstancePartitionOperationsResponse][google.spanner.admin.instance.v1.ListInstancePartitionOperationsResponse]. + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + filter: str = proto.Field( + proto.STRING, + number=2, + ) + page_size: int = proto.Field( + proto.INT32, + number=3, + ) + page_token: str = proto.Field( + proto.STRING, + number=4, + ) + instance_partition_deadline: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=5, + message=timestamp_pb2.Timestamp, + ) + + +class ListInstancePartitionOperationsResponse(proto.Message): + r"""The response for + [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations]. + + Attributes: + operations (MutableSequence[google.longrunning.operations_pb2.Operation]): + The list of matching instance partition [long-running + operations][google.longrunning.Operation]. Each operation's + name will be prefixed by the instance partition's name. The + operation's + [metadata][google.longrunning.Operation.metadata] field type + ``metadata.type_url`` describes the type of the metadata. + next_page_token (str): + ``next_page_token`` can be sent in a subsequent + [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations] + call to fetch more of the matching metadata. + unreachable_instance_partitions (MutableSequence[str]): + The list of unreachable instance partitions. It includes the + names of instance partitions whose operation metadata could + not be retrieved within + [instance_partition_deadline][google.spanner.admin.instance.v1.ListInstancePartitionOperationsRequest.instance_partition_deadline]. + """ + + @property + def raw_page(self): + return self + + operations: MutableSequence[operations_pb2.Operation] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=operations_pb2.Operation, + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + unreachable_instance_partitions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/spanner_v1/services/__init__.py b/google/cloud/spanner_v1/services/__init__.py index 89a37dc92c..8f6cf06824 100644 --- a/google/cloud/spanner_v1/services/__init__.py +++ b/google/cloud/spanner_v1/services/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/services/spanner/__init__.py b/google/cloud/spanner_v1/services/spanner/__init__.py index b2130addc4..e8184d7477 100644 --- a/google/cloud/spanner_v1/services/spanner/__init__.py +++ b/google/cloud/spanner_v1/services/spanner/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/services/spanner/async_client.py b/google/cloud/spanner_v1/services/spanner/async_client.py index f4cd066bd9..d1c5827f47 100644 --- a/google/cloud/spanner_v1/services/spanner/async_client.py +++ b/google/cloud/spanner_v1/services/spanner/async_client.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ import re from typing import ( Dict, + Callable, Mapping, MutableMapping, MutableSequence, @@ -40,9 +41,9 @@ from google.oauth2 import service_account # type: ignore try: - OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault] + OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None] except AttributeError: # pragma: NO COVER - OptionalRetry = Union[retries.AsyncRetry, object] # type: ignore + OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore from google.cloud.spanner_v1.services.spanner import pagers from google.cloud.spanner_v1.types import commit_response @@ -67,8 +68,12 @@ class SpannerAsyncClient: _client: SpannerClient + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. DEFAULT_ENDPOINT = SpannerClient.DEFAULT_ENDPOINT DEFAULT_MTLS_ENDPOINT = SpannerClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = SpannerClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = SpannerClient._DEFAULT_UNIVERSE database_path = staticmethod(SpannerClient.database_path) parse_database_path = staticmethod(SpannerClient.parse_database_path) @@ -169,6 +174,25 @@ def transport(self) -> SpannerTransport: """ return self._client.transport + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + get_transport_class = functools.partial( type(SpannerClient).get_transport_class, type(SpannerClient) ) @@ -177,11 +201,13 @@ def __init__( self, *, credentials: Optional[ga_credentials.Credentials] = None, - transport: Union[str, SpannerTransport] = "grpc_asyncio", + transport: Optional[ + Union[str, SpannerTransport, Callable[..., SpannerTransport]] + ] = "grpc_asyncio", client_options: Optional[ClientOptions] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: - """Instantiates the spanner client. + """Instantiates the spanner async client. Args: credentials (Optional[google.auth.credentials.Credentials]): The @@ -189,26 +215,43 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.SpannerTransport]): The - transport to use. If set to None, a transport is chosen - automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. - (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT - environment variable can also be used to override the endpoint: + transport (Optional[Union[str,SpannerTransport,Callable[..., SpannerTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the SpannerTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint) and "auto" (auto switch to the - default mTLS endpoint if client certificate is present, this is - the default value). However, the ``api_endpoint`` property takes - precedence if provided. - (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable is "true", then the ``client_cert_source`` property can be used - to provide client certificate for mutual TLS transport. If + to provide a client certificate for mTLS transport. If not provided, the default SSL client certificate will be used if present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not set, no client certificate will be used. + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport creation failed for any reason. @@ -297,8 +340,8 @@ async def sample_create_session(): A session in the Cloud Spanner API. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database]) if request is not None and has_flattened_params: raise ValueError( @@ -306,7 +349,10 @@ async def sample_create_session(): "the individual field arguments should be set." ) - request = spanner.CreateSessionRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.CreateSessionRequest): + request = spanner.CreateSessionRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -315,20 +361,9 @@ async def sample_create_session(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.create_session, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_session + ] # Certain fields should be provided within the metadata header; # add these here. @@ -336,6 +371,9 @@ async def sample_create_session(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -426,8 +464,8 @@ async def sample_batch_create_sessions(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database, session_count]) if request is not None and has_flattened_params: raise ValueError( @@ -435,7 +473,10 @@ async def sample_batch_create_sessions(): "the individual field arguments should be set." ) - request = spanner.BatchCreateSessionsRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.BatchCreateSessionsRequest): + request = spanner.BatchCreateSessionsRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -446,20 +487,9 @@ async def sample_batch_create_sessions(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.batch_create_sessions, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=60.0, - ), - default_timeout=60.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.batch_create_sessions + ] # Certain fields should be provided within the metadata header; # add these here. @@ -467,6 +497,9 @@ async def sample_batch_create_sessions(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -539,8 +572,8 @@ async def sample_get_session(): A session in the Cloud Spanner API. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -548,7 +581,10 @@ async def sample_get_session(): "the individual field arguments should be set." ) - request = spanner.GetSessionRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.GetSessionRequest): + request = spanner.GetSessionRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -557,20 +593,9 @@ async def sample_get_session(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.get_session, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_session + ] # Certain fields should be provided within the metadata header; # add these here. @@ -578,6 +603,9 @@ async def sample_get_session(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -654,8 +682,8 @@ async def sample_list_sessions(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database]) if request is not None and has_flattened_params: raise ValueError( @@ -663,7 +691,10 @@ async def sample_list_sessions(): "the individual field arguments should be set." ) - request = spanner.ListSessionsRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.ListSessionsRequest): + request = spanner.ListSessionsRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -672,20 +703,9 @@ async def sample_list_sessions(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.list_sessions, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_sessions + ] # Certain fields should be provided within the metadata header; # add these here. @@ -693,6 +713,9 @@ async def sample_list_sessions(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -767,8 +790,8 @@ async def sample_delete_session(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -776,7 +799,10 @@ async def sample_delete_session(): "the individual field arguments should be set." ) - request = spanner.DeleteSessionRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.DeleteSessionRequest): + request = spanner.DeleteSessionRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -785,20 +811,9 @@ async def sample_delete_session(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.delete_session, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.delete_session + ] # Certain fields should be provided within the metadata header; # add these here. @@ -806,6 +821,9 @@ async def sample_delete_session(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. await rpc( request, @@ -882,24 +900,16 @@ async def sample_execute_sql(): """ # Create or coerce a protobuf request object. - request = spanner.ExecuteSqlRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.ExecuteSqlRequest): + request = spanner.ExecuteSqlRequest(request) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.execute_sql, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.execute_sql + ] # Certain fields should be provided within the metadata header; # add these here. @@ -907,6 +917,9 @@ async def sample_execute_sql(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -982,15 +995,16 @@ async def sample_execute_streaming_sql(): """ # Create or coerce a protobuf request object. - request = spanner.ExecuteSqlRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.ExecuteSqlRequest): + request = spanner.ExecuteSqlRequest(request) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.execute_streaming_sql, - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.execute_streaming_sql + ] # Certain fields should be provided within the metadata header; # add these here. @@ -998,6 +1012,9 @@ async def sample_execute_streaming_sql(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1120,24 +1137,16 @@ async def sample_execute_batch_dml(): """ # Create or coerce a protobuf request object. - request = spanner.ExecuteBatchDmlRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.ExecuteBatchDmlRequest): + request = spanner.ExecuteBatchDmlRequest(request) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.execute_batch_dml, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.execute_batch_dml + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1145,6 +1154,9 @@ async def sample_execute_batch_dml(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1226,24 +1238,14 @@ async def sample_read(): """ # Create or coerce a protobuf request object. - request = spanner.ReadRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.ReadRequest): + request = spanner.ReadRequest(request) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.read, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[self._client._transport.read] # Certain fields should be provided within the metadata header; # add these here. @@ -1251,6 +1253,9 @@ async def sample_read(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1327,15 +1332,16 @@ async def sample_streaming_read(): """ # Create or coerce a protobuf request object. - request = spanner.ReadRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.ReadRequest): + request = spanner.ReadRequest(request) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.streaming_read, - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.streaming_read + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1343,6 +1349,9 @@ async def sample_streaming_read(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1425,8 +1434,8 @@ async def sample_begin_transaction(): A transaction. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([session, options]) if request is not None and has_flattened_params: raise ValueError( @@ -1434,7 +1443,10 @@ async def sample_begin_transaction(): "the individual field arguments should be set." ) - request = spanner.BeginTransactionRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.BeginTransactionRequest): + request = spanner.BeginTransactionRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1445,20 +1457,9 @@ async def sample_begin_transaction(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.begin_transaction, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.begin_transaction + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1466,6 +1467,9 @@ async def sample_begin_transaction(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1588,8 +1592,8 @@ async def sample_commit(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any( [session, transaction_id, mutations, single_use_transaction] ) @@ -1599,7 +1603,10 @@ async def sample_commit(): "the individual field arguments should be set." ) - request = spanner.CommitRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.CommitRequest): + request = spanner.CommitRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1614,20 +1621,7 @@ async def sample_commit(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.commit, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=3600.0, - ), - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[self._client._transport.commit] # Certain fields should be provided within the metadata header; # add these here. @@ -1635,6 +1629,9 @@ async def sample_commit(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1716,8 +1713,8 @@ async def sample_rollback(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([session, transaction_id]) if request is not None and has_flattened_params: raise ValueError( @@ -1725,7 +1722,10 @@ async def sample_rollback(): "the individual field arguments should be set." ) - request = spanner.RollbackRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.RollbackRequest): + request = spanner.RollbackRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -1736,20 +1736,7 @@ async def sample_rollback(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.rollback, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[self._client._transport.rollback] # Certain fields should be provided within the metadata header; # add these here. @@ -1757,6 +1744,9 @@ async def sample_rollback(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. await rpc( request, @@ -1833,24 +1823,16 @@ async def sample_partition_query(): """ # Create or coerce a protobuf request object. - request = spanner.PartitionQueryRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.PartitionQueryRequest): + request = spanner.PartitionQueryRequest(request) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.partition_query, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.partition_query + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1858,6 +1840,9 @@ async def sample_partition_query(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -1940,24 +1925,16 @@ async def sample_partition_read(): """ # Create or coerce a protobuf request object. - request = spanner.PartitionReadRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.PartitionReadRequest): + request = spanner.PartitionReadRequest(request) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.partition_read, - default_retry=retries.AsyncRetry( - initial=0.25, - maximum=32.0, - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=30.0, - ), - default_timeout=30.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.partition_read + ] # Certain fields should be provided within the metadata header; # add these here. @@ -1965,6 +1942,9 @@ async def sample_partition_read(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = await rpc( request, @@ -2070,8 +2050,8 @@ async def sample_batch_write(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([session, mutation_groups]) if request is not None and has_flattened_params: raise ValueError( @@ -2079,7 +2059,10 @@ async def sample_batch_write(): "the individual field arguments should be set." ) - request = spanner.BatchWriteRequest(request) + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, spanner.BatchWriteRequest): + request = spanner.BatchWriteRequest(request) # If we have keyword arguments corresponding to fields on the # request, apply these. @@ -2090,11 +2073,9 @@ async def sample_batch_write(): # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. - rpc = gapic_v1.method_async.wrap_method( - self._client._transport.batch_write, - default_timeout=3600.0, - client_info=DEFAULT_CLIENT_INFO, - ) + rpc = self._client._transport._wrapped_methods[ + self._client._transport.batch_write + ] # Certain fields should be provided within the metadata header; # add these here. @@ -2102,6 +2083,9 @@ async def sample_batch_write(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._client._validate_universe_domain() + # Send the request. response = rpc( request, diff --git a/google/cloud/spanner_v1/services/spanner/client.py b/google/cloud/spanner_v1/services/spanner/client.py index 28f203fff7..15a9eb45d6 100644 --- a/google/cloud/spanner_v1/services/spanner/client.py +++ b/google/cloud/spanner_v1/services/spanner/client.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ import re from typing import ( Dict, + Callable, Mapping, MutableMapping, MutableSequence, @@ -29,6 +30,7 @@ Union, cast, ) +import warnings from google.cloud.spanner_v1 import gapic_version as package_version @@ -43,9 +45,9 @@ from google.oauth2 import service_account # type: ignore try: - OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] except AttributeError: # pragma: NO COVER - OptionalRetry = Union[retries.Retry, object] # type: ignore + OptionalRetry = Union[retries.Retry, object, None] # type: ignore from google.cloud.spanner_v1.services.spanner import pagers from google.cloud.spanner_v1.types import commit_response @@ -134,11 +136,15 @@ def _get_default_mtls_endpoint(api_endpoint): return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. DEFAULT_ENDPOINT = "spanner.googleapis.com" DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore DEFAULT_ENDPOINT ) + _DEFAULT_ENDPOINT_TEMPLATE = "spanner.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + @classmethod def from_service_account_info(cls, info: dict, *args, **kwargs): """Creates an instance of this client using the provided credentials @@ -313,7 +319,7 @@ def parse_common_location_path(path: str) -> Dict[str, str]: def get_mtls_endpoint_and_cert_source( cls, client_options: Optional[client_options_lib.ClientOptions] = None ): - """Return the API endpoint and client cert source for mutual TLS. + """Deprecated. Return the API endpoint and client cert source for mutual TLS. The client cert source is determined in the following order: (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the @@ -343,6 +349,11 @@ def get_mtls_endpoint_and_cert_source( Raises: google.auth.exceptions.MutualTLSChannelError: If any errors happen. """ + + warnings.warn( + "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", + DeprecationWarning, + ) if client_options is None: client_options = client_options_lib.ClientOptions() use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") @@ -376,11 +387,185 @@ def get_mtls_endpoint_and_cert_source( return api_endpoint, client_cert_source + @staticmethod + def _read_environment_variables(): + """Returns the environment variables used by the client. + + Returns: + Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, + GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. + + Raises: + ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not + any of ["true", "false"]. + google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT + is not any of ["auto", "never", "always"]. + """ + use_client_cert = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + return use_client_cert == "true", use_mtls_endpoint, universe_domain_env + + @staticmethod + def _get_client_cert_source(provided_cert_source, use_cert_flag): + """Return the client cert source to be used by the client. + + Args: + provided_cert_source (bytes): The client certificate source provided. + use_cert_flag (bool): A flag indicating whether to use the client certificate. + + Returns: + bytes or None: The client cert source to be used by the client. + """ + client_cert_source = None + if use_cert_flag: + if provided_cert_source: + client_cert_source = provided_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + return client_cert_source + + @staticmethod + def _get_api_endpoint( + api_override, client_cert_source, universe_domain, use_mtls_endpoint + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = SpannerClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = SpannerClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = SpannerClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], universe_domain_env: Optional[str] + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = SpannerClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + @staticmethod + def _compare_universes( + client_universe: str, credentials: ga_credentials.Credentials + ) -> bool: + """Returns True iff the universe domains used by the client and credentials match. + + Args: + client_universe (str): The universe domain configured via the client options. + credentials (ga_credentials.Credentials): The credentials being used in the client. + + Returns: + bool: True iff client_universe matches the universe in credentials. + + Raises: + ValueError: when client_universe does not match the universe in credentials. + """ + + default_universe = SpannerClient._DEFAULT_UNIVERSE + credentials_universe = getattr(credentials, "universe_domain", default_universe) + + if client_universe != credentials_universe: + raise ValueError( + "The configured universe domain " + f"({client_universe}) does not match the universe domain " + f"found in the credentials ({credentials_universe}). " + "If you haven't configured the universe domain explicitly, " + f"`{default_universe}` is the default." + ) + return True + + def _validate_universe_domain(self): + """Validates client's and credentials' universe domains are consistent. + + Returns: + bool: True iff the configured universe domain is valid. + + Raises: + ValueError: If the configured universe domain is not valid. + """ + self._is_universe_domain_valid = ( + self._is_universe_domain_valid + or SpannerClient._compare_universes( + self.universe_domain, self.transport._credentials + ) + ) + return self._is_universe_domain_valid + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + def __init__( self, *, credentials: Optional[ga_credentials.Credentials] = None, - transport: Optional[Union[str, SpannerTransport]] = None, + transport: Optional[ + Union[str, SpannerTransport, Callable[..., SpannerTransport]] + ] = None, client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -392,25 +577,37 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, SpannerTransport]): The - transport to use. If set to None, a transport is chosen - automatically. - client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the - client. It won't take effect if a ``transport`` instance is provided. - (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT - environment variable can also be used to override the endpoint: + transport (Optional[Union[str,SpannerTransport,Callable[..., SpannerTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the SpannerTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint) and "auto" (auto switch to the - default mTLS endpoint if client certificate is present, this is - the default value). However, the ``api_endpoint`` property takes - precedence if provided. - (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable is "true", then the ``client_cert_source`` property can be used - to provide client certificate for mutual TLS transport. If + to provide a client certificate for mTLS transport. If not provided, the default SSL client certificate will be used if present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): The client info used to send a user-agent string along with API requests. If ``None``, then default info will be used. @@ -421,17 +618,34 @@ def __init__( google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ - if isinstance(client_options, dict): - client_options = client_options_lib.from_dict(client_options) - if client_options is None: - client_options = client_options_lib.ClientOptions() - client_options = cast(client_options_lib.ClientOptions, client_options) + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr(self._client_options, "universe_domain", None) - api_endpoint, client_cert_source_func = self.get_mtls_endpoint_and_cert_source( - client_options + ( + self._use_client_cert, + self._use_mtls_endpoint, + self._universe_domain_env, + ) = SpannerClient._read_environment_variables() + self._client_cert_source = SpannerClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = SpannerClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env ) + self._api_endpoint = None # updated below, depending on `transport` - api_key_value = getattr(client_options, "api_key", None) + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + api_key_value = getattr(self._client_options, "api_key", None) if api_key_value and credentials: raise ValueError( "client_options.api_key and credentials are mutually exclusive" @@ -440,20 +654,30 @@ def __init__( # Save or instantiate the transport. # Ordinarily, we provide the transport, but allowing a custom transport # instance provides an extensibility point for unusual situations. - if isinstance(transport, SpannerTransport): + transport_provided = isinstance(transport, SpannerTransport) + if transport_provided: # transport is a SpannerTransport instance. - if credentials or client_options.credentials_file or api_key_value: + if credentials or self._client_options.credentials_file or api_key_value: raise ValueError( "When providing a transport instance, " "provide its credentials directly." ) - if client_options.scopes: + if self._client_options.scopes: raise ValueError( "When providing a transport instance, provide its scopes " "directly." ) - self._transport = transport - else: + self._transport = cast(SpannerTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = self._api_endpoint or SpannerClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + + if not transport_provided: import google.auth._default # type: ignore if api_key_value and hasattr( @@ -463,17 +687,24 @@ def __init__( api_key_value ) - Transport = type(self).get_transport_class(transport) - self._transport = Transport( + transport_init: Union[ + Type[SpannerTransport], Callable[..., SpannerTransport] + ] = ( + type(self).get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., SpannerTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( credentials=credentials, - credentials_file=client_options.credentials_file, - host=api_endpoint, - scopes=client_options.scopes, - client_cert_source_for_mtls=client_cert_source_func, - quota_project_id=client_options.quota_project_id, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, client_info=client_info, always_use_jwt_access=True, - api_audience=client_options.api_audience, + api_audience=self._client_options.api_audience, ) def create_session( @@ -553,8 +784,8 @@ def sample_create_session(): A session in the Cloud Spanner API. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database]) if request is not None and has_flattened_params: raise ValueError( @@ -562,10 +793,8 @@ def sample_create_session(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner.CreateSessionRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.CreateSessionRequest): request = spanner.CreateSessionRequest(request) # If we have keyword arguments corresponding to fields on the @@ -583,6 +812,9 @@ def sample_create_session(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -673,8 +905,8 @@ def sample_batch_create_sessions(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database, session_count]) if request is not None and has_flattened_params: raise ValueError( @@ -682,10 +914,8 @@ def sample_batch_create_sessions(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner.BatchCreateSessionsRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.BatchCreateSessionsRequest): request = spanner.BatchCreateSessionsRequest(request) # If we have keyword arguments corresponding to fields on the @@ -705,6 +935,9 @@ def sample_batch_create_sessions(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -777,8 +1010,8 @@ def sample_get_session(): A session in the Cloud Spanner API. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -786,10 +1019,8 @@ def sample_get_session(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner.GetSessionRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.GetSessionRequest): request = spanner.GetSessionRequest(request) # If we have keyword arguments corresponding to fields on the @@ -807,6 +1038,9 @@ def sample_get_session(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -883,8 +1117,8 @@ def sample_list_sessions(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([database]) if request is not None and has_flattened_params: raise ValueError( @@ -892,10 +1126,8 @@ def sample_list_sessions(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner.ListSessionsRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.ListSessionsRequest): request = spanner.ListSessionsRequest(request) # If we have keyword arguments corresponding to fields on the @@ -913,6 +1145,9 @@ def sample_list_sessions(): gapic_v1.routing_header.to_grpc_metadata((("database", request.database),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -987,8 +1222,8 @@ def sample_delete_session(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([name]) if request is not None and has_flattened_params: raise ValueError( @@ -996,10 +1231,8 @@ def sample_delete_session(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner.DeleteSessionRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.DeleteSessionRequest): request = spanner.DeleteSessionRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1017,6 +1250,9 @@ def sample_delete_session(): gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. rpc( request, @@ -1093,10 +1329,8 @@ def sample_execute_sql(): """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes - # in a spanner.ExecuteSqlRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.ExecuteSqlRequest): request = spanner.ExecuteSqlRequest(request) @@ -1110,6 +1344,9 @@ def sample_execute_sql(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1185,10 +1422,8 @@ def sample_execute_streaming_sql(): """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes - # in a spanner.ExecuteSqlRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.ExecuteSqlRequest): request = spanner.ExecuteSqlRequest(request) @@ -1202,6 +1437,9 @@ def sample_execute_streaming_sql(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1324,10 +1562,8 @@ def sample_execute_batch_dml(): """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes - # in a spanner.ExecuteBatchDmlRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.ExecuteBatchDmlRequest): request = spanner.ExecuteBatchDmlRequest(request) @@ -1341,6 +1577,9 @@ def sample_execute_batch_dml(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1422,10 +1661,8 @@ def sample_read(): """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes - # in a spanner.ReadRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.ReadRequest): request = spanner.ReadRequest(request) @@ -1439,6 +1676,9 @@ def sample_read(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1515,10 +1755,8 @@ def sample_streaming_read(): """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes - # in a spanner.ReadRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.ReadRequest): request = spanner.ReadRequest(request) @@ -1532,6 +1770,9 @@ def sample_streaming_read(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1614,8 +1855,8 @@ def sample_begin_transaction(): A transaction. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([session, options]) if request is not None and has_flattened_params: raise ValueError( @@ -1623,10 +1864,8 @@ def sample_begin_transaction(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner.BeginTransactionRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.BeginTransactionRequest): request = spanner.BeginTransactionRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1646,6 +1885,9 @@ def sample_begin_transaction(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1768,8 +2010,8 @@ def sample_commit(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any( [session, transaction_id, mutations, single_use_transaction] ) @@ -1779,10 +2021,8 @@ def sample_commit(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner.CommitRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.CommitRequest): request = spanner.CommitRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1806,6 +2046,9 @@ def sample_commit(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -1887,8 +2130,8 @@ def sample_rollback(): sent along with the request as metadata. """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([session, transaction_id]) if request is not None and has_flattened_params: raise ValueError( @@ -1896,10 +2139,8 @@ def sample_rollback(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner.RollbackRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.RollbackRequest): request = spanner.RollbackRequest(request) # If we have keyword arguments corresponding to fields on the @@ -1919,6 +2160,9 @@ def sample_rollback(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. rpc( request, @@ -1995,10 +2239,8 @@ def sample_partition_query(): """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes - # in a spanner.PartitionQueryRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.PartitionQueryRequest): request = spanner.PartitionQueryRequest(request) @@ -2012,6 +2254,9 @@ def sample_partition_query(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2094,10 +2339,8 @@ def sample_partition_read(): """ # Create or coerce a protobuf request object. - # Minor optimization to avoid making a copy if the user passes - # in a spanner.PartitionReadRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.PartitionReadRequest): request = spanner.PartitionReadRequest(request) @@ -2111,6 +2354,9 @@ def sample_partition_read(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, @@ -2216,8 +2462,8 @@ def sample_batch_write(): """ # Create or coerce a protobuf request object. - # Quick check: If we got a request object, we should *not* have - # gotten any keyword arguments that map to the request. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. has_flattened_params = any([session, mutation_groups]) if request is not None and has_flattened_params: raise ValueError( @@ -2225,10 +2471,8 @@ def sample_batch_write(): "the individual field arguments should be set." ) - # Minor optimization to avoid making a copy if the user passes - # in a spanner.BatchWriteRequest. - # There's no risk of modifying the input as we've already verified - # there are no flattened fields. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. if not isinstance(request, spanner.BatchWriteRequest): request = spanner.BatchWriteRequest(request) # If we have keyword arguments corresponding to fields on the @@ -2248,6 +2492,9 @@ def sample_batch_write(): gapic_v1.routing_header.to_grpc_metadata((("session", request.session),)), ) + # Validate the universe domain. + self._validate_universe_domain() + # Send the request. response = rpc( request, diff --git a/google/cloud/spanner_v1/services/spanner/pagers.py b/google/cloud/spanner_v1/services/spanner/pagers.py index e537ef3b8f..506de51067 100644 --- a/google/cloud/spanner_v1/services/spanner/pagers.py +++ b/google/cloud/spanner_v1/services/spanner/pagers.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/services/spanner/transports/__init__.py b/google/cloud/spanner_v1/services/spanner/transports/__init__.py index 188e4d2d6a..e554f96a50 100644 --- a/google/cloud/spanner_v1/services/spanner/transports/__init__.py +++ b/google/cloud/spanner_v1/services/spanner/transports/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/services/spanner/transports/base.py b/google/cloud/spanner_v1/services/spanner/transports/base.py index 27006d8fbc..73fdbcffa2 100644 --- a/google/cloud/spanner_v1/services/spanner/transports/base.py +++ b/google/cloud/spanner_v1/services/spanner/transports/base.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -64,7 +64,7 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -127,6 +127,10 @@ def __init__( host += ":443" self._host = host + @property + def host(self): + return self._host + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -137,6 +141,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, @@ -151,6 +156,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=60.0, @@ -165,6 +171,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, @@ -179,6 +186,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=3600.0, @@ -193,6 +201,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, @@ -207,6 +216,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, @@ -226,6 +236,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, @@ -240,6 +251,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, @@ -259,6 +271,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, @@ -273,6 +286,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=3600.0, @@ -287,6 +301,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, @@ -301,6 +316,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, @@ -315,6 +331,7 @@ def _prep_wrapped_messages(self, client_info): maximum=32.0, multiplier=1.3, predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, core_exceptions.ServiceUnavailable, ), deadline=30.0, diff --git a/google/cloud/spanner_v1/services/spanner/transports/grpc.py b/google/cloud/spanner_v1/services/spanner/transports/grpc.py index 86d9ba4133..9293258ea4 100644 --- a/google/cloud/spanner_v1/services/spanner/transports/grpc.py +++ b/google/cloud/spanner_v1/services/spanner/transports/grpc.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -57,7 +57,7 @@ def __init__( credentials: Optional[ga_credentials.Credentials] = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, - channel: Optional[grpc.Channel] = None, + channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None, api_mtls_endpoint: Optional[str] = None, client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, @@ -71,20 +71,23 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. scopes (Optional(Sequence[str])): A list of scopes. This argument is - ignored if ``channel`` is provided. - channel (Optional[grpc.Channel]): A ``Channel`` instance through - which to make calls. + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from @@ -94,11 +97,11 @@ def __init__( private key bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials - for the grpc channel. It is ignored if ``channel`` is provided. + for the grpc channel. It is ignored if a ``channel`` instance is provided. client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): A callback to provide client certificate bytes and private key bytes, both in PEM format. It is used to configure a mutual TLS channel. It is - ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -124,7 +127,7 @@ def __init__( if client_cert_source: warnings.warn("client_cert_source is deprecated", DeprecationWarning) - if channel: + if isinstance(channel, grpc.Channel): # Ignore credentials if a channel was passed. credentials = False # If a channel was explicitly provided, set it. @@ -165,7 +168,9 @@ def __init__( ) if not self._grpc_channel: - self._grpc_channel = type(self).create_channel( + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( self._host, # use the credentials which are saved credentials=self._credentials, diff --git a/google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py b/google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py index d0755e3a67..25b5ae1866 100644 --- a/google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py +++ b/google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers_async +from google.api_core import exceptions as core_exceptions +from google.api_core import retry_async as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -72,7 +74,6 @@ def create_channel( the credentials from the environment. credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. scopes (Optional[Sequence[str]]): A optional list of scopes needed for this service. These are only used when credentials are not specified and are passed to :func:`google.auth.default`. @@ -102,7 +103,7 @@ def __init__( credentials: Optional[ga_credentials.Credentials] = None, credentials_file: Optional[str] = None, scopes: Optional[Sequence[str]] = None, - channel: Optional[aio.Channel] = None, + channel: Optional[Union[aio.Channel, Callable[..., aio.Channel]]] = None, api_mtls_endpoint: Optional[str] = None, client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, @@ -116,21 +117,24 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. credentials_file (Optional[str]): A file with credentials that can be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. + This argument is ignored if a ``channel`` instance is provided. scopes (Optional[Sequence[str]]): A optional list of scopes needed for this service. These are only used when credentials are not specified and are passed to :func:`google.auth.default`. - channel (Optional[aio.Channel]): A ``Channel`` instance through - which to make calls. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from @@ -140,11 +144,11 @@ def __init__( private key bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials - for the grpc channel. It is ignored if ``channel`` is provided. + for the grpc channel. It is ignored if a ``channel`` instance is provided. client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): A callback to provide client certificate bytes and private key bytes, both in PEM format. It is used to configure a mutual TLS channel. It is - ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -170,7 +174,7 @@ def __init__( if client_cert_source: warnings.warn("client_cert_source is deprecated", DeprecationWarning) - if channel: + if isinstance(channel, aio.Channel): # Ignore credentials if a channel was passed. credentials = False # If a channel was explicitly provided, set it. @@ -210,7 +214,9 @@ def __init__( ) if not self._grpc_channel: - self._grpc_channel = type(self).create_channel( + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( self._host, # use the credentials which are saved credentials=self._credentials, @@ -815,6 +821,221 @@ def batch_write( ) return self._stubs["batch_write"] + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.create_session: gapic_v1.method_async.wrap_method( + self.create_session, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.batch_create_sessions: gapic_v1.method_async.wrap_method( + self.batch_create_sessions, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=60.0, + ), + default_timeout=60.0, + client_info=client_info, + ), + self.get_session: gapic_v1.method_async.wrap_method( + self.get_session, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.list_sessions: gapic_v1.method_async.wrap_method( + self.list_sessions, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.delete_session: gapic_v1.method_async.wrap_method( + self.delete_session, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.execute_sql: gapic_v1.method_async.wrap_method( + self.execute_sql, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.execute_streaming_sql: gapic_v1.method_async.wrap_method( + self.execute_streaming_sql, + default_timeout=3600.0, + client_info=client_info, + ), + self.execute_batch_dml: gapic_v1.method_async.wrap_method( + self.execute_batch_dml, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.read: gapic_v1.method_async.wrap_method( + self.read, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.streaming_read: gapic_v1.method_async.wrap_method( + self.streaming_read, + default_timeout=3600.0, + client_info=client_info, + ), + self.begin_transaction: gapic_v1.method_async.wrap_method( + self.begin_transaction, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.commit: gapic_v1.method_async.wrap_method( + self.commit, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=3600.0, + ), + default_timeout=3600.0, + client_info=client_info, + ), + self.rollback: gapic_v1.method_async.wrap_method( + self.rollback, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.partition_query: gapic_v1.method_async.wrap_method( + self.partition_query, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.partition_read: gapic_v1.method_async.wrap_method( + self.partition_read, + default_retry=retries.AsyncRetry( + initial=0.25, + maximum=32.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ResourceExhausted, + core_exceptions.ServiceUnavailable, + ), + deadline=30.0, + ), + default_timeout=30.0, + client_info=client_info, + ), + self.batch_write: gapic_v1.method_async.wrap_method( + self.batch_write, + default_timeout=3600.0, + client_info=client_info, + ), + } + def close(self): return self.grpc_channel.close() diff --git a/google/cloud/spanner_v1/services/spanner/transports/rest.py b/google/cloud/spanner_v1/services/spanner/transports/rest.py index 5e32bfaf2a..12e1124f9b 100644 --- a/google/cloud/spanner_v1/services/spanner/transports/rest.py +++ b/google/cloud/spanner_v1/services/spanner/transports/rest.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -34,9 +34,9 @@ import warnings try: - OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] except AttributeError: # pragma: NO COVER - OptionalRetry = Union[retries.Retry, object] # type: ignore + OptionalRetry = Union[retries.Retry, object, None] # type: ignore from google.cloud.spanner_v1.types import commit_response @@ -553,7 +553,7 @@ def __init__( Args: host (Optional[str]): - The hostname to connect to. + The hostname to connect to (default: 'spanner.googleapis.com'). credentials (Optional[google.auth.credentials.Credentials]): The authorization credentials to attach to requests. These credentials identify the application to the service; if none @@ -667,9 +667,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -678,7 +676,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -765,9 +762,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -776,7 +771,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -860,9 +854,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -871,7 +863,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -958,9 +949,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -969,7 +958,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1054,9 +1042,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1065,7 +1051,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1149,7 +1134,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1265,9 +1249,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1276,7 +1258,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1364,9 +1345,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1375,7 +1354,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1468,9 +1446,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1479,7 +1455,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1566,7 +1541,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1655,7 +1629,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1743,9 +1716,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1754,7 +1725,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1843,9 +1813,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1854,7 +1822,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -1942,9 +1909,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -1953,7 +1918,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2034,9 +1998,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -2045,7 +2007,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) @@ -2128,9 +2089,7 @@ def __call__( # Jsonify the request body body = json_format.MessageToJson( - transcoded_request["body"], - including_default_value_fields=False, - use_integers_for_enums=True, + transcoded_request["body"], use_integers_for_enums=True ) uri = transcoded_request["uri"] method = transcoded_request["method"] @@ -2139,7 +2098,6 @@ def __call__( query_params = json.loads( json_format.MessageToJson( transcoded_request["query_params"], - including_default_value_fields=False, use_integers_for_enums=True, ) ) diff --git a/google/cloud/spanner_v1/types/__init__.py b/google/cloud/spanner_v1/types/__init__.py index 52b485d976..03133b0438 100644 --- a/google/cloud/spanner_v1/types/__init__.py +++ b/google/cloud/spanner_v1/types/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/types/commit_response.py b/google/cloud/spanner_v1/types/commit_response.py index bb88bfcd20..dca48c3f88 100644 --- a/google/cloud/spanner_v1/types/commit_response.py +++ b/google/cloud/spanner_v1/types/commit_response.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/types/keys.py b/google/cloud/spanner_v1/types/keys.py index 5df70c5fce..78d246cc16 100644 --- a/google/cloud/spanner_v1/types/keys.py +++ b/google/cloud/spanner_v1/types/keys.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/types/mutation.py b/google/cloud/spanner_v1/types/mutation.py index a489819372..9e17878f81 100644 --- a/google/cloud/spanner_v1/types/mutation.py +++ b/google/cloud/spanner_v1/types/mutation.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/types/query_plan.py b/google/cloud/spanner_v1/types/query_plan.py index 7c797a4a58..ca594473f8 100644 --- a/google/cloud/spanner_v1/types/query_plan.py +++ b/google/cloud/spanner_v1/types/query_plan.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/types/result_set.py b/google/cloud/spanner_v1/types/result_set.py index 98ee23599e..af604c129d 100644 --- a/google/cloud/spanner_v1/types/result_set.py +++ b/google/cloud/spanner_v1/types/result_set.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/cloud/spanner_v1/types/spanner.py b/google/cloud/spanner_v1/types/spanner.py index 2590c212d2..465a39fbdb 100644 --- a/google/cloud/spanner_v1/types/spanner.py +++ b/google/cloud/spanner_v1/types/spanner.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -166,6 +166,16 @@ class Session(proto.Message): earlier than the actual last use time. creator_role (str): The database role which created this session. + multiplexed (bool): + Optional. If true, specifies a multiplexed session. A + multiplexed session may be used for multiple, concurrent + read-only operations but can not be used for read-write + transactions, partitioned reads, or partitioned queries. + Multiplexed sessions can be created via + [CreateSession][google.spanner.v1.Spanner.CreateSession] but + not via + [BatchCreateSessions][google.spanner.v1.Spanner.BatchCreateSessions]. + Multiplexed sessions may not be deleted nor listed. """ name: str = proto.Field( @@ -191,6 +201,10 @@ class Session(proto.Message): proto.STRING, number=5, ) + multiplexed: bool = proto.Field( + proto.BOOL, + number=6, + ) class GetSessionRequest(proto.Message): @@ -409,9 +423,9 @@ class DirectedReadOptions(proto.Message): This field is a member of `oneof`_ ``replicas``. exclude_replicas (google.cloud.spanner_v1.types.DirectedReadOptions.ExcludeReplicas): - Exclude_replicas indicates that should be excluded from - serving requests. Spanner will not route requests to the - replicas in this list. + Exclude_replicas indicates that specified replicas should be + excluded from serving requests. Spanner will not route + requests to the replicas in this list. This field is a member of `oneof`_ ``replicas``. """ @@ -429,7 +443,7 @@ class ReplicaSelection(proto.Message): - ``location:us-east1`` --> The "us-east1" replica(s) of any available type will be used to process the request. - ``type:READ_ONLY`` --> The "READ_ONLY" type replica(s) in nearest - . available location will be used to process the request. + available location will be used to process the request. - ``location:us-east1 type:READ_ONLY`` --> The "READ_ONLY" type replica(s) in location "us-east1" will be used to process the request. @@ -1024,9 +1038,10 @@ class PartitionQueryRequest(proto.Message): Required. The query request to generate partitions for. The request will fail if the query is not root partitionable. For a query to be root partitionable, it needs to satisfy a - few conditions. For example, the first operator in the query - execution plan must be a distributed union operator. For - more information about other conditions, see `Read data in + few conditions. For example, if the query execution plan + contains a distributed union operator, then it must be the + first operator in the plan. For more information about other + conditions, see `Read data in parallel `__. The query request must not contain DML commands, such as @@ -1516,6 +1531,23 @@ class BatchWriteRequest(proto.Message): mutation_groups (MutableSequence[google.cloud.spanner_v1.types.BatchWriteRequest.MutationGroup]): Required. The groups of mutations to be applied. + exclude_txn_from_change_streams (bool): + Optional. When ``exclude_txn_from_change_streams`` is set to + ``true``: + + - Mutations from all transactions in this batch write + operation will not be recorded in change streams with DDL + option ``allow_txn_exclusion=true`` that are tracking + columns modified by these transactions. + - Mutations from all transactions in this batch write + operation will be recorded in change streams with DDL + option ``allow_txn_exclusion=false or not set`` that are + tracking columns modified by these transactions. + + When ``exclude_txn_from_change_streams`` is set to ``false`` + or not set, mutations from all transactions in this batch + write operation will be recorded in all change streams that + are tracking columns modified by these transactions. """ class MutationGroup(proto.Message): @@ -1549,6 +1581,10 @@ class MutationGroup(proto.Message): number=4, message=MutationGroup, ) + exclude_txn_from_change_streams: bool = proto.Field( + proto.BOOL, + number=5, + ) class BatchWriteResponse(proto.Message): diff --git a/google/cloud/spanner_v1/types/transaction.py b/google/cloud/spanner_v1/types/transaction.py index 57761569d1..8ffa66543b 100644 --- a/google/cloud/spanner_v1/types/transaction.py +++ b/google/cloud/spanner_v1/types/transaction.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -399,6 +399,25 @@ class TransactionOptions(proto.Message): the ``session`` resource. This field is a member of `oneof`_ ``mode``. + exclude_txn_from_change_streams (bool): + When ``exclude_txn_from_change_streams`` is set to ``true``: + + - Mutations from this transaction will not be recorded in + change streams with DDL option + ``allow_txn_exclusion=true`` that are tracking columns + modified by these transactions. + - Mutations from this transaction will be recorded in + change streams with DDL option + ``allow_txn_exclusion=false or not set`` that are + tracking columns modified by these transactions. + + When ``exclude_txn_from_change_streams`` is set to ``false`` + or not set, mutations from this transaction will be recorded + in all change streams that are tracking columns modified by + these transactions. ``exclude_txn_from_change_streams`` may + only be specified for read-write or partitioned-dml + transactions, otherwise the API will return an + ``INVALID_ARGUMENT`` error. """ class ReadWrite(proto.Message): @@ -581,6 +600,10 @@ class ReadOnly(proto.Message): oneof="mode", message=ReadOnly, ) + exclude_txn_from_change_streams: bool = proto.Field( + proto.BOOL, + number=5, + ) class Transaction(proto.Message): diff --git a/google/cloud/spanner_v1/types/type.py b/google/cloud/spanner_v1/types/type.py index 235b851748..2ba1af3f86 100644 --- a/google/cloud/spanner_v1/types/type.py +++ b/google/cloud/spanner_v1/types/type.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json b/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json index fd425a364b..11932ae5e8 100644 --- a/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json +++ b/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-spanner-admin-database", - "version": "3.45.0" + "version": "0.1.0" }, "snippets": [ { diff --git a/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json b/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json index d94b53aae4..0811b451cb 100644 --- a/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json +++ b/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-spanner-admin-instance", - "version": "3.45.0" + "version": "0.1.0" }, "snippets": [ { @@ -188,6 +188,183 @@ ], "title": "spanner_v1_generated_instance_admin_create_instance_config_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", + "shortName": "InstanceAdminAsyncClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.create_instance_partition", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "CreateInstancePartition" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.CreateInstancePartitionRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "instance_partition", + "type": "google.cloud.spanner_admin_instance_v1.types.InstancePartition" + }, + { + "name": "instance_partition_id", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "create_instance_partition" + }, + "description": "Sample for CreateInstancePartition", + "file": "spanner_v1_generated_instance_admin_create_instance_partition_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_CreateInstancePartition_async", + "segments": [ + { + "end": 63, + "start": 27, + "type": "FULL" + }, + { + "end": 63, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 53, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 60, + "start": 54, + "type": "REQUEST_EXECUTION" + }, + { + "end": 64, + "start": 61, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_create_instance_partition_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", + "shortName": "InstanceAdminClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.create_instance_partition", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "CreateInstancePartition" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.CreateInstancePartitionRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "instance_partition", + "type": "google.cloud.spanner_admin_instance_v1.types.InstancePartition" + }, + { + "name": "instance_partition_id", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation.Operation", + "shortName": "create_instance_partition" + }, + "description": "Sample for CreateInstancePartition", + "file": "spanner_v1_generated_instance_admin_create_instance_partition_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_CreateInstancePartition_sync", + "segments": [ + { + "end": 63, + "start": 27, + "type": "FULL" + }, + { + "end": 63, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 53, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 60, + "start": 54, + "type": "REQUEST_EXECUTION" + }, + { + "end": 64, + "start": 61, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_create_instance_partition_sync.py" + }, { "canonical": true, "clientMethod": { @@ -528,19 +705,19 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", "shortName": "InstanceAdminAsyncClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.delete_instance", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.delete_instance_partition", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstance", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstancePartition", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "DeleteInstance" + "shortName": "DeleteInstancePartition" }, "parameters": [ { "name": "request", - "type": "google.cloud.spanner_admin_instance_v1.types.DeleteInstanceRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.DeleteInstancePartitionRequest" }, { "name": "name", @@ -559,13 +736,13 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_instance" + "shortName": "delete_instance_partition" }, - "description": "Sample for DeleteInstance", - "file": "spanner_v1_generated_instance_admin_delete_instance_async.py", + "description": "Sample for DeleteInstancePartition", + "file": "spanner_v1_generated_instance_admin_delete_instance_partition_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_DeleteInstance_async", + "regionTag": "spanner_v1_generated_InstanceAdmin_DeleteInstancePartition_async", "segments": [ { "end": 49, @@ -596,7 +773,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_delete_instance_async.py" + "title": "spanner_v1_generated_instance_admin_delete_instance_partition_async.py" }, { "canonical": true, @@ -605,19 +782,19 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", "shortName": "InstanceAdminClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.delete_instance", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.delete_instance_partition", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstance", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstancePartition", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "DeleteInstance" + "shortName": "DeleteInstancePartition" }, "parameters": [ { "name": "request", - "type": "google.cloud.spanner_admin_instance_v1.types.DeleteInstanceRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.DeleteInstancePartitionRequest" }, { "name": "name", @@ -636,13 +813,13 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_instance" + "shortName": "delete_instance_partition" }, - "description": "Sample for DeleteInstance", - "file": "spanner_v1_generated_instance_admin_delete_instance_sync.py", + "description": "Sample for DeleteInstancePartition", + "file": "spanner_v1_generated_instance_admin_delete_instance_partition_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_DeleteInstance_sync", + "regionTag": "spanner_v1_generated_InstanceAdmin_DeleteInstancePartition_sync", "segments": [ { "end": 49, @@ -673,7 +850,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_delete_instance_sync.py" + "title": "spanner_v1_generated_instance_admin_delete_instance_partition_sync.py" }, { "canonical": true, @@ -683,22 +860,22 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", "shortName": "InstanceAdminAsyncClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.get_iam_policy", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.delete_instance", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetIamPolicy", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstance", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "GetIamPolicy" + "shortName": "DeleteInstance" }, "parameters": [ { "name": "request", - "type": "google.iam.v1.iam_policy_pb2.GetIamPolicyRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.DeleteInstanceRequest" }, { - "name": "resource", + "name": "name", "type": "str" }, { @@ -714,47 +891,44 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.iam.v1.policy_pb2.Policy", - "shortName": "get_iam_policy" + "shortName": "delete_instance" }, - "description": "Sample for GetIamPolicy", - "file": "spanner_v1_generated_instance_admin_get_iam_policy_async.py", + "description": "Sample for DeleteInstance", + "file": "spanner_v1_generated_instance_admin_delete_instance_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_GetIamPolicy_async", + "regionTag": "spanner_v1_generated_InstanceAdmin_DeleteInstance_async", "segments": [ { - "end": 52, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 49, "start": 27, "type": "SHORT" }, { - "end": 41, - "start": 39, + "end": 40, + "start": 38, "type": "CLIENT_INITIALIZATION" }, { - "end": 46, - "start": 42, + "end": 45, + "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 49, - "start": 47, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 50, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_get_iam_policy_async.py" + "title": "spanner_v1_generated_instance_admin_delete_instance_async.py" }, { "canonical": true, @@ -763,22 +937,22 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", "shortName": "InstanceAdminClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.get_iam_policy", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.delete_instance", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetIamPolicy", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstance", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "GetIamPolicy" + "shortName": "DeleteInstance" }, "parameters": [ { "name": "request", - "type": "google.iam.v1.iam_policy_pb2.GetIamPolicyRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.DeleteInstanceRequest" }, { - "name": "resource", + "name": "name", "type": "str" }, { @@ -794,47 +968,44 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.iam.v1.policy_pb2.Policy", - "shortName": "get_iam_policy" + "shortName": "delete_instance" }, - "description": "Sample for GetIamPolicy", - "file": "spanner_v1_generated_instance_admin_get_iam_policy_sync.py", + "description": "Sample for DeleteInstance", + "file": "spanner_v1_generated_instance_admin_delete_instance_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_GetIamPolicy_sync", + "regionTag": "spanner_v1_generated_InstanceAdmin_DeleteInstance_sync", "segments": [ { - "end": 52, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 49, "start": 27, "type": "SHORT" }, { - "end": 41, - "start": 39, + "end": 40, + "start": 38, "type": "CLIENT_INITIALIZATION" }, { - "end": 46, - "start": 42, + "end": 45, + "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 49, - "start": 47, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 50, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_get_iam_policy_sync.py" + "title": "spanner_v1_generated_instance_admin_delete_instance_sync.py" }, { "canonical": true, @@ -844,22 +1015,22 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", "shortName": "InstanceAdminAsyncClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.get_instance_config", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.get_iam_policy", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetInstanceConfig", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetIamPolicy", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "GetInstanceConfig" + "shortName": "GetIamPolicy" }, "parameters": [ { "name": "request", - "type": "google.cloud.spanner_admin_instance_v1.types.GetInstanceConfigRequest" + "type": "google.iam.v1.iam_policy_pb2.GetIamPolicyRequest" }, { - "name": "name", + "name": "resource", "type": "str" }, { @@ -875,7 +1046,168 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.spanner_admin_instance_v1.types.InstanceConfig", + "resultType": "google.iam.v1.policy_pb2.Policy", + "shortName": "get_iam_policy" + }, + "description": "Sample for GetIamPolicy", + "file": "spanner_v1_generated_instance_admin_get_iam_policy_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_GetIamPolicy_async", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 41, + "start": 39, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 46, + "start": 42, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 49, + "start": 47, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_get_iam_policy_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", + "shortName": "InstanceAdminClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.get_iam_policy", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetIamPolicy", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "GetIamPolicy" + }, + "parameters": [ + { + "name": "request", + "type": "google.iam.v1.iam_policy_pb2.GetIamPolicyRequest" + }, + { + "name": "resource", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.iam.v1.policy_pb2.Policy", + "shortName": "get_iam_policy" + }, + "description": "Sample for GetIamPolicy", + "file": "spanner_v1_generated_instance_admin_get_iam_policy_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_GetIamPolicy_sync", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 41, + "start": 39, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 46, + "start": 42, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 49, + "start": 47, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_get_iam_policy_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", + "shortName": "InstanceAdminAsyncClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.get_instance_config", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetInstanceConfig", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "GetInstanceConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.GetInstanceConfigRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.spanner_admin_instance_v1.types.InstanceConfig", "shortName": "get_instance_config" }, "description": "Sample for GetInstanceConfig", @@ -958,19 +1290,502 @@ "resultType": "google.cloud.spanner_admin_instance_v1.types.InstanceConfig", "shortName": "get_instance_config" }, - "description": "Sample for GetInstanceConfig", - "file": "spanner_v1_generated_instance_admin_get_instance_config_sync.py", + "description": "Sample for GetInstanceConfig", + "file": "spanner_v1_generated_instance_admin_get_instance_config_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_GetInstanceConfig_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_get_instance_config_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", + "shortName": "InstanceAdminAsyncClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.get_instance_partition", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetInstancePartition", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "GetInstancePartition" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.GetInstancePartitionRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.spanner_admin_instance_v1.types.InstancePartition", + "shortName": "get_instance_partition" + }, + "description": "Sample for GetInstancePartition", + "file": "spanner_v1_generated_instance_admin_get_instance_partition_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_GetInstancePartition_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_get_instance_partition_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", + "shortName": "InstanceAdminClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.get_instance_partition", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetInstancePartition", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "GetInstancePartition" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.GetInstancePartitionRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.spanner_admin_instance_v1.types.InstancePartition", + "shortName": "get_instance_partition" + }, + "description": "Sample for GetInstancePartition", + "file": "spanner_v1_generated_instance_admin_get_instance_partition_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_GetInstancePartition_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_get_instance_partition_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", + "shortName": "InstanceAdminAsyncClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.get_instance", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetInstance", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "GetInstance" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.GetInstanceRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.spanner_admin_instance_v1.types.Instance", + "shortName": "get_instance" + }, + "description": "Sample for GetInstance", + "file": "spanner_v1_generated_instance_admin_get_instance_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_GetInstance_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_get_instance_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", + "shortName": "InstanceAdminClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.get_instance", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetInstance", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "GetInstance" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.GetInstanceRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.spanner_admin_instance_v1.types.Instance", + "shortName": "get_instance" + }, + "description": "Sample for GetInstance", + "file": "spanner_v1_generated_instance_admin_get_instance_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_GetInstance_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_get_instance_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", + "shortName": "InstanceAdminAsyncClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.list_instance_config_operations", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "ListInstanceConfigOperations" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.ListInstanceConfigOperationsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstanceConfigOperationsAsyncPager", + "shortName": "list_instance_config_operations" + }, + "description": "Sample for ListInstanceConfigOperations", + "file": "spanner_v1_generated_instance_admin_list_instance_config_operations_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstanceConfigOperations_async", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_list_instance_config_operations_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", + "shortName": "InstanceAdminClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.list_instance_config_operations", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "ListInstanceConfigOperations" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.ListInstanceConfigOperationsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstanceConfigOperationsPager", + "shortName": "list_instance_config_operations" + }, + "description": "Sample for ListInstanceConfigOperations", + "file": "spanner_v1_generated_instance_admin_list_instance_config_operations_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_GetInstanceConfig_sync", + "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstanceConfigOperations_sync", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -990,12 +1805,12 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_get_instance_config_sync.py" + "title": "spanner_v1_generated_instance_admin_list_instance_config_operations_sync.py" }, { "canonical": true, @@ -1005,22 +1820,22 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", "shortName": "InstanceAdminAsyncClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.get_instance", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.list_instance_configs", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetInstance", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "GetInstance" + "shortName": "ListInstanceConfigs" }, "parameters": [ { "name": "request", - "type": "google.cloud.spanner_admin_instance_v1.types.GetInstanceRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.ListInstanceConfigsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -1036,22 +1851,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.spanner_admin_instance_v1.types.Instance", - "shortName": "get_instance" + "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstanceConfigsAsyncPager", + "shortName": "list_instance_configs" }, - "description": "Sample for GetInstance", - "file": "spanner_v1_generated_instance_admin_get_instance_async.py", + "description": "Sample for ListInstanceConfigs", + "file": "spanner_v1_generated_instance_admin_list_instance_configs_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_GetInstance_async", + "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstanceConfigs_async", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -1071,12 +1886,12 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_get_instance_async.py" + "title": "spanner_v1_generated_instance_admin_list_instance_configs_async.py" }, { "canonical": true, @@ -1085,22 +1900,22 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", "shortName": "InstanceAdminClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.get_instance", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.list_instance_configs", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.GetInstance", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "GetInstance" + "shortName": "ListInstanceConfigs" }, "parameters": [ { "name": "request", - "type": "google.cloud.spanner_admin_instance_v1.types.GetInstanceRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.ListInstanceConfigsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -1116,22 +1931,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.spanner_admin_instance_v1.types.Instance", - "shortName": "get_instance" + "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstanceConfigsPager", + "shortName": "list_instance_configs" }, - "description": "Sample for GetInstance", - "file": "spanner_v1_generated_instance_admin_get_instance_sync.py", + "description": "Sample for ListInstanceConfigs", + "file": "spanner_v1_generated_instance_admin_list_instance_configs_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_GetInstance_sync", + "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstanceConfigs_sync", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -1151,12 +1966,12 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_get_instance_sync.py" + "title": "spanner_v1_generated_instance_admin_list_instance_configs_sync.py" }, { "canonical": true, @@ -1166,19 +1981,19 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", "shortName": "InstanceAdminAsyncClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.list_instance_config_operations", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.list_instance_partition_operations", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "ListInstanceConfigOperations" + "shortName": "ListInstancePartitionOperations" }, "parameters": [ { "name": "request", - "type": "google.cloud.spanner_admin_instance_v1.types.ListInstanceConfigOperationsRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsRequest" }, { "name": "parent", @@ -1197,14 +2012,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstanceConfigOperationsAsyncPager", - "shortName": "list_instance_config_operations" + "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstancePartitionOperationsAsyncPager", + "shortName": "list_instance_partition_operations" }, - "description": "Sample for ListInstanceConfigOperations", - "file": "spanner_v1_generated_instance_admin_list_instance_config_operations_async.py", + "description": "Sample for ListInstancePartitionOperations", + "file": "spanner_v1_generated_instance_admin_list_instance_partition_operations_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstanceConfigOperations_async", + "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstancePartitionOperations_async", "segments": [ { "end": 52, @@ -1237,7 +2052,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_list_instance_config_operations_async.py" + "title": "spanner_v1_generated_instance_admin_list_instance_partition_operations_async.py" }, { "canonical": true, @@ -1246,19 +2061,19 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", "shortName": "InstanceAdminClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.list_instance_config_operations", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.list_instance_partition_operations", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "ListInstanceConfigOperations" + "shortName": "ListInstancePartitionOperations" }, "parameters": [ { "name": "request", - "type": "google.cloud.spanner_admin_instance_v1.types.ListInstanceConfigOperationsRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionOperationsRequest" }, { "name": "parent", @@ -1277,14 +2092,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstanceConfigOperationsPager", - "shortName": "list_instance_config_operations" + "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstancePartitionOperationsPager", + "shortName": "list_instance_partition_operations" }, - "description": "Sample for ListInstanceConfigOperations", - "file": "spanner_v1_generated_instance_admin_list_instance_config_operations_sync.py", + "description": "Sample for ListInstancePartitionOperations", + "file": "spanner_v1_generated_instance_admin_list_instance_partition_operations_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstanceConfigOperations_sync", + "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstancePartitionOperations_sync", "segments": [ { "end": 52, @@ -1317,7 +2132,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_list_instance_config_operations_sync.py" + "title": "spanner_v1_generated_instance_admin_list_instance_partition_operations_sync.py" }, { "canonical": true, @@ -1327,19 +2142,19 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", "shortName": "InstanceAdminAsyncClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.list_instance_configs", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.list_instance_partitions", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "ListInstanceConfigs" + "shortName": "ListInstancePartitions" }, "parameters": [ { "name": "request", - "type": "google.cloud.spanner_admin_instance_v1.types.ListInstanceConfigsRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsRequest" }, { "name": "parent", @@ -1358,14 +2173,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstanceConfigsAsyncPager", - "shortName": "list_instance_configs" + "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstancePartitionsAsyncPager", + "shortName": "list_instance_partitions" }, - "description": "Sample for ListInstanceConfigs", - "file": "spanner_v1_generated_instance_admin_list_instance_configs_async.py", + "description": "Sample for ListInstancePartitions", + "file": "spanner_v1_generated_instance_admin_list_instance_partitions_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstanceConfigs_async", + "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstancePartitions_async", "segments": [ { "end": 52, @@ -1398,7 +2213,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_list_instance_configs_async.py" + "title": "spanner_v1_generated_instance_admin_list_instance_partitions_async.py" }, { "canonical": true, @@ -1407,19 +2222,19 @@ "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", "shortName": "InstanceAdminClient" }, - "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.list_instance_configs", + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.list_instance_partitions", "method": { - "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs", + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions", "service": { "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", "shortName": "InstanceAdmin" }, - "shortName": "ListInstanceConfigs" + "shortName": "ListInstancePartitions" }, "parameters": [ { "name": "request", - "type": "google.cloud.spanner_admin_instance_v1.types.ListInstanceConfigsRequest" + "type": "google.cloud.spanner_admin_instance_v1.types.ListInstancePartitionsRequest" }, { "name": "parent", @@ -1438,14 +2253,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstanceConfigsPager", - "shortName": "list_instance_configs" + "resultType": "google.cloud.spanner_admin_instance_v1.services.instance_admin.pagers.ListInstancePartitionsPager", + "shortName": "list_instance_partitions" }, - "description": "Sample for ListInstanceConfigs", - "file": "spanner_v1_generated_instance_admin_list_instance_configs_sync.py", + "description": "Sample for ListInstancePartitions", + "file": "spanner_v1_generated_instance_admin_list_instance_partitions_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstanceConfigs_sync", + "regionTag": "spanner_v1_generated_InstanceAdmin_ListInstancePartitions_sync", "segments": [ { "end": 52, @@ -1478,7 +2293,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "spanner_v1_generated_instance_admin_list_instance_configs_sync.py" + "title": "spanner_v1_generated_instance_admin_list_instance_partitions_sync.py" }, { "canonical": true, @@ -2140,6 +2955,175 @@ ], "title": "spanner_v1_generated_instance_admin_update_instance_config_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient", + "shortName": "InstanceAdminAsyncClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminAsyncClient.update_instance_partition", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "UpdateInstancePartition" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.UpdateInstancePartitionRequest" + }, + { + "name": "instance_partition", + "type": "google.cloud.spanner_admin_instance_v1.types.InstancePartition" + }, + { + "name": "field_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "update_instance_partition" + }, + "description": "Sample for UpdateInstancePartition", + "file": "spanner_v1_generated_instance_admin_update_instance_partition_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_UpdateInstancePartition_async", + "segments": [ + { + "end": 61, + "start": 27, + "type": "FULL" + }, + { + "end": 61, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 51, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 58, + "start": 52, + "type": "REQUEST_EXECUTION" + }, + { + "end": 62, + "start": 59, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_update_instance_partition_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient", + "shortName": "InstanceAdminClient" + }, + "fullName": "google.cloud.spanner_admin_instance_v1.InstanceAdminClient.update_instance_partition", + "method": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition", + "service": { + "fullName": "google.spanner.admin.instance.v1.InstanceAdmin", + "shortName": "InstanceAdmin" + }, + "shortName": "UpdateInstancePartition" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.spanner_admin_instance_v1.types.UpdateInstancePartitionRequest" + }, + { + "name": "instance_partition", + "type": "google.cloud.spanner_admin_instance_v1.types.InstancePartition" + }, + { + "name": "field_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation.Operation", + "shortName": "update_instance_partition" + }, + "description": "Sample for UpdateInstancePartition", + "file": "spanner_v1_generated_instance_admin_update_instance_partition_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "spanner_v1_generated_InstanceAdmin_UpdateInstancePartition_sync", + "segments": [ + { + "end": 61, + "start": 27, + "type": "FULL" + }, + { + "end": 61, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 51, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 58, + "start": 52, + "type": "REQUEST_EXECUTION" + }, + { + "end": 62, + "start": 59, + "type": "RESPONSE_HANDLING" + } + ], + "title": "spanner_v1_generated_instance_admin_update_instance_partition_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/samples/generated_samples/snippet_metadata_google.spanner.v1.json b/samples/generated_samples/snippet_metadata_google.spanner.v1.json index f73c3a8647..4384d19e2a 100644 --- a/samples/generated_samples/snippet_metadata_google.spanner.v1.json +++ b/samples/generated_samples/snippet_metadata_google.spanner.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-spanner", - "version": "3.45.0" + "version": "0.1.0" }, "snippets": [ { diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_copy_backup_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_copy_backup_async.py index eecfd3f8c5..32b6a49424 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_copy_backup_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_copy_backup_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_copy_backup_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_copy_backup_sync.py index adeb79022c..8095668300 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_copy_backup_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_copy_backup_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_create_backup_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_create_backup_async.py index addc500d76..fab8784592 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_create_backup_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_create_backup_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_create_backup_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_create_backup_sync.py index 71d2e117a9..aed56f38ec 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_create_backup_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_create_backup_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_create_database_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_create_database_async.py index 3a90afd12b..ed33381135 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_create_database_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_create_database_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_create_database_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_create_database_sync.py index 5df156a31a..eefa7b1b76 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_create_database_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_create_database_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_delete_backup_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_delete_backup_async.py index 81756a5082..8e2f065e08 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_delete_backup_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_delete_backup_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_delete_backup_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_delete_backup_sync.py index faeaf80e14..0285226164 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_delete_backup_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_delete_backup_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_drop_database_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_drop_database_async.py index 535c200bca..761e554b70 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_drop_database_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_drop_database_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_drop_database_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_drop_database_sync.py index f41ae22b78..6c288a5218 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_drop_database_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_drop_database_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_get_backup_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_get_backup_async.py index 44c85937d7..dfa618063f 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_get_backup_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_get_backup_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_get_backup_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_get_backup_sync.py index c3b485b1b7..8bcc701ffd 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_get_backup_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_get_backup_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_get_database_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_get_database_async.py index c03912e2b5..d683763f11 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_get_database_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_get_database_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_get_database_ddl_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_get_database_ddl_async.py index 31543e78c7..d0b3144c54 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_get_database_ddl_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_get_database_ddl_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_get_database_ddl_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_get_database_ddl_sync.py index 513fefb4a1..2290e41605 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_get_database_ddl_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_get_database_ddl_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_get_database_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_get_database_sync.py index 9c387b5c03..03c230f0a5 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_get_database_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_get_database_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_get_iam_policy_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_get_iam_policy_async.py index 3cc9288504..be670085c5 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_get_iam_policy_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_get_iam_policy_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_get_iam_policy_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_get_iam_policy_sync.py index ce2cef22b7..373cefddf8 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_get_iam_policy_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_get_iam_policy_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_backup_operations_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_backup_operations_async.py index c7f1a8251d..006ccfd03d 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_backup_operations_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_backup_operations_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_backup_operations_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_backup_operations_sync.py index ae1edbdfcd..3b43e2a421 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_backup_operations_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_backup_operations_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_backups_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_backups_async.py index fde292d848..b5108233aa 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_backups_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_backups_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_backups_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_backups_sync.py index 8b68a4e6b1..9560a10109 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_backups_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_backups_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_database_operations_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_database_operations_async.py index 45e1020028..83d3e9da52 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_database_operations_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_database_operations_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_database_operations_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_database_operations_sync.py index 2b30bd20b3..1000a4d331 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_database_operations_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_database_operations_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_database_roles_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_database_roles_async.py index 7154625202..c932837b20 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_database_roles_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_database_roles_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_database_roles_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_database_roles_sync.py index e187ca5c37..7954a66b66 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_database_roles_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_database_roles_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_databases_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_databases_async.py index a166a7ede7..1309518b23 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_databases_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_databases_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_list_databases_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_list_databases_sync.py index 0b42664a5c..12124cf524 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_list_databases_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_list_databases_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_restore_database_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_restore_database_async.py index 7edc6e92a5..eb8f2a3f80 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_restore_database_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_restore_database_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_restore_database_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_restore_database_sync.py index ceaf444bab..f2307a1373 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_restore_database_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_restore_database_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_set_iam_policy_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_set_iam_policy_async.py index e99eeb9038..471292596d 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_set_iam_policy_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_set_iam_policy_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_set_iam_policy_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_set_iam_policy_sync.py index 3d9e8c45fd..6966e294af 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_set_iam_policy_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_set_iam_policy_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_test_iam_permissions_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_test_iam_permissions_async.py index 7489498e52..feb2a5ca93 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_test_iam_permissions_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_test_iam_permissions_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_test_iam_permissions_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_test_iam_permissions_sync.py index bcc5ae0380..16b7587251 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_test_iam_permissions_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_test_iam_permissions_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_update_backup_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_update_backup_async.py index f73b28dbf1..aea59b4c92 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_update_backup_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_update_backup_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_update_backup_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_update_backup_sync.py index 104f11ab98..aac39bb124 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_update_backup_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_update_backup_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_update_database_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_update_database_async.py index de4017607f..cfc427c768 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_update_database_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_update_database_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_update_database_ddl_async.py b/samples/generated_samples/spanner_v1_generated_database_admin_update_database_ddl_async.py index 8811a329bc..940760d957 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_update_database_ddl_async.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_update_database_ddl_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_update_database_ddl_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_update_database_ddl_sync.py index 62b0b6af59..37189cc03b 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_update_database_ddl_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_update_database_ddl_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_database_admin_update_database_sync.py b/samples/generated_samples/spanner_v1_generated_database_admin_update_database_sync.py index c819d9aabe..fe15e7ce86 100644 --- a/samples/generated_samples/spanner_v1_generated_database_admin_update_database_sync.py +++ b/samples/generated_samples/spanner_v1_generated_database_admin_update_database_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_async.py index bdfc15c803..4eb7c7aa05 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_config_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_config_async.py index 43ddc483bc..824b001bbb 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_config_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_config_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_config_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_config_sync.py index e087c4693d..8674445ca1 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_config_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_config_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_partition_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_partition_async.py new file mode 100644 index 0000000000..65d4f9f7d3 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_partition_async.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for CreateInstancePartition +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_CreateInstancePartition_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +async def sample_create_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + instance_partition = spanner_admin_instance_v1.InstancePartition() + instance_partition.node_count = 1070 + instance_partition.name = "name_value" + instance_partition.config = "config_value" + instance_partition.display_name = "display_name_value" + + request = spanner_admin_instance_v1.CreateInstancePartitionRequest( + parent="parent_value", + instance_partition_id="instance_partition_id_value", + instance_partition=instance_partition, + ) + + # Make the request + operation = client.create_instance_partition(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + +# [END spanner_v1_generated_InstanceAdmin_CreateInstancePartition_async] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_partition_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_partition_sync.py new file mode 100644 index 0000000000..dd29783b41 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_partition_sync.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for CreateInstancePartition +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_CreateInstancePartition_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +def sample_create_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + instance_partition = spanner_admin_instance_v1.InstancePartition() + instance_partition.node_count = 1070 + instance_partition.name = "name_value" + instance_partition.config = "config_value" + instance_partition.display_name = "display_name_value" + + request = spanner_admin_instance_v1.CreateInstancePartitionRequest( + parent="parent_value", + instance_partition_id="instance_partition_id_value", + instance_partition=instance_partition, + ) + + # Make the request + operation = client.create_instance_partition(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + +# [END spanner_v1_generated_InstanceAdmin_CreateInstancePartition_sync] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_sync.py index 2410a4ffe7..355d17496b 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_create_instance_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_async.py index fdbdce5acf..91ff61bb4f 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_config_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_config_async.py index 81121e071d..9cdb724363 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_config_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_config_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_config_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_config_sync.py index f040b054eb..b42ccf67c7 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_config_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_config_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_partition_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_partition_async.py new file mode 100644 index 0000000000..4609f23b3c --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_partition_async.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for DeleteInstancePartition +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_DeleteInstancePartition_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +async def sample_delete_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.DeleteInstancePartitionRequest( + name="name_value", + ) + + # Make the request + await client.delete_instance_partition(request=request) + + +# [END spanner_v1_generated_InstanceAdmin_DeleteInstancePartition_async] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_partition_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_partition_sync.py new file mode 100644 index 0000000000..ee3154a818 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_partition_sync.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for DeleteInstancePartition +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_DeleteInstancePartition_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +def sample_delete_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.DeleteInstancePartitionRequest( + name="name_value", + ) + + # Make the request + client.delete_instance_partition(request=request) + + +# [END spanner_v1_generated_InstanceAdmin_DeleteInstancePartition_sync] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_sync.py index 08f041ad82..3303f219fe 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_delete_instance_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_get_iam_policy_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_get_iam_policy_async.py index 3168f83c50..73fdfdf2f4 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_get_iam_policy_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_get_iam_policy_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_get_iam_policy_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_get_iam_policy_sync.py index b254f0b4fd..0afa94e008 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_get_iam_policy_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_get_iam_policy_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_async.py index e8ad7e9e71..32de7eab8b 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_config_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_config_async.py index 22bbff1172..aeeb5b5106 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_config_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_config_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_config_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_config_sync.py index af43a9f9b9..fbdcf3ff1f 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_config_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_config_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_partition_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_partition_async.py new file mode 100644 index 0000000000..d59e5a4cc7 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_partition_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetInstancePartition +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_GetInstancePartition_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +async def sample_get_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.GetInstancePartitionRequest( + name="name_value", + ) + + # Make the request + response = await client.get_instance_partition(request=request) + + # Handle the response + print(response) + +# [END spanner_v1_generated_InstanceAdmin_GetInstancePartition_async] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_partition_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_partition_sync.py new file mode 100644 index 0000000000..545112fe50 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_partition_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetInstancePartition +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_GetInstancePartition_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +def sample_get_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.GetInstancePartitionRequest( + name="name_value", + ) + + # Make the request + response = client.get_instance_partition(request=request) + + # Handle the response + print(response) + +# [END spanner_v1_generated_InstanceAdmin_GetInstancePartition_sync] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_sync.py index 0204121a69..25e9221772 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_get_instance_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_config_operations_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_config_operations_async.py index 0272e4784d..c521261e57 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_config_operations_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_config_operations_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_config_operations_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_config_operations_sync.py index 155b16d23b..ee1d6c10bc 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_config_operations_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_config_operations_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_configs_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_configs_async.py index f373257f54..0f405efa17 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_configs_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_configs_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_configs_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_configs_sync.py index 9cccfc5bcf..dc94c90e45 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_configs_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_configs_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partition_operations_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partition_operations_async.py new file mode 100644 index 0000000000..a526600c46 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partition_operations_async.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListInstancePartitionOperations +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_ListInstancePartitionOperations_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +async def sample_list_instance_partition_operations(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.ListInstancePartitionOperationsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_instance_partition_operations(request=request) + + # Handle the response + async for response in page_result: + print(response) + +# [END spanner_v1_generated_InstanceAdmin_ListInstancePartitionOperations_async] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partition_operations_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partition_operations_sync.py new file mode 100644 index 0000000000..47d40cc011 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partition_operations_sync.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListInstancePartitionOperations +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_ListInstancePartitionOperations_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +def sample_list_instance_partition_operations(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.ListInstancePartitionOperationsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_instance_partition_operations(request=request) + + # Handle the response + for response in page_result: + print(response) + +# [END spanner_v1_generated_InstanceAdmin_ListInstancePartitionOperations_sync] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partitions_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partitions_async.py new file mode 100644 index 0000000000..b241b83957 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partitions_async.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListInstancePartitions +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_ListInstancePartitions_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +async def sample_list_instance_partitions(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.ListInstancePartitionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_instance_partitions(request=request) + + # Handle the response + async for response in page_result: + print(response) + +# [END spanner_v1_generated_InstanceAdmin_ListInstancePartitions_async] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partitions_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partitions_sync.py new file mode 100644 index 0000000000..7e23ad5fdf --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instance_partitions_sync.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListInstancePartitions +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_ListInstancePartitions_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +def sample_list_instance_partitions(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + request = spanner_admin_instance_v1.ListInstancePartitionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_instance_partitions(request=request) + + # Handle the response + for response in page_result: + print(response) + +# [END spanner_v1_generated_InstanceAdmin_ListInstancePartitions_sync] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instances_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instances_async.py index 86b3622d20..c499be7e7d 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instances_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instances_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instances_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instances_sync.py index b0cf56bfe2..6fd4ce9b04 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_list_instances_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_list_instances_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_set_iam_policy_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_set_iam_policy_async.py index 9e6995401f..b575a3ebec 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_set_iam_policy_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_set_iam_policy_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_set_iam_policy_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_set_iam_policy_sync.py index 600b5d6802..87f95719d9 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_set_iam_policy_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_set_iam_policy_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_test_iam_permissions_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_test_iam_permissions_async.py index 1b8e2e590c..94f406fe86 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_test_iam_permissions_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_test_iam_permissions_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_test_iam_permissions_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_test_iam_permissions_sync.py index eeb7214ea0..0940a69558 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_test_iam_permissions_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_test_iam_permissions_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_async.py index 6b9067d4c9..27fc605adb 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_config_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_config_async.py index 52c8b32f19..1705623ab6 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_config_async.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_config_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_config_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_config_sync.py index f442729bac..7313ce4dd1 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_config_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_config_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_partition_async.py b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_partition_async.py new file mode 100644 index 0000000000..cc84025f61 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_partition_async.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateInstancePartition +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_UpdateInstancePartition_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +async def sample_update_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminAsyncClient() + + # Initialize request argument(s) + instance_partition = spanner_admin_instance_v1.InstancePartition() + instance_partition.node_count = 1070 + instance_partition.name = "name_value" + instance_partition.config = "config_value" + instance_partition.display_name = "display_name_value" + + request = spanner_admin_instance_v1.UpdateInstancePartitionRequest( + instance_partition=instance_partition, + ) + + # Make the request + operation = client.update_instance_partition(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + +# [END spanner_v1_generated_InstanceAdmin_UpdateInstancePartition_async] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_partition_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_partition_sync.py new file mode 100644 index 0000000000..8c03a71cb6 --- /dev/null +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_partition_sync.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateInstancePartition +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-spanner-admin-instance + + +# [START spanner_v1_generated_InstanceAdmin_UpdateInstancePartition_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import spanner_admin_instance_v1 + + +def sample_update_instance_partition(): + # Create a client + client = spanner_admin_instance_v1.InstanceAdminClient() + + # Initialize request argument(s) + instance_partition = spanner_admin_instance_v1.InstancePartition() + instance_partition.node_count = 1070 + instance_partition.name = "name_value" + instance_partition.config = "config_value" + instance_partition.display_name = "display_name_value" + + request = spanner_admin_instance_v1.UpdateInstancePartitionRequest( + instance_partition=instance_partition, + ) + + # Make the request + operation = client.update_instance_partition(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + +# [END spanner_v1_generated_InstanceAdmin_UpdateInstancePartition_sync] diff --git a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_sync.py b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_sync.py index b16bad3938..8c8bd97801 100644 --- a/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_sync.py +++ b/samples/generated_samples/spanner_v1_generated_instance_admin_update_instance_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_batch_create_sessions_async.py b/samples/generated_samples/spanner_v1_generated_spanner_batch_create_sessions_async.py index 230fd92344..1bb7980b78 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_batch_create_sessions_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_batch_create_sessions_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_batch_create_sessions_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_batch_create_sessions_sync.py index 444810e746..03cf8cb51f 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_batch_create_sessions_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_batch_create_sessions_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_batch_write_async.py b/samples/generated_samples/spanner_v1_generated_spanner_batch_write_async.py index 39352562b1..ffd543c558 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_batch_write_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_batch_write_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_batch_write_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_batch_write_sync.py index 4ee88b0cd6..4c2a61570e 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_batch_write_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_batch_write_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_begin_transaction_async.py b/samples/generated_samples/spanner_v1_generated_spanner_begin_transaction_async.py index 1d34f5195a..d83678021f 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_begin_transaction_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_begin_transaction_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_begin_transaction_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_begin_transaction_sync.py index 1ce58b04f8..7b46b6607a 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_begin_transaction_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_begin_transaction_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_commit_async.py b/samples/generated_samples/spanner_v1_generated_spanner_commit_async.py index 083721f956..d58a68ebf7 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_commit_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_commit_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_commit_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_commit_sync.py index 11874739c2..7591f2ee3a 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_commit_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_commit_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_create_session_async.py b/samples/generated_samples/spanner_v1_generated_spanner_create_session_async.py index 1e5161a115..0aa41bfd0f 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_create_session_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_create_session_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_create_session_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_create_session_sync.py index 2065e11683..f3eb09c5fd 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_create_session_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_create_session_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_delete_session_async.py b/samples/generated_samples/spanner_v1_generated_spanner_delete_session_async.py index 3aea99c567..daa5434346 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_delete_session_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_delete_session_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_delete_session_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_delete_session_sync.py index f09fdbfae6..bf710daa12 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_delete_session_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_delete_session_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_execute_batch_dml_async.py b/samples/generated_samples/spanner_v1_generated_spanner_execute_batch_dml_async.py index 24c9f5f8d1..5652a454af 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_execute_batch_dml_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_execute_batch_dml_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_execute_batch_dml_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_execute_batch_dml_sync.py index dcd875e200..368d9151fc 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_execute_batch_dml_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_execute_batch_dml_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_execute_sql_async.py b/samples/generated_samples/spanner_v1_generated_spanner_execute_sql_async.py index cbb44d8250..5e90cf9dbf 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_execute_sql_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_execute_sql_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_execute_sql_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_execute_sql_sync.py index e678c6f55e..1c34213f81 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_execute_sql_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_execute_sql_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_execute_streaming_sql_async.py b/samples/generated_samples/spanner_v1_generated_spanner_execute_streaming_sql_async.py index 97f95cc10f..66620d7c7f 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_execute_streaming_sql_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_execute_streaming_sql_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_execute_streaming_sql_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_execute_streaming_sql_sync.py index 115d6bc12c..5cb5e99785 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_execute_streaming_sql_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_execute_streaming_sql_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_get_session_async.py b/samples/generated_samples/spanner_v1_generated_spanner_get_session_async.py index 986c371d1f..64d5c6ebcb 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_get_session_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_get_session_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_get_session_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_get_session_sync.py index ed37be7ffa..80b6574586 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_get_session_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_get_session_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_list_sessions_async.py b/samples/generated_samples/spanner_v1_generated_spanner_list_sessions_async.py index e6746d2eb3..1a683d2957 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_list_sessions_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_list_sessions_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_list_sessions_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_list_sessions_sync.py index 35d4fde2e0..691cb51b69 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_list_sessions_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_list_sessions_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_partition_query_async.py b/samples/generated_samples/spanner_v1_generated_spanner_partition_query_async.py index 6d271d7c7b..35071eead0 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_partition_query_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_partition_query_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_partition_query_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_partition_query_sync.py index bab4edec49..fe881a1152 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_partition_query_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_partition_query_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_partition_read_async.py b/samples/generated_samples/spanner_v1_generated_spanner_partition_read_async.py index 49cd776504..7283111d8c 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_partition_read_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_partition_read_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_partition_read_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_partition_read_sync.py index 33157a8388..981d2bc900 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_partition_read_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_partition_read_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_read_async.py b/samples/generated_samples/spanner_v1_generated_spanner_read_async.py index b70704354e..d067e6c5da 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_read_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_read_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_read_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_read_sync.py index de74519a41..b87735f096 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_read_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_read_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_rollback_async.py b/samples/generated_samples/spanner_v1_generated_spanner_rollback_async.py index c016fd9a2e..fbb8495acc 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_rollback_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_rollback_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_rollback_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_rollback_sync.py index efaa9aa6f9..0a3bef9fb9 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_rollback_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_rollback_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_streaming_read_async.py b/samples/generated_samples/spanner_v1_generated_spanner_streaming_read_async.py index 15df24eb1e..65bd926ab4 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_streaming_read_async.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_streaming_read_async.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/generated_samples/spanner_v1_generated_spanner_streaming_read_sync.py b/samples/generated_samples/spanner_v1_generated_spanner_streaming_read_sync.py index 1019c904bb..b7165fea6e 100644 --- a/samples/generated_samples/spanner_v1_generated_spanner_streaming_read_sync.py +++ b/samples/generated_samples/spanner_v1_generated_spanner_streaming_read_sync.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/scripts/fixup_spanner_admin_database_v1_keywords.py b/scripts/fixup_spanner_admin_database_v1_keywords.py index dcba0a2eb4..c0ae624bb9 100644 --- a/scripts/fixup_spanner_admin_database_v1_keywords.py +++ b/scripts/fixup_spanner_admin_database_v1_keywords.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/scripts/fixup_spanner_admin_instance_v1_keywords.py b/scripts/fixup_spanner_admin_instance_v1_keywords.py index 4c100f171d..321014ad94 100644 --- a/scripts/fixup_spanner_admin_instance_v1_keywords.py +++ b/scripts/fixup_spanner_admin_instance_v1_keywords.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -41,18 +41,24 @@ class spanner_admin_instanceCallTransformer(cst.CSTTransformer): METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { 'create_instance': ('parent', 'instance_id', 'instance', ), 'create_instance_config': ('parent', 'instance_config_id', 'instance_config', 'validate_only', ), + 'create_instance_partition': ('parent', 'instance_partition_id', 'instance_partition', ), 'delete_instance': ('name', ), 'delete_instance_config': ('name', 'etag', 'validate_only', ), + 'delete_instance_partition': ('name', 'etag', ), 'get_iam_policy': ('resource', 'options', ), 'get_instance': ('name', 'field_mask', ), 'get_instance_config': ('name', ), + 'get_instance_partition': ('name', ), 'list_instance_config_operations': ('parent', 'filter', 'page_size', 'page_token', ), 'list_instance_configs': ('parent', 'page_size', 'page_token', ), - 'list_instances': ('parent', 'page_size', 'page_token', 'filter', ), + 'list_instance_partition_operations': ('parent', 'filter', 'page_size', 'page_token', 'instance_partition_deadline', ), + 'list_instance_partitions': ('parent', 'page_size', 'page_token', 'instance_partition_deadline', ), + 'list_instances': ('parent', 'page_size', 'page_token', 'filter', 'instance_deadline', ), 'set_iam_policy': ('resource', 'policy', 'update_mask', ), 'test_iam_permissions': ('resource', 'permissions', ), 'update_instance': ('instance', 'field_mask', ), 'update_instance_config': ('instance_config', 'update_mask', 'validate_only', ), + 'update_instance_partition': ('instance_partition', 'field_mask', ), } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: diff --git a/scripts/fixup_spanner_v1_keywords.py b/scripts/fixup_spanner_v1_keywords.py index 939da961f0..da54fd7fa1 100644 --- a/scripts/fixup_spanner_v1_keywords.py +++ b/scripts/fixup_spanner_v1_keywords.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ class spannerCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { 'batch_create_sessions': ('database', 'session_count', 'session_template', ), - 'batch_write': ('session', 'mutation_groups', 'request_options', ), + 'batch_write': ('session', 'mutation_groups', 'request_options', 'exclude_txn_from_change_streams', ), 'begin_transaction': ('session', 'options', 'request_options', ), 'commit': ('session', 'transaction_id', 'single_use_transaction', 'mutations', 'return_commit_stats', 'max_commit_delay', 'request_options', ), 'create_session': ('database', 'session', ), diff --git a/tests/__init__.py b/tests/__init__.py index 89a37dc92c..8f6cf06824 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py index 89a37dc92c..8f6cf06824 100644 --- a/tests/unit/__init__.py +++ b/tests/unit/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/gapic/__init__.py b/tests/unit/gapic/__init__.py index 89a37dc92c..8f6cf06824 100644 --- a/tests/unit/gapic/__init__.py +++ b/tests/unit/gapic/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/gapic/spanner_admin_database_v1/__init__.py b/tests/unit/gapic/spanner_admin_database_v1/__init__.py index 89a37dc92c..8f6cf06824 100644 --- a/tests/unit/gapic/spanner_admin_database_v1/__init__.py +++ b/tests/unit/gapic/spanner_admin_database_v1/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/gapic/spanner_admin_database_v1/test_database_admin.py b/tests/unit/gapic/spanner_admin_database_v1/test_database_admin.py index 6f9f99b5d1..58afc8e591 100644 --- a/tests/unit/gapic/spanner_admin_database_v1/test_database_admin.py +++ b/tests/unit/gapic/spanner_admin_database_v1/test_database_admin.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ import json import math import pytest +from google.api_core import api_core_version from proto.marshal.rules.dates import DurationRule, TimestampRule from proto.marshal.rules import wrappers from requests import Response @@ -90,6 +91,17 @@ def modify_default_endpoint(client): ) +# If default endpoint template is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint template so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint_template(client): + return ( + "test.{UNIVERSE_DOMAIN}" + if ("localhost" in client._DEFAULT_ENDPOINT_TEMPLATE) + else client._DEFAULT_ENDPOINT_TEMPLATE + ) + + def test__get_default_mtls_endpoint(): api_endpoint = "example.googleapis.com" api_mtls_endpoint = "example.mtls.googleapis.com" @@ -119,6 +131,270 @@ def test__get_default_mtls_endpoint(): ) +def test__read_environment_variables(): + assert DatabaseAdminClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert DatabaseAdminClient._read_environment_variables() == (True, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert DatabaseAdminClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + DatabaseAdminClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + assert DatabaseAdminClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert DatabaseAdminClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert DatabaseAdminClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + DatabaseAdminClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_CLOUD_UNIVERSE_DOMAIN": "foo.com"}): + assert DatabaseAdminClient._read_environment_variables() == ( + False, + "auto", + "foo.com", + ) + + +def test__get_client_cert_source(): + mock_provided_cert_source = mock.Mock() + mock_default_cert_source = mock.Mock() + + assert DatabaseAdminClient._get_client_cert_source(None, False) is None + assert ( + DatabaseAdminClient._get_client_cert_source(mock_provided_cert_source, False) + is None + ) + assert ( + DatabaseAdminClient._get_client_cert_source(mock_provided_cert_source, True) + == mock_provided_cert_source + ) + + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", return_value=True + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_default_cert_source, + ): + assert ( + DatabaseAdminClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + DatabaseAdminClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + DatabaseAdminClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(DatabaseAdminClient), +) +@mock.patch.object( + DatabaseAdminAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(DatabaseAdminAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = DatabaseAdminClient._DEFAULT_UNIVERSE + default_endpoint = DatabaseAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = DatabaseAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + DatabaseAdminClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + DatabaseAdminClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == DatabaseAdminClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + DatabaseAdminClient._get_api_endpoint(None, None, default_universe, "auto") + == default_endpoint + ) + assert ( + DatabaseAdminClient._get_api_endpoint(None, None, default_universe, "always") + == DatabaseAdminClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + DatabaseAdminClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == DatabaseAdminClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + DatabaseAdminClient._get_api_endpoint(None, None, mock_universe, "never") + == mock_endpoint + ) + assert ( + DatabaseAdminClient._get_api_endpoint(None, None, default_universe, "never") + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + DatabaseAdminClient._get_api_endpoint( + None, mock_client_cert_source, mock_universe, "auto" + ) + assert ( + str(excinfo.value) + == "mTLS is not supported in any universe other than googleapis.com." + ) + + +def test__get_universe_domain(): + client_universe_domain = "foo.com" + universe_domain_env = "bar.com" + + assert ( + DatabaseAdminClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + DatabaseAdminClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + DatabaseAdminClient._get_universe_domain(None, None) + == DatabaseAdminClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + DatabaseAdminClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (DatabaseAdminClient, transports.DatabaseAdminGrpcTransport, "grpc"), + (DatabaseAdminClient, transports.DatabaseAdminRestTransport, "rest"), + ], +) +def test__validate_universe_domain(client_class, transport_class, transport_name): + client = client_class( + transport=transport_class(credentials=ga_credentials.AnonymousCredentials()) + ) + assert client._validate_universe_domain() == True + + # Test the case when universe is already validated. + assert client._validate_universe_domain() == True + + if transport_name == "grpc": + # Test the case where credentials are provided by the + # `local_channel_credentials`. The default universes in both match. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + client = client_class(transport=transport_class(channel=channel)) + assert client._validate_universe_domain() == True + + # Test the case where credentials do not exist: e.g. a transport is provided + # with no credentials. Validation should still succeed because there is no + # mismatch with non-existent credentials. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + transport = transport_class(channel=channel) + transport._credentials = None + client = client_class(transport=transport) + assert client._validate_universe_domain() == True + + # TODO: This is needed to cater for older versions of google-auth + # Make this test unconditional once the minimum supported version of + # google-auth becomes 2.23.0 or higher. + google_auth_major, google_auth_minor = [ + int(part) for part in google.auth.__version__.split(".")[0:2] + ] + if google_auth_major > 2 or (google_auth_major == 2 and google_auth_minor >= 23): + credentials = ga_credentials.AnonymousCredentials() + credentials._universe_domain = "foo.com" + # Test the case when there is a universe mismatch from the credentials. + client = client_class(transport=transport_class(credentials=credentials)) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (googleapis.com) does not match the universe domain found in the credentials (foo.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test the case when there is a universe mismatch from the client. + # + # TODO: Make this test unconditional once the minimum supported version of + # google-api-core becomes 2.15.0 or higher. + api_core_major, api_core_minor = [ + int(part) for part in api_core_version.__version__.split(".")[0:2] + ] + if api_core_major > 2 or (api_core_major == 2 and api_core_minor >= 15): + client = client_class( + client_options={"universe_domain": "bar.com"}, + transport=transport_class( + credentials=ga_credentials.AnonymousCredentials(), + ), + ) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (bar.com) does not match the universe domain found in the credentials (googleapis.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test that ValueError is raised if universe_domain is provided via client options and credentials is None + with pytest.raises(ValueError): + client._compare_universes("foo.bar", None) + + @pytest.mark.parametrize( "client_class,transport_name", [ @@ -230,13 +506,13 @@ def test_database_admin_client_get_transport_class(): ) @mock.patch.object( DatabaseAdminClient, - "DEFAULT_ENDPOINT", - modify_default_endpoint(DatabaseAdminClient), + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(DatabaseAdminClient), ) @mock.patch.object( DatabaseAdminAsyncClient, - "DEFAULT_ENDPOINT", - modify_default_endpoint(DatabaseAdminAsyncClient), + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(DatabaseAdminAsyncClient), ) def test_database_admin_client_client_options( client_class, transport_class, transport_name @@ -278,7 +554,9 @@ def test_database_admin_client_client_options( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -308,15 +586,23 @@ def test_database_admin_client_client_options( # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has # unsupported value. with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): + with pytest.raises(MutualTLSChannelError) as excinfo: client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. with mock.patch.dict( os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} ): - with pytest.raises(ValueError): + with pytest.raises(ValueError) as excinfo: client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) # Check the case quota_project_id is provided options = client_options.ClientOptions(quota_project_id="octopus") @@ -326,7 +612,9 @@ def test_database_admin_client_client_options( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id="octopus", @@ -344,7 +632,9 @@ def test_database_admin_client_client_options( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -377,13 +667,13 @@ def test_database_admin_client_client_options( ) @mock.patch.object( DatabaseAdminClient, - "DEFAULT_ENDPOINT", - modify_default_endpoint(DatabaseAdminClient), + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(DatabaseAdminClient), ) @mock.patch.object( DatabaseAdminAsyncClient, - "DEFAULT_ENDPOINT", - modify_default_endpoint(DatabaseAdminAsyncClient), + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(DatabaseAdminAsyncClient), ) @mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) def test_database_admin_client_mtls_env_auto( @@ -406,7 +696,9 @@ def test_database_admin_client_mtls_env_auto( if use_client_cert_env == "false": expected_client_cert_source = None - expected_host = client.DEFAULT_ENDPOINT + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) else: expected_client_cert_source = client_cert_source_callback expected_host = client.DEFAULT_MTLS_ENDPOINT @@ -438,7 +730,9 @@ def test_database_admin_client_mtls_env_auto( return_value=client_cert_source_callback, ): if use_client_cert_env == "false": - expected_host = client.DEFAULT_ENDPOINT + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) expected_client_cert_source = None else: expected_host = client.DEFAULT_MTLS_ENDPOINT @@ -472,7 +766,9 @@ def test_database_admin_client_mtls_env_auto( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -562,6 +858,115 @@ def test_database_admin_client_get_mtls_endpoint_and_cert_source(client_class): assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT assert cert_source == mock_client_cert_source + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + +@pytest.mark.parametrize( + "client_class", [DatabaseAdminClient, DatabaseAdminAsyncClient] +) +@mock.patch.object( + DatabaseAdminClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(DatabaseAdminClient), +) +@mock.patch.object( + DatabaseAdminAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(DatabaseAdminAsyncClient), +) +def test_database_admin_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = DatabaseAdminClient._DEFAULT_UNIVERSE + default_endpoint = DatabaseAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = DatabaseAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + # If ClientOptions.api_endpoint is set and GOOGLE_API_USE_CLIENT_CERTIFICATE="true", + # use ClientOptions.api_endpoint as the api endpoint regardless. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ): + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=api_override + ) + client = client_class( + client_options=options, + credentials=ga_credentials.AnonymousCredentials(), + ) + assert client.api_endpoint == api_override + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == default_endpoint + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="always", + # use the DEFAULT_MTLS_ENDPOINT as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + + # If ClientOptions.api_endpoint is not set, GOOGLE_API_USE_MTLS_ENDPOINT="auto" (default), + # GOOGLE_API_USE_CLIENT_CERTIFICATE="false" (default), default cert source doesn't exist, + # and ClientOptions.universe_domain="bar.com", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with universe domain as the api endpoint. + options = client_options.ClientOptions() + universe_exists = hasattr(options, "universe_domain") + if universe_exists: + options = client_options.ClientOptions(universe_domain=mock_universe) + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + else: + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == ( + mock_endpoint if universe_exists else default_endpoint + ) + assert client.universe_domain == ( + mock_universe if universe_exists else default_universe + ) + + # If ClientOptions does not have a universe domain attribute and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + options = client_options.ClientOptions() + if hasattr(options, "universe_domain"): + delattr(options, "universe_domain") + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == default_endpoint + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -588,7 +993,9 @@ def test_database_admin_client_client_options_scopes( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=["1", "2"], client_cert_source_for_mtls=None, quota_project_id=None, @@ -628,7 +1035,9 @@ def test_database_admin_client_client_options_credentials_file( patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -688,7 +1097,9 @@ def test_database_admin_client_create_channel_credentials_file( patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -757,7 +1168,8 @@ def test_list_databases(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.ListDatabasesRequest() + request = spanner_database_admin.ListDatabasesRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListDatabasesPager) @@ -774,12 +1186,149 @@ def test_list_databases_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_databases), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.list_databases() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.ListDatabasesRequest() +def test_list_databases_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.ListDatabasesRequest( + parent="parent_value", + page_token="page_token_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_databases), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_databases(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.ListDatabasesRequest( + parent="parent_value", + page_token="page_token_value", + ) + + +def test_list_databases_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.list_databases in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.list_databases] = mock_rpc + request = {} + client.list_databases(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_databases(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_databases_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_databases), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_database_admin.ListDatabasesResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_databases() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.ListDatabasesRequest() + + +@pytest.mark.asyncio +async def test_list_databases_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_databases + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_databases + ] = mock_object + + request = {} + await client.list_databases(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_databases(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_list_databases_async( transport: str = "grpc_asyncio", @@ -807,7 +1356,8 @@ async def test_list_databases_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.ListDatabasesRequest() + request = spanner_database_admin.ListDatabasesRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListDatabasesAsyncPager) @@ -964,7 +1514,7 @@ async def test_list_databases_flattened_error_async(): def test_list_databases_pager(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -1014,7 +1564,7 @@ def test_list_databases_pager(transport_name: str = "grpc"): def test_list_databases_pages(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -1056,7 +1606,7 @@ def test_list_databases_pages(transport_name: str = "grpc"): @pytest.mark.asyncio async def test_list_databases_async_pager(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1106,7 +1656,7 @@ async def test_list_databases_async_pager(): @pytest.mark.asyncio async def test_list_databases_async_pages(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1178,7 +1728,8 @@ def test_create_database(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.CreateDatabaseRequest() + request = spanner_database_admin.CreateDatabaseRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -1194,12 +1745,155 @@ def test_create_database_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.create_database() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.CreateDatabaseRequest() +def test_create_database_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.CreateDatabaseRequest( + parent="parent_value", + create_statement="create_statement_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.create_database(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.CreateDatabaseRequest( + parent="parent_value", + create_statement="create_statement_value", + ) + + +def test_create_database_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.create_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.create_database] = mock_rpc + request = {} + client.create_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.create_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_create_database_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_database), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_database() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.CreateDatabaseRequest() + + +@pytest.mark.asyncio +async def test_create_database_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.create_database + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.create_database + ] = mock_object + + request = {} + await client.create_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.create_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_create_database_async( transport: str = "grpc_asyncio", @@ -1225,7 +1919,8 @@ async def test_create_database_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.CreateDatabaseRequest() + request = spanner_database_admin.CreateDatabaseRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -1423,7 +2118,8 @@ def test_get_database(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.GetDatabaseRequest() + request = spanner_database_admin.GetDatabaseRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner_database_admin.Database) @@ -1446,12 +2142,153 @@ def test_get_database_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.get_database() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.GetDatabaseRequest() +def test_get_database_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.GetDatabaseRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_database(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.GetDatabaseRequest( + name="name_value", + ) + + +def test_get_database_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_database] = mock_rpc + request = {} + client.get_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_database_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_database), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_database_admin.Database( + name="name_value", + state=spanner_database_admin.Database.State.CREATING, + version_retention_period="version_retention_period_value", + default_leader="default_leader_value", + database_dialect=common.DatabaseDialect.GOOGLE_STANDARD_SQL, + enable_drop_protection=True, + reconciling=True, + ) + ) + response = await client.get_database() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.GetDatabaseRequest() + + +@pytest.mark.asyncio +async def test_get_database_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_database + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.get_database + ] = mock_object + + request = {} + await client.get_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.get_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_get_database_async( transport: str = "grpc_asyncio", @@ -1485,7 +2322,8 @@ async def test_get_database_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.GetDatabaseRequest() + request = spanner_database_admin.GetDatabaseRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner_database_admin.Database) @@ -1670,30 +2508,168 @@ def test_update_database(request_type, transport: str = "grpc"): response = client.update_database(request) # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) == 1 - _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.UpdateDatabaseRequest() + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = spanner_database_admin.UpdateDatabaseRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_update_database_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_database() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.UpdateDatabaseRequest() + + +def test_update_database_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.UpdateDatabaseRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_database(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.UpdateDatabaseRequest() + + +def test_update_database_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.update_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.update_database] = mock_rpc + request = {} + client.update_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 - # Establish that the response is the type that we expect. - assert isinstance(response, future.Future) + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.update_database(request) + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 -def test_update_database_empty_call(): + +@pytest.mark.asyncio +async def test_update_database_empty_call_async(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. - client = DatabaseAdminClient( + client = DatabaseAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), - transport="grpc", + transport="grpc_asyncio", ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_database), "__call__") as call: - client.update_database() + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.update_database() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.UpdateDatabaseRequest() +@pytest.mark.asyncio +async def test_update_database_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_database + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.update_database + ] = mock_object + + request = {} + await client.update_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.update_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_update_database_async( transport: str = "grpc_asyncio", @@ -1719,7 +2695,8 @@ async def test_update_database_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.UpdateDatabaseRequest() + request = spanner_database_admin.UpdateDatabaseRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -1911,7 +2888,8 @@ def test_update_database_ddl(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.UpdateDatabaseDdlRequest() + request = spanner_database_admin.UpdateDatabaseDdlRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -1929,12 +2907,163 @@ def test_update_database_ddl_empty_call(): with mock.patch.object( type(client.transport.update_database_ddl), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.update_database_ddl() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.UpdateDatabaseDdlRequest() +def test_update_database_ddl_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database="database_value", + operation_id="operation_id_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_database_ddl), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_database_ddl(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.UpdateDatabaseDdlRequest( + database="database_value", + operation_id="operation_id_value", + ) + + +def test_update_database_ddl_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_database_ddl in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_database_ddl + ] = mock_rpc + request = {} + client.update_database_ddl(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.update_database_ddl(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_database_ddl_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_database_ddl), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.update_database_ddl() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.UpdateDatabaseDdlRequest() + + +@pytest.mark.asyncio +async def test_update_database_ddl_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_database_ddl + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.update_database_ddl + ] = mock_object + + request = {} + await client.update_database_ddl(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.update_database_ddl(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_update_database_ddl_async( transport: str = "grpc_asyncio", @@ -1962,7 +3091,8 @@ async def test_update_database_ddl_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.UpdateDatabaseDdlRequest() + request = spanner_database_admin.UpdateDatabaseDdlRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -2160,7 +3290,8 @@ def test_drop_database(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.DropDatabaseRequest() + request = spanner_database_admin.DropDatabaseRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert response is None @@ -2176,12 +3307,143 @@ def test_drop_database_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.drop_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.drop_database() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.DropDatabaseRequest() +def test_drop_database_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.DropDatabaseRequest( + database="database_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.drop_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.drop_database(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.DropDatabaseRequest( + database="database_value", + ) + + +def test_drop_database_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.drop_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.drop_database] = mock_rpc + request = {} + client.drop_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.drop_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_drop_database_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.drop_database), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.drop_database() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.DropDatabaseRequest() + + +@pytest.mark.asyncio +async def test_drop_database_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.drop_database + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.drop_database + ] = mock_object + + request = {} + await client.drop_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.drop_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_drop_database_async( transport: str = "grpc_asyncio", @@ -2205,7 +3467,8 @@ async def test_drop_database_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.DropDatabaseRequest() + request = spanner_database_admin.DropDatabaseRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert response is None @@ -2384,7 +3647,8 @@ def test_get_database_ddl(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.GetDatabaseDdlRequest() + request = spanner_database_admin.GetDatabaseDdlRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner_database_admin.GetDatabaseDdlResponse) @@ -2392,22 +3656,160 @@ def test_get_database_ddl(request_type, transport: str = "grpc"): assert response.proto_descriptors == b"proto_descriptors_blob" -def test_get_database_ddl_empty_call(): +def test_get_database_ddl_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_database_ddl), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_database_ddl() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.GetDatabaseDdlRequest() + + +def test_get_database_ddl_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.GetDatabaseDdlRequest( + database="database_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_database_ddl), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_database_ddl(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.GetDatabaseDdlRequest( + database="database_value", + ) + + +def test_get_database_ddl_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_database_ddl in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_database_ddl + ] = mock_rpc + request = {} + client.get_database_ddl(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_database_ddl(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_database_ddl_empty_call_async(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. - client = DatabaseAdminClient( + client = DatabaseAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), - transport="grpc", + transport="grpc_asyncio", ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_database_ddl), "__call__") as call: - client.get_database_ddl() + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_database_admin.GetDatabaseDdlResponse( + statements=["statements_value"], + proto_descriptors=b"proto_descriptors_blob", + ) + ) + response = await client.get_database_ddl() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.GetDatabaseDdlRequest() +@pytest.mark.asyncio +async def test_get_database_ddl_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_database_ddl + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.get_database_ddl + ] = mock_object + + request = {} + await client.get_database_ddl(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.get_database_ddl(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_get_database_ddl_async( transport: str = "grpc_asyncio", @@ -2436,7 +3838,8 @@ async def test_get_database_ddl_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.GetDatabaseDdlRequest() + request = spanner_database_admin.GetDatabaseDdlRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner_database_admin.GetDatabaseDdlResponse) @@ -2621,7 +4024,8 @@ def test_set_iam_policy(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.SetIamPolicyRequest() + request = iam_policy_pb2.SetIamPolicyRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, policy_pb2.Policy) @@ -2639,12 +4043,148 @@ def test_set_iam_policy_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.set_iam_policy() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == iam_policy_pb2.SetIamPolicyRequest() +def test_set_iam_policy_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = iam_policy_pb2.SetIamPolicyRequest( + resource="resource_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.set_iam_policy(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.SetIamPolicyRequest( + resource="resource_value", + ) + + +def test_set_iam_policy_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.set_iam_policy in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.set_iam_policy] = mock_rpc + request = {} + client.set_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.set_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_set_iam_policy_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + policy_pb2.Policy( + version=774, + etag=b"etag_blob", + ) + ) + response = await client.set_iam_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.SetIamPolicyRequest() + + +@pytest.mark.asyncio +async def test_set_iam_policy_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.set_iam_policy + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.set_iam_policy + ] = mock_object + + request = {} + await client.set_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.set_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_set_iam_policy_async( transport: str = "grpc_asyncio", request_type=iam_policy_pb2.SetIamPolicyRequest @@ -2672,7 +4212,8 @@ async def test_set_iam_policy_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.SetIamPolicyRequest() + request = iam_policy_pb2.SetIamPolicyRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, policy_pb2.Policy) @@ -2871,7 +4412,8 @@ def test_get_iam_policy(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.GetIamPolicyRequest() + request = iam_policy_pb2.GetIamPolicyRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, policy_pb2.Policy) @@ -2889,12 +4431,148 @@ def test_get_iam_policy_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.get_iam_policy() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == iam_policy_pb2.GetIamPolicyRequest() +def test_get_iam_policy_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = iam_policy_pb2.GetIamPolicyRequest( + resource="resource_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_iam_policy(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.GetIamPolicyRequest( + resource="resource_value", + ) + + +def test_get_iam_policy_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_iam_policy in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_iam_policy] = mock_rpc + request = {} + client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_iam_policy_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + policy_pb2.Policy( + version=774, + etag=b"etag_blob", + ) + ) + response = await client.get_iam_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.GetIamPolicyRequest() + + +@pytest.mark.asyncio +async def test_get_iam_policy_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_iam_policy + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.get_iam_policy + ] = mock_object + + request = {} + await client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.get_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_get_iam_policy_async( transport: str = "grpc_asyncio", request_type=iam_policy_pb2.GetIamPolicyRequest @@ -2922,7 +4600,8 @@ async def test_get_iam_policy_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.GetIamPolicyRequest() + request = iam_policy_pb2.GetIamPolicyRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, policy_pb2.Policy) @@ -3121,7 +4800,8 @@ def test_test_iam_permissions(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.TestIamPermissionsRequest() + request = iam_policy_pb2.TestIamPermissionsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, iam_policy_pb2.TestIamPermissionsResponse) @@ -3131,21 +4811,164 @@ def test_test_iam_permissions(request_type, transport: str = "grpc"): def test_test_iam_permissions_empty_call(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. - client = DatabaseAdminClient( + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.test_iam_permissions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.TestIamPermissionsRequest() + + +def test_test_iam_permissions_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = iam_policy_pb2.TestIamPermissionsRequest( + resource="resource_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.test_iam_permissions(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.TestIamPermissionsRequest( + resource="resource_value", + ) + + +def test_test_iam_permissions_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.test_iam_permissions in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.test_iam_permissions + ] = mock_rpc + request = {} + client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.test_iam_permissions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_test_iam_permissions_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), - transport="grpc", + transport="grpc_asyncio", ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( type(client.transport.test_iam_permissions), "__call__" ) as call: - client.test_iam_permissions() + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + iam_policy_pb2.TestIamPermissionsResponse( + permissions=["permissions_value"], + ) + ) + response = await client.test_iam_permissions() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == iam_policy_pb2.TestIamPermissionsRequest() +@pytest.mark.asyncio +async def test_test_iam_permissions_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.test_iam_permissions + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.test_iam_permissions + ] = mock_object + + request = {} + await client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.test_iam_permissions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_test_iam_permissions_async( transport: str = "grpc_asyncio", @@ -3175,7 +4998,8 @@ async def test_test_iam_permissions_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.TestIamPermissionsRequest() + request = iam_policy_pb2.TestIamPermissionsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, iam_policy_pb2.TestIamPermissionsResponse) @@ -3393,7 +5217,8 @@ def test_create_backup(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == gsad_backup.CreateBackupRequest() + request = gsad_backup.CreateBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -3409,12 +5234,155 @@ def test_create_backup_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.create_backup() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == gsad_backup.CreateBackupRequest() +def test_create_backup_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = gsad_backup.CreateBackupRequest( + parent="parent_value", + backup_id="backup_id_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.create_backup(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == gsad_backup.CreateBackupRequest( + parent="parent_value", + backup_id="backup_id_value", + ) + + +def test_create_backup_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.create_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.create_backup] = mock_rpc + request = {} + client.create_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.create_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_create_backup_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_backup), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_backup() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == gsad_backup.CreateBackupRequest() + + +@pytest.mark.asyncio +async def test_create_backup_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.create_backup + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.create_backup + ] = mock_object + + request = {} + await client.create_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.create_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_create_backup_async( transport: str = "grpc_asyncio", request_type=gsad_backup.CreateBackupRequest @@ -3439,7 +5407,8 @@ async def test_create_backup_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == gsad_backup.CreateBackupRequest() + request = gsad_backup.CreateBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -3639,7 +5608,8 @@ def test_copy_backup(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == backup.CopyBackupRequest() + request = backup.CopyBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -3655,12 +5625,157 @@ def test_copy_backup_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.copy_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.copy_backup() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == backup.CopyBackupRequest() +def test_copy_backup_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = backup.CopyBackupRequest( + parent="parent_value", + backup_id="backup_id_value", + source_backup="source_backup_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.copy_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.copy_backup(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.CopyBackupRequest( + parent="parent_value", + backup_id="backup_id_value", + source_backup="source_backup_value", + ) + + +def test_copy_backup_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.copy_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.copy_backup] = mock_rpc + request = {} + client.copy_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.copy_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_copy_backup_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.copy_backup), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.copy_backup() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.CopyBackupRequest() + + +@pytest.mark.asyncio +async def test_copy_backup_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.copy_backup + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.copy_backup + ] = mock_object + + request = {} + await client.copy_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.copy_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_copy_backup_async( transport: str = "grpc_asyncio", request_type=backup.CopyBackupRequest @@ -3685,7 +5800,8 @@ async def test_copy_backup_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == backup.CopyBackupRequest() + request = backup.CopyBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -3903,7 +6019,8 @@ def test_get_backup(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == backup.GetBackupRequest() + request = backup.GetBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, backup.Backup) @@ -3926,12 +6043,151 @@ def test_get_backup_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.get_backup() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == backup.GetBackupRequest() +def test_get_backup_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = backup.GetBackupRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_backup(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.GetBackupRequest( + name="name_value", + ) + + +def test_get_backup_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_backup] = mock_rpc + request = {} + client.get_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_backup_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_backup), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + backup.Backup( + database="database_value", + name="name_value", + size_bytes=1089, + state=backup.Backup.State.CREATING, + referencing_databases=["referencing_databases_value"], + database_dialect=common.DatabaseDialect.GOOGLE_STANDARD_SQL, + referencing_backups=["referencing_backups_value"], + ) + ) + response = await client.get_backup() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.GetBackupRequest() + + +@pytest.mark.asyncio +async def test_get_backup_async_use_cached_wrapped_rpc(transport: str = "grpc_asyncio"): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_backup + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.get_backup + ] = mock_object + + request = {} + await client.get_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.get_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_get_backup_async( transport: str = "grpc_asyncio", request_type=backup.GetBackupRequest @@ -3964,7 +6220,8 @@ async def test_get_backup_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == backup.GetBackupRequest() + request = backup.GetBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, backup.Backup) @@ -4155,7 +6412,8 @@ def test_update_backup(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == gsad_backup.UpdateBackupRequest() + request = gsad_backup.UpdateBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, gsad_backup.Backup) @@ -4178,12 +6436,149 @@ def test_update_backup_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.update_backup() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == gsad_backup.UpdateBackupRequest() +def test_update_backup_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = gsad_backup.UpdateBackupRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_backup(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == gsad_backup.UpdateBackupRequest() + + +def test_update_backup_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.update_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.update_backup] = mock_rpc + request = {} + client.update_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_backup_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_backup), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gsad_backup.Backup( + database="database_value", + name="name_value", + size_bytes=1089, + state=gsad_backup.Backup.State.CREATING, + referencing_databases=["referencing_databases_value"], + database_dialect=common.DatabaseDialect.GOOGLE_STANDARD_SQL, + referencing_backups=["referencing_backups_value"], + ) + ) + response = await client.update_backup() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == gsad_backup.UpdateBackupRequest() + + +@pytest.mark.asyncio +async def test_update_backup_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_backup + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.update_backup + ] = mock_object + + request = {} + await client.update_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.update_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_update_backup_async( transport: str = "grpc_asyncio", request_type=gsad_backup.UpdateBackupRequest @@ -4216,7 +6611,8 @@ async def test_update_backup_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == gsad_backup.UpdateBackupRequest() + request = gsad_backup.UpdateBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, gsad_backup.Backup) @@ -4409,7 +6805,8 @@ def test_delete_backup(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == backup.DeleteBackupRequest() + request = backup.DeleteBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert response is None @@ -4425,12 +6822,143 @@ def test_delete_backup_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.delete_backup() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == backup.DeleteBackupRequest() +def test_delete_backup_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = backup.DeleteBackupRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_backup), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_backup(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.DeleteBackupRequest( + name="name_value", + ) + + +def test_delete_backup_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.delete_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.delete_backup] = mock_rpc + request = {} + client.delete_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.delete_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_backup_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_backup), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_backup() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.DeleteBackupRequest() + + +@pytest.mark.asyncio +async def test_delete_backup_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.delete_backup + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.delete_backup + ] = mock_object + + request = {} + await client.delete_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.delete_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_delete_backup_async( transport: str = "grpc_asyncio", request_type=backup.DeleteBackupRequest @@ -4453,7 +6981,8 @@ async def test_delete_backup_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == backup.DeleteBackupRequest() + request = backup.DeleteBackupRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert response is None @@ -4631,7 +7160,8 @@ def test_list_backups(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == backup.ListBackupsRequest() + request = backup.ListBackupsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListBackupsPager) @@ -4646,12 +7176,151 @@ def test_list_backups_empty_call(): transport="grpc", ) - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.list_backups), "__call__") as call: - client.list_backups() - call.assert_called() - _, args, _ = call.mock_calls[0] - assert args[0] == backup.ListBackupsRequest() + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_backups), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_backups() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.ListBackupsRequest() + + +def test_list_backups_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = backup.ListBackupsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_backups), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_backups(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.ListBackupsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + +def test_list_backups_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.list_backups in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.list_backups] = mock_rpc + request = {} + client.list_backups(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_backups(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_backups_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_backups), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + backup.ListBackupsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_backups() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.ListBackupsRequest() + + +@pytest.mark.asyncio +async def test_list_backups_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_backups + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_backups + ] = mock_object + + request = {} + await client.list_backups(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_backups(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 @pytest.mark.asyncio @@ -4680,7 +7349,8 @@ async def test_list_backups_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == backup.ListBackupsRequest() + request = backup.ListBackupsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListBackupsAsyncPager) @@ -4837,7 +7507,7 @@ async def test_list_backups_flattened_error_async(): def test_list_backups_pager(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -4887,7 +7557,7 @@ def test_list_backups_pager(transport_name: str = "grpc"): def test_list_backups_pages(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -4929,7 +7599,7 @@ def test_list_backups_pages(transport_name: str = "grpc"): @pytest.mark.asyncio async def test_list_backups_async_pager(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -4979,7 +7649,7 @@ async def test_list_backups_async_pager(): @pytest.mark.asyncio async def test_list_backups_async_pages(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -5051,7 +7721,8 @@ def test_restore_database(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.RestoreDatabaseRequest() + request = spanner_database_admin.RestoreDatabaseRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -5067,12 +7738,159 @@ def test_restore_database_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.restore_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.restore_database() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.RestoreDatabaseRequest() +def test_restore_database_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.RestoreDatabaseRequest( + parent="parent_value", + database_id="database_id_value", + backup="backup_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.restore_database), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.restore_database(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.RestoreDatabaseRequest( + parent="parent_value", + database_id="database_id_value", + backup="backup_value", + ) + + +def test_restore_database_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.restore_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.restore_database + ] = mock_rpc + request = {} + client.restore_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.restore_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_restore_database_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.restore_database), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.restore_database() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.RestoreDatabaseRequest() + + +@pytest.mark.asyncio +async def test_restore_database_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.restore_database + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.restore_database + ] = mock_object + + request = {} + await client.restore_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.restore_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_restore_database_async( transport: str = "grpc_asyncio", @@ -5098,7 +7916,8 @@ async def test_restore_database_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.RestoreDatabaseRequest() + request = spanner_database_admin.RestoreDatabaseRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -5298,7 +8117,8 @@ def test_list_database_operations(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.ListDatabaseOperationsRequest() + request = spanner_database_admin.ListDatabaseOperationsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListDatabaseOperationsPager) @@ -5317,12 +8137,160 @@ def test_list_database_operations_empty_call(): with mock.patch.object( type(client.transport.list_database_operations), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.list_database_operations() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.ListDatabaseOperationsRequest() +def test_list_database_operations_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.ListDatabaseOperationsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_database_operations), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_database_operations(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.ListDatabaseOperationsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + +def test_list_database_operations_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_database_operations + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_database_operations + ] = mock_rpc + request = {} + client.list_database_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_database_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_database_operations_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_database_operations), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_database_admin.ListDatabaseOperationsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_database_operations() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.ListDatabaseOperationsRequest() + + +@pytest.mark.asyncio +async def test_list_database_operations_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_database_operations + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_database_operations + ] = mock_object + + request = {} + await client.list_database_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_database_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_list_database_operations_async( transport: str = "grpc_asyncio", @@ -5352,7 +8320,8 @@ async def test_list_database_operations_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.ListDatabaseOperationsRequest() + request = spanner_database_admin.ListDatabaseOperationsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListDatabaseOperationsAsyncPager) @@ -5517,7 +8486,7 @@ async def test_list_database_operations_flattened_error_async(): def test_list_database_operations_pager(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -5569,7 +8538,7 @@ def test_list_database_operations_pager(transport_name: str = "grpc"): def test_list_database_operations_pages(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -5613,7 +8582,7 @@ def test_list_database_operations_pages(transport_name: str = "grpc"): @pytest.mark.asyncio async def test_list_database_operations_async_pager(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -5665,7 +8634,7 @@ async def test_list_database_operations_async_pager(): @pytest.mark.asyncio async def test_list_database_operations_async_pages(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -5726,48 +8695,197 @@ def test_list_backup_operations(request_type, transport: str = "grpc"): transport=transport, ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_backup_operations), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = backup.ListBackupOperationsResponse( + next_page_token="next_page_token_value", + ) + response = client.list_backup_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = backup.ListBackupOperationsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListBackupOperationsPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_backup_operations_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_backup_operations), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_backup_operations() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.ListBackupOperationsRequest() + + +def test_list_backup_operations_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = backup.ListBackupOperationsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_backup_operations), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_backup_operations(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == backup.ListBackupOperationsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + +def test_list_backup_operations_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_backup_operations + in client._transport._wrapped_methods + ) - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.list_backup_operations), "__call__" - ) as call: - # Designate an appropriate return value for the call. - call.return_value = backup.ListBackupOperationsResponse( - next_page_token="next_page_token_value", + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. ) - response = client.list_backup_operations(request) + client._transport._wrapped_methods[ + client._transport.list_backup_operations + ] = mock_rpc + request = {} + client.list_backup_operations(request) # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) == 1 - _, args, _ = call.mock_calls[0] - assert args[0] == backup.ListBackupOperationsRequest() + assert mock_rpc.call_count == 1 - # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListBackupOperationsPager) - assert response.next_page_token == "next_page_token_value" + client.list_backup_operations(request) + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 -def test_list_backup_operations_empty_call(): + +@pytest.mark.asyncio +async def test_list_backup_operations_empty_call_async(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. - client = DatabaseAdminClient( + client = DatabaseAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), - transport="grpc", + transport="grpc_asyncio", ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( type(client.transport.list_backup_operations), "__call__" ) as call: - client.list_backup_operations() + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + backup.ListBackupOperationsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_backup_operations() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == backup.ListBackupOperationsRequest() +@pytest.mark.asyncio +async def test_list_backup_operations_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_backup_operations + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_backup_operations + ] = mock_object + + request = {} + await client.list_backup_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_backup_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_list_backup_operations_async( transport: str = "grpc_asyncio", request_type=backup.ListBackupOperationsRequest @@ -5796,7 +8914,8 @@ async def test_list_backup_operations_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == backup.ListBackupOperationsRequest() + request = backup.ListBackupOperationsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListBackupOperationsAsyncPager) @@ -5961,7 +9080,7 @@ async def test_list_backup_operations_flattened_error_async(): def test_list_backup_operations_pager(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -6013,7 +9132,7 @@ def test_list_backup_operations_pager(transport_name: str = "grpc"): def test_list_backup_operations_pages(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -6057,7 +9176,7 @@ def test_list_backup_operations_pages(transport_name: str = "grpc"): @pytest.mark.asyncio async def test_list_backup_operations_async_pager(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -6109,7 +9228,7 @@ async def test_list_backup_operations_async_pager(): @pytest.mark.asyncio async def test_list_backup_operations_async_pages(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -6187,7 +9306,8 @@ def test_list_database_roles(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.ListDatabaseRolesRequest() + request = spanner_database_admin.ListDatabaseRolesRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListDatabaseRolesPager) @@ -6206,12 +9326,157 @@ def test_list_database_roles_empty_call(): with mock.patch.object( type(client.transport.list_database_roles), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.list_database_roles() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_database_admin.ListDatabaseRolesRequest() +def test_list_database_roles_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_database_admin.ListDatabaseRolesRequest( + parent="parent_value", + page_token="page_token_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_database_roles), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_database_roles(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.ListDatabaseRolesRequest( + parent="parent_value", + page_token="page_token_value", + ) + + +def test_list_database_roles_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_database_roles in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_database_roles + ] = mock_rpc + request = {} + client.list_database_roles(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_database_roles(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_database_roles_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_database_roles), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_database_admin.ListDatabaseRolesResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_database_roles() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_database_admin.ListDatabaseRolesRequest() + + +@pytest.mark.asyncio +async def test_list_database_roles_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DatabaseAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_database_roles + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_database_roles + ] = mock_object + + request = {} + await client.list_database_roles(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_database_roles(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_list_database_roles_async( transport: str = "grpc_asyncio", @@ -6241,7 +9506,8 @@ async def test_list_database_roles_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_database_admin.ListDatabaseRolesRequest() + request = spanner_database_admin.ListDatabaseRolesRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListDatabaseRolesAsyncPager) @@ -6406,7 +9672,7 @@ async def test_list_database_roles_flattened_error_async(): def test_list_database_roles_pager(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -6458,7 +9724,7 @@ def test_list_database_roles_pager(transport_name: str = "grpc"): def test_list_database_roles_pages(transport_name: str = "grpc"): client = DatabaseAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -6502,7 +9768,7 @@ def test_list_database_roles_pages(transport_name: str = "grpc"): @pytest.mark.asyncio async def test_list_database_roles_async_pager(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -6556,7 +9822,7 @@ async def test_list_database_roles_async_pager(): @pytest.mark.asyncio async def test_list_database_roles_async_pages(): client = DatabaseAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -6644,6 +9910,42 @@ def test_list_databases_rest(request_type): assert response.next_page_token == "next_page_token_value" +def test_list_databases_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.list_databases in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.list_databases] = mock_rpc + + request = {} + client.list_databases(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_databases(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_list_databases_rest_required_fields( request_type=spanner_database_admin.ListDatabasesRequest, ): @@ -6654,11 +9956,7 @@ def test_list_databases_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -6983,6 +10281,46 @@ def test_create_database_rest(request_type): assert response.operation.name == "operations/spam" +def test_create_database_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.create_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.create_database] = mock_rpc + + request = {} + client.create_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.create_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_create_database_rest_required_fields( request_type=spanner_database_admin.CreateDatabaseRequest, ): @@ -6994,11 +10332,7 @@ def test_create_database_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -7277,6 +10611,42 @@ def test_get_database_rest(request_type): assert response.reconciling is True +def test_get_database_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_database] = mock_rpc + + request = {} + client.get_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_get_database_rest_required_fields( request_type=spanner_database_admin.GetDatabaseRequest, ): @@ -7287,11 +10657,7 @@ def test_get_database_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -7650,6 +11016,46 @@ def get_message_fields(field): assert response.operation.name == "operations/spam" +def test_update_database_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.update_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.update_database] = mock_rpc + + request = {} + client.update_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.update_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_update_database_rest_required_fields( request_type=spanner_database_admin.UpdateDatabaseRequest, ): @@ -7659,11 +11065,7 @@ def test_update_database_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -7925,6 +11327,50 @@ def test_update_database_ddl_rest(request_type): assert response.operation.name == "operations/spam" +def test_update_database_ddl_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_database_ddl in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_database_ddl + ] = mock_rpc + + request = {} + client.update_database_ddl(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.update_database_ddl(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_update_database_ddl_rest_required_fields( request_type=spanner_database_admin.UpdateDatabaseDdlRequest, ): @@ -7936,11 +11382,7 @@ def test_update_database_ddl_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -8198,12 +11640,48 @@ def test_drop_database_rest(request_type): response_value.status_code = 200 json_return_value = "" - response_value._content = json_return_value.encode("UTF-8") - req.return_value = response_value - response = client.drop_database(request) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.drop_database(request) + + # Establish that the response is the type that we expect. + assert response is None + + +def test_drop_database_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.drop_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.drop_database] = mock_rpc + + request = {} + client.drop_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 - # Establish that the response is the type that we expect. - assert response is None + client.drop_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 def test_drop_database_rest_required_fields( @@ -8216,11 +11694,7 @@ def test_drop_database_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -8468,6 +11942,44 @@ def test_get_database_ddl_rest(request_type): assert response.proto_descriptors == b"proto_descriptors_blob" +def test_get_database_ddl_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_database_ddl in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_database_ddl + ] = mock_rpc + + request = {} + client.get_database_ddl(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_database_ddl(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_get_database_ddl_rest_required_fields( request_type=spanner_database_admin.GetDatabaseDdlRequest, ): @@ -8478,11 +11990,7 @@ def test_get_database_ddl_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -8745,6 +12253,42 @@ def test_set_iam_policy_rest(request_type): assert response.etag == b"etag_blob" +def test_set_iam_policy_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.set_iam_policy in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.set_iam_policy] = mock_rpc + + request = {} + client.set_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.set_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_set_iam_policy_rest_required_fields( request_type=iam_policy_pb2.SetIamPolicyRequest, ): @@ -8755,11 +12299,7 @@ def test_set_iam_policy_rest_required_fields( request = request_type(**request_init) pb_request = request jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -9019,6 +12559,42 @@ def test_get_iam_policy_rest(request_type): assert response.etag == b"etag_blob" +def test_get_iam_policy_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_iam_policy in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_iam_policy] = mock_rpc + + request = {} + client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_get_iam_policy_rest_required_fields( request_type=iam_policy_pb2.GetIamPolicyRequest, ): @@ -9029,11 +12605,7 @@ def test_get_iam_policy_rest_required_fields( request = request_type(**request_init) pb_request = request jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -9283,6 +12855,46 @@ def test_test_iam_permissions_rest(request_type): assert response.permissions == ["permissions_value"] +def test_test_iam_permissions_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.test_iam_permissions in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.test_iam_permissions + ] = mock_rpc + + request = {} + client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.test_iam_permissions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_test_iam_permissions_rest_required_fields( request_type=iam_policy_pb2.TestIamPermissionsRequest, ): @@ -9294,11 +12906,7 @@ def test_test_iam_permissions_rest_required_fields( request = request_type(**request_init) pb_request = request jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -9660,6 +13268,46 @@ def get_message_fields(field): assert response.operation.name == "operations/spam" +def test_create_backup_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.create_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.create_backup] = mock_rpc + + request = {} + client.create_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.create_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_create_backup_rest_required_fields( request_type=gsad_backup.CreateBackupRequest, ): @@ -9671,11 +13319,7 @@ def test_create_backup_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -9961,6 +13605,46 @@ def test_copy_backup_rest(request_type): assert response.operation.name == "operations/spam" +def test_copy_backup_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.copy_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.copy_backup] = mock_rpc + + request = {} + client.copy_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.copy_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_copy_backup_rest_required_fields(request_type=backup.CopyBackupRequest): transport_class = transports.DatabaseAdminRestTransport @@ -9971,11 +13655,7 @@ def test_copy_backup_rest_required_fields(request_type=backup.CopyBackupRequest) request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -10262,6 +13942,42 @@ def test_get_backup_rest(request_type): assert response.referencing_backups == ["referencing_backups_value"] +def test_get_backup_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_backup] = mock_rpc + + request = {} + client.get_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_get_backup_rest_required_fields(request_type=backup.GetBackupRequest): transport_class = transports.DatabaseAdminRestTransport @@ -10270,11 +13986,7 @@ def test_get_backup_rest_required_fields(request_type=backup.GetBackupRequest): request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -10640,6 +14352,42 @@ def get_message_fields(field): assert response.referencing_backups == ["referencing_backups_value"] +def test_update_backup_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.update_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.update_backup] = mock_rpc + + request = {} + client.update_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_update_backup_rest_required_fields( request_type=gsad_backup.UpdateBackupRequest, ): @@ -10649,11 +14397,7 @@ def test_update_backup_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -10916,6 +14660,42 @@ def test_delete_backup_rest(request_type): assert response is None +def test_delete_backup_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.delete_backup in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.delete_backup] = mock_rpc + + request = {} + client.delete_backup(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.delete_backup(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_delete_backup_rest_required_fields(request_type=backup.DeleteBackupRequest): transport_class = transports.DatabaseAdminRestTransport @@ -10924,11 +14704,7 @@ def test_delete_backup_rest_required_fields(request_type=backup.DeleteBackupRequ request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -11169,6 +14945,42 @@ def test_list_backups_rest(request_type): assert response.next_page_token == "next_page_token_value" +def test_list_backups_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.list_backups in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.list_backups] = mock_rpc + + request = {} + client.list_backups(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_backups(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_list_backups_rest_required_fields(request_type=backup.ListBackupsRequest): transport_class = transports.DatabaseAdminRestTransport @@ -11177,11 +14989,7 @@ def test_list_backups_rest_required_fields(request_type=backup.ListBackupsReques request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -11502,6 +15310,48 @@ def test_restore_database_rest(request_type): assert response.operation.name == "operations/spam" +def test_restore_database_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.restore_database in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.restore_database + ] = mock_rpc + + request = {} + client.restore_database(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.restore_database(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_restore_database_rest_required_fields( request_type=spanner_database_admin.RestoreDatabaseRequest, ): @@ -11513,11 +15363,7 @@ def test_restore_database_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -11788,6 +15634,47 @@ def test_list_database_operations_rest(request_type): assert response.next_page_token == "next_page_token_value" +def test_list_database_operations_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_database_operations + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_database_operations + ] = mock_rpc + + request = {} + client.list_database_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_database_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_list_database_operations_rest_required_fields( request_type=spanner_database_admin.ListDatabaseOperationsRequest, ): @@ -11798,11 +15685,7 @@ def test_list_database_operations_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -12141,6 +16024,47 @@ def test_list_backup_operations_rest(request_type): assert response.next_page_token == "next_page_token_value" +def test_list_backup_operations_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_backup_operations + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_backup_operations + ] = mock_rpc + + request = {} + client.list_backup_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_backup_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_list_backup_operations_rest_required_fields( request_type=backup.ListBackupOperationsRequest, ): @@ -12151,11 +16075,7 @@ def test_list_backup_operations_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -12486,6 +16406,46 @@ def test_list_database_roles_rest(request_type): assert response.next_page_token == "next_page_token_value" +def test_list_database_roles_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DatabaseAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_database_roles in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_database_roles + ] = mock_rpc + + request = {} + client.list_database_roles(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_database_roles(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_list_database_roles_rest_required_fields( request_type=spanner_database_admin.ListDatabaseRolesRequest, ): @@ -12496,11 +16456,7 @@ def test_list_database_roles_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -12833,7 +16789,7 @@ def test_credentials_transport_error(): ) # It is an error to provide an api_key and a credential. - options = mock.Mock() + options = client_options.ClientOptions() options.api_key = "api_key" with pytest.raises(ValueError): client = DatabaseAdminClient( @@ -14657,7 +18613,9 @@ def test_api_key_credentials(client_class, transport_class): patched.assert_called_once_with( credentials=mock_cred, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, diff --git a/tests/unit/gapic/spanner_admin_instance_v1/__init__.py b/tests/unit/gapic/spanner_admin_instance_v1/__init__.py index 89a37dc92c..8f6cf06824 100644 --- a/tests/unit/gapic/spanner_admin_instance_v1/__init__.py +++ b/tests/unit/gapic/spanner_admin_instance_v1/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/gapic/spanner_admin_instance_v1/test_instance_admin.py b/tests/unit/gapic/spanner_admin_instance_v1/test_instance_admin.py index ac621afc00..77ac0d813b 100644 --- a/tests/unit/gapic/spanner_admin_instance_v1/test_instance_admin.py +++ b/tests/unit/gapic/spanner_admin_instance_v1/test_instance_admin.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ import json import math import pytest +from google.api_core import api_core_version from proto.marshal.rules.dates import DurationRule, TimestampRule from proto.marshal.rules import wrappers from requests import Response @@ -84,6 +85,17 @@ def modify_default_endpoint(client): ) +# If default endpoint template is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint template so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint_template(client): + return ( + "test.{UNIVERSE_DOMAIN}" + if ("localhost" in client._DEFAULT_ENDPOINT_TEMPLATE) + else client._DEFAULT_ENDPOINT_TEMPLATE + ) + + def test__get_default_mtls_endpoint(): api_endpoint = "example.googleapis.com" api_mtls_endpoint = "example.mtls.googleapis.com" @@ -113,6 +125,270 @@ def test__get_default_mtls_endpoint(): ) +def test__read_environment_variables(): + assert InstanceAdminClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert InstanceAdminClient._read_environment_variables() == (True, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert InstanceAdminClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + InstanceAdminClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + assert InstanceAdminClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert InstanceAdminClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert InstanceAdminClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + InstanceAdminClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_CLOUD_UNIVERSE_DOMAIN": "foo.com"}): + assert InstanceAdminClient._read_environment_variables() == ( + False, + "auto", + "foo.com", + ) + + +def test__get_client_cert_source(): + mock_provided_cert_source = mock.Mock() + mock_default_cert_source = mock.Mock() + + assert InstanceAdminClient._get_client_cert_source(None, False) is None + assert ( + InstanceAdminClient._get_client_cert_source(mock_provided_cert_source, False) + is None + ) + assert ( + InstanceAdminClient._get_client_cert_source(mock_provided_cert_source, True) + == mock_provided_cert_source + ) + + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", return_value=True + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_default_cert_source, + ): + assert ( + InstanceAdminClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + InstanceAdminClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + InstanceAdminClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(InstanceAdminClient), +) +@mock.patch.object( + InstanceAdminAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(InstanceAdminAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = InstanceAdminClient._DEFAULT_UNIVERSE + default_endpoint = InstanceAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = InstanceAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + InstanceAdminClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + InstanceAdminClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == InstanceAdminClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + InstanceAdminClient._get_api_endpoint(None, None, default_universe, "auto") + == default_endpoint + ) + assert ( + InstanceAdminClient._get_api_endpoint(None, None, default_universe, "always") + == InstanceAdminClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + InstanceAdminClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == InstanceAdminClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + InstanceAdminClient._get_api_endpoint(None, None, mock_universe, "never") + == mock_endpoint + ) + assert ( + InstanceAdminClient._get_api_endpoint(None, None, default_universe, "never") + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + InstanceAdminClient._get_api_endpoint( + None, mock_client_cert_source, mock_universe, "auto" + ) + assert ( + str(excinfo.value) + == "mTLS is not supported in any universe other than googleapis.com." + ) + + +def test__get_universe_domain(): + client_universe_domain = "foo.com" + universe_domain_env = "bar.com" + + assert ( + InstanceAdminClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + InstanceAdminClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + InstanceAdminClient._get_universe_domain(None, None) + == InstanceAdminClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + InstanceAdminClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (InstanceAdminClient, transports.InstanceAdminGrpcTransport, "grpc"), + (InstanceAdminClient, transports.InstanceAdminRestTransport, "rest"), + ], +) +def test__validate_universe_domain(client_class, transport_class, transport_name): + client = client_class( + transport=transport_class(credentials=ga_credentials.AnonymousCredentials()) + ) + assert client._validate_universe_domain() == True + + # Test the case when universe is already validated. + assert client._validate_universe_domain() == True + + if transport_name == "grpc": + # Test the case where credentials are provided by the + # `local_channel_credentials`. The default universes in both match. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + client = client_class(transport=transport_class(channel=channel)) + assert client._validate_universe_domain() == True + + # Test the case where credentials do not exist: e.g. a transport is provided + # with no credentials. Validation should still succeed because there is no + # mismatch with non-existent credentials. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + transport = transport_class(channel=channel) + transport._credentials = None + client = client_class(transport=transport) + assert client._validate_universe_domain() == True + + # TODO: This is needed to cater for older versions of google-auth + # Make this test unconditional once the minimum supported version of + # google-auth becomes 2.23.0 or higher. + google_auth_major, google_auth_minor = [ + int(part) for part in google.auth.__version__.split(".")[0:2] + ] + if google_auth_major > 2 or (google_auth_major == 2 and google_auth_minor >= 23): + credentials = ga_credentials.AnonymousCredentials() + credentials._universe_domain = "foo.com" + # Test the case when there is a universe mismatch from the credentials. + client = client_class(transport=transport_class(credentials=credentials)) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (googleapis.com) does not match the universe domain found in the credentials (foo.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test the case when there is a universe mismatch from the client. + # + # TODO: Make this test unconditional once the minimum supported version of + # google-api-core becomes 2.15.0 or higher. + api_core_major, api_core_minor = [ + int(part) for part in api_core_version.__version__.split(".")[0:2] + ] + if api_core_major > 2 or (api_core_major == 2 and api_core_minor >= 15): + client = client_class( + client_options={"universe_domain": "bar.com"}, + transport=transport_class( + credentials=ga_credentials.AnonymousCredentials(), + ), + ) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (bar.com) does not match the universe domain found in the credentials (googleapis.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test that ValueError is raised if universe_domain is provided via client options and credentials is None + with pytest.raises(ValueError): + client._compare_universes("foo.bar", None) + + @pytest.mark.parametrize( "client_class,transport_name", [ @@ -224,13 +500,13 @@ def test_instance_admin_client_get_transport_class(): ) @mock.patch.object( InstanceAdminClient, - "DEFAULT_ENDPOINT", - modify_default_endpoint(InstanceAdminClient), + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(InstanceAdminClient), ) @mock.patch.object( InstanceAdminAsyncClient, - "DEFAULT_ENDPOINT", - modify_default_endpoint(InstanceAdminAsyncClient), + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(InstanceAdminAsyncClient), ) def test_instance_admin_client_client_options( client_class, transport_class, transport_name @@ -272,7 +548,9 @@ def test_instance_admin_client_client_options( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -302,15 +580,23 @@ def test_instance_admin_client_client_options( # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has # unsupported value. with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): + with pytest.raises(MutualTLSChannelError) as excinfo: client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. with mock.patch.dict( os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} ): - with pytest.raises(ValueError): + with pytest.raises(ValueError) as excinfo: client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) # Check the case quota_project_id is provided options = client_options.ClientOptions(quota_project_id="octopus") @@ -320,7 +606,9 @@ def test_instance_admin_client_client_options( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id="octopus", @@ -338,7 +626,9 @@ def test_instance_admin_client_client_options( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -371,13 +661,13 @@ def test_instance_admin_client_client_options( ) @mock.patch.object( InstanceAdminClient, - "DEFAULT_ENDPOINT", - modify_default_endpoint(InstanceAdminClient), + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(InstanceAdminClient), ) @mock.patch.object( InstanceAdminAsyncClient, - "DEFAULT_ENDPOINT", - modify_default_endpoint(InstanceAdminAsyncClient), + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(InstanceAdminAsyncClient), ) @mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) def test_instance_admin_client_mtls_env_auto( @@ -400,7 +690,9 @@ def test_instance_admin_client_mtls_env_auto( if use_client_cert_env == "false": expected_client_cert_source = None - expected_host = client.DEFAULT_ENDPOINT + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) else: expected_client_cert_source = client_cert_source_callback expected_host = client.DEFAULT_MTLS_ENDPOINT @@ -432,7 +724,9 @@ def test_instance_admin_client_mtls_env_auto( return_value=client_cert_source_callback, ): if use_client_cert_env == "false": - expected_host = client.DEFAULT_ENDPOINT + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) expected_client_cert_source = None else: expected_host = client.DEFAULT_MTLS_ENDPOINT @@ -466,7 +760,9 @@ def test_instance_admin_client_mtls_env_auto( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -556,6 +852,115 @@ def test_instance_admin_client_get_mtls_endpoint_and_cert_source(client_class): assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT assert cert_source == mock_client_cert_source + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + +@pytest.mark.parametrize( + "client_class", [InstanceAdminClient, InstanceAdminAsyncClient] +) +@mock.patch.object( + InstanceAdminClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(InstanceAdminClient), +) +@mock.patch.object( + InstanceAdminAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(InstanceAdminAsyncClient), +) +def test_instance_admin_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = InstanceAdminClient._DEFAULT_UNIVERSE + default_endpoint = InstanceAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = InstanceAdminClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + # If ClientOptions.api_endpoint is set and GOOGLE_API_USE_CLIENT_CERTIFICATE="true", + # use ClientOptions.api_endpoint as the api endpoint regardless. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ): + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=api_override + ) + client = client_class( + client_options=options, + credentials=ga_credentials.AnonymousCredentials(), + ) + assert client.api_endpoint == api_override + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == default_endpoint + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="always", + # use the DEFAULT_MTLS_ENDPOINT as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + + # If ClientOptions.api_endpoint is not set, GOOGLE_API_USE_MTLS_ENDPOINT="auto" (default), + # GOOGLE_API_USE_CLIENT_CERTIFICATE="false" (default), default cert source doesn't exist, + # and ClientOptions.universe_domain="bar.com", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with universe domain as the api endpoint. + options = client_options.ClientOptions() + universe_exists = hasattr(options, "universe_domain") + if universe_exists: + options = client_options.ClientOptions(universe_domain=mock_universe) + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + else: + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == ( + mock_endpoint if universe_exists else default_endpoint + ) + assert client.universe_domain == ( + mock_universe if universe_exists else default_universe + ) + + # If ClientOptions does not have a universe domain attribute and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + options = client_options.ClientOptions() + if hasattr(options, "universe_domain"): + delattr(options, "universe_domain") + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == default_endpoint + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -582,7 +987,9 @@ def test_instance_admin_client_client_options_scopes( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=["1", "2"], client_cert_source_for_mtls=None, quota_project_id=None, @@ -622,7 +1029,9 @@ def test_instance_admin_client_client_options_credentials_file( patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -682,7 +1091,9 @@ def test_instance_admin_client_create_channel_credentials_file( patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -753,7 +1164,8 @@ def test_list_instance_configs(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.ListInstanceConfigsRequest() + request = spanner_instance_admin.ListInstanceConfigsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListInstanceConfigsPager) @@ -772,93 +1184,240 @@ def test_list_instance_configs_empty_call(): with mock.patch.object( type(client.transport.list_instance_configs), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.list_instance_configs() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_instance_admin.ListInstanceConfigsRequest() -@pytest.mark.asyncio -async def test_list_instance_configs_async( - transport: str = "grpc_asyncio", - request_type=spanner_instance_admin.ListInstanceConfigsRequest, -): - client = InstanceAdminAsyncClient( +def test_list_instance_configs_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.ListInstanceConfigsRequest( + parent="parent_value", + page_token="page_token_value", + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( type(client.transport.list_instance_configs), "__call__" ) as call: - # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - spanner_instance_admin.ListInstanceConfigsResponse( - next_page_token="next_page_token_value", - ) + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. ) - response = await client.list_instance_configs(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) + client.list_instance_configs(request=request) + call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.ListInstanceConfigsRequest() - - # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListInstanceConfigsAsyncPager) - assert response.next_page_token == "next_page_token_value" - - -@pytest.mark.asyncio -async def test_list_instance_configs_async_from_dict(): - await test_list_instance_configs_async(request_type=dict) + assert args[0] == spanner_instance_admin.ListInstanceConfigsRequest( + parent="parent_value", + page_token="page_token_value", + ) -def test_list_instance_configs_field_headers(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - ) +def test_list_instance_configs_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) - # Any value that is part of the HTTP/1.1 URI should be sent as - # a field header. Set these to a non-empty value. - request = spanner_instance_admin.ListInstanceConfigsRequest() + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() - request.parent = "parent_value" + # Ensure method has been cached + assert ( + client._transport.list_instance_configs + in client._transport._wrapped_methods + ) - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.list_instance_configs), "__call__" - ) as call: - call.return_value = spanner_instance_admin.ListInstanceConfigsResponse() + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_instance_configs + ] = mock_rpc + request = {} client.list_instance_configs(request) # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) == 1 - _, args, _ = call.mock_calls[0] - assert args[0] == request + assert mock_rpc.call_count == 1 - # Establish that the field header was sent. - _, _, kw = call.mock_calls[0] - assert ( - "x-goog-request-params", - "parent=parent_value", - ) in kw["metadata"] + client.list_instance_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 @pytest.mark.asyncio -async def test_list_instance_configs_field_headers_async(): +async def test_list_instance_configs_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", ) - # Any value that is part of the HTTP/1.1 URI should be sent as - # a field header. Set these to a non-empty value. - request = spanner_instance_admin.ListInstanceConfigsRequest() + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstanceConfigsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_instance_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.ListInstanceConfigsRequest() + + +@pytest.mark.asyncio +async def test_list_instance_configs_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_instance_configs + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_instance_configs + ] = mock_object + + request = {} + await client.list_instance_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_instance_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_instance_configs_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.ListInstanceConfigsRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstanceConfigsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_instance_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.ListInstanceConfigsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListInstanceConfigsAsyncPager) + assert response.next_page_token == "next_page_token_value" + + +@pytest.mark.asyncio +async def test_list_instance_configs_async_from_dict(): + await test_list_instance_configs_async(request_type=dict) + + +def test_list_instance_configs_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.ListInstanceConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_configs), "__call__" + ) as call: + call.return_value = spanner_instance_admin.ListInstanceConfigsResponse() + client.list_instance_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_instance_configs_field_headers_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.ListInstanceConfigsRequest() request.parent = "parent_value" @@ -972,7 +1531,7 @@ async def test_list_instance_configs_flattened_error_async(): def test_list_instance_configs_pager(transport_name: str = "grpc"): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -1026,7 +1585,7 @@ def test_list_instance_configs_pager(transport_name: str = "grpc"): def test_list_instance_configs_pages(transport_name: str = "grpc"): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -1070,7 +1629,7 @@ def test_list_instance_configs_pages(transport_name: str = "grpc"): @pytest.mark.asyncio async def test_list_instance_configs_async_pager(): client = InstanceAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1124,7 +1683,7 @@ async def test_list_instance_configs_async_pager(): @pytest.mark.asyncio async def test_list_instance_configs_async_pages(): client = InstanceAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1209,7 +1768,8 @@ def test_get_instance_config(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.GetInstanceConfigRequest() + request = spanner_instance_admin.GetInstanceConfigRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner_instance_admin.InstanceConfig) @@ -1238,12 +1798,162 @@ def test_get_instance_config_empty_call(): with mock.patch.object( type(client.transport.get_instance_config), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.get_instance_config() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_instance_admin.GetInstanceConfigRequest() +def test_get_instance_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.GetInstanceConfigRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_instance_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.GetInstanceConfigRequest( + name="name_value", + ) + + +def test_get_instance_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_instance_config in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_instance_config + ] = mock_rpc + request = {} + client.get_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_instance_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.InstanceConfig( + name="name_value", + display_name="display_name_value", + config_type=spanner_instance_admin.InstanceConfig.Type.GOOGLE_MANAGED, + base_config="base_config_value", + etag="etag_value", + leader_options=["leader_options_value"], + reconciling=True, + state=spanner_instance_admin.InstanceConfig.State.CREATING, + ) + ) + response = await client.get_instance_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.GetInstanceConfigRequest() + + +@pytest.mark.asyncio +async def test_get_instance_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_instance_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.get_instance_config + ] = mock_object + + request = {} + await client.get_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.get_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_get_instance_config_async( transport: str = "grpc_asyncio", @@ -1280,7 +1990,8 @@ async def test_get_instance_config_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.GetInstanceConfigRequest() + request = spanner_instance_admin.GetInstanceConfigRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner_instance_admin.InstanceConfig) @@ -1481,7 +2192,8 @@ def test_create_instance_config(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.CreateInstanceConfigRequest() + request = spanner_instance_admin.CreateInstanceConfigRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -1499,54 +2211,207 @@ def test_create_instance_config_empty_call(): with mock.patch.object( type(client.transport.create_instance_config), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.create_instance_config() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_instance_admin.CreateInstanceConfigRequest() -@pytest.mark.asyncio -async def test_create_instance_config_async( - transport: str = "grpc_asyncio", - request_type=spanner_instance_admin.CreateInstanceConfigRequest, -): - client = InstanceAdminAsyncClient( +def test_create_instance_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.CreateInstanceConfigRequest( + parent="parent_value", + instance_config_id="instance_config_id_value", + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( type(client.transport.create_instance_config), "__call__" ) as call: - # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - operations_pb2.Operation(name="operations/spam") + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. ) - response = await client.create_instance_config(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) + client.create_instance_config(request=request) + call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.CreateInstanceConfigRequest() + assert args[0] == spanner_instance_admin.CreateInstanceConfigRequest( + parent="parent_value", + instance_config_id="instance_config_id_value", + ) - # Establish that the response is the type that we expect. - assert isinstance(response, future.Future) +def test_create_instance_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) -@pytest.mark.asyncio -async def test_create_instance_config_async_from_dict(): - await test_create_instance_config_async(request_type=dict) + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + # Ensure method has been cached + assert ( + client._transport.create_instance_config + in client._transport._wrapped_methods + ) -def test_create_instance_config_field_headers(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - ) + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.create_instance_config + ] = mock_rpc + request = {} + client.create_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.create_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_create_instance_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_instance_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.CreateInstanceConfigRequest() + + +@pytest.mark.asyncio +async def test_create_instance_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.create_instance_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.create_instance_config + ] = mock_object + + request = {} + await client.create_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.create_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_create_instance_config_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.CreateInstanceConfigRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.CreateInstanceConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_create_instance_config_async_from_dict(): + await test_create_instance_config_async(request_type=dict) + + +def test_create_instance_config_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. @@ -1742,7 +2607,8 @@ def test_update_instance_config(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.UpdateInstanceConfigRequest() + request = spanner_instance_admin.UpdateInstanceConfigRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -1760,12 +2626,158 @@ def test_update_instance_config_empty_call(): with mock.patch.object( type(client.transport.update_instance_config), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.update_instance_config() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_instance_admin.UpdateInstanceConfigRequest() +def test_update_instance_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.UpdateInstanceConfigRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_instance_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.UpdateInstanceConfigRequest() + + +def test_update_instance_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_instance_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_instance_config + ] = mock_rpc + request = {} + client.update_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.update_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_instance_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.update_instance_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.UpdateInstanceConfigRequest() + + +@pytest.mark.asyncio +async def test_update_instance_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_instance_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.update_instance_config + ] = mock_object + + request = {} + await client.update_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.update_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_update_instance_config_async( transport: str = "grpc_asyncio", @@ -1793,7 +2805,8 @@ async def test_update_instance_config_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.UpdateInstanceConfigRequest() + request = spanner_instance_admin.UpdateInstanceConfigRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) @@ -1993,7 +3006,8 @@ def test_delete_instance_config(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.DeleteInstanceConfigRequest() + request = spanner_instance_admin.DeleteInstanceConfigRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert response is None @@ -2011,99 +3025,242 @@ def test_delete_instance_config_empty_call(): with mock.patch.object( type(client.transport.delete_instance_config), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.delete_instance_config() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_instance_admin.DeleteInstanceConfigRequest() -@pytest.mark.asyncio -async def test_delete_instance_config_async( - transport: str = "grpc_asyncio", - request_type=spanner_instance_admin.DeleteInstanceConfigRequest, -): - client = InstanceAdminAsyncClient( +def test_delete_instance_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.DeleteInstanceConfigRequest( + name="name_value", + etag="etag_value", + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( type(client.transport.delete_instance_config), "__call__" ) as call: - # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - response = await client.delete_instance_config(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_instance_config(request=request) + call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.DeleteInstanceConfigRequest() - - # Establish that the response is the type that we expect. - assert response is None - - -@pytest.mark.asyncio -async def test_delete_instance_config_async_from_dict(): - await test_delete_instance_config_async(request_type=dict) + assert args[0] == spanner_instance_admin.DeleteInstanceConfigRequest( + name="name_value", + etag="etag_value", + ) -def test_delete_instance_config_field_headers(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - ) +def test_delete_instance_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) - # Any value that is part of the HTTP/1.1 URI should be sent as - # a field header. Set these to a non-empty value. - request = spanner_instance_admin.DeleteInstanceConfigRequest() + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() - request.name = "name_value" + # Ensure method has been cached + assert ( + client._transport.delete_instance_config + in client._transport._wrapped_methods + ) - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.delete_instance_config), "__call__" - ) as call: - call.return_value = None + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.delete_instance_config + ] = mock_rpc + request = {} client.delete_instance_config(request) # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) == 1 - _, args, _ = call.mock_calls[0] - assert args[0] == request + assert mock_rpc.call_count == 1 - # Establish that the field header was sent. - _, _, kw = call.mock_calls[0] - assert ( - "x-goog-request-params", - "name=name_value", - ) in kw["metadata"] + client.delete_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 @pytest.mark.asyncio -async def test_delete_instance_config_field_headers_async(): +async def test_delete_instance_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", ) - # Any value that is part of the HTTP/1.1 URI should be sent as - # a field header. Set these to a non-empty value. - request = spanner_instance_admin.DeleteInstanceConfigRequest() - - request.name = "name_value" - # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( type(client.transport.delete_instance_config), "__call__" ) as call: + # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - await client.delete_instance_config(request) - - # Establish that the underlying gRPC stub method was called. + response = await client.delete_instance_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.DeleteInstanceConfigRequest() + + +@pytest.mark.asyncio +async def test_delete_instance_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.delete_instance_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.delete_instance_config + ] = mock_object + + request = {} + await client.delete_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.delete_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_instance_config_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.DeleteInstanceConfigRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.DeleteInstanceConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert response is None + + +@pytest.mark.asyncio +async def test_delete_instance_config_async_from_dict(): + await test_delete_instance_config_async(request_type=dict) + + +def test_delete_instance_config_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.DeleteInstanceConfigRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_config), "__call__" + ) as call: + call.return_value = None + client.delete_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_delete_instance_config_field_headers_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.DeleteInstanceConfigRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + await client.delete_instance_config(request) + + # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] assert args[0] == request @@ -2230,7 +3387,8 @@ def test_list_instance_config_operations(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.ListInstanceConfigOperationsRequest() + request = spanner_instance_admin.ListInstanceConfigOperationsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListInstanceConfigOperationsPager) @@ -2249,12 +3407,160 @@ def test_list_instance_config_operations_empty_call(): with mock.patch.object( type(client.transport.list_instance_config_operations), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.list_instance_config_operations() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_instance_admin.ListInstanceConfigOperationsRequest() +def test_list_instance_config_operations_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.ListInstanceConfigOperationsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_config_operations), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_instance_config_operations(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.ListInstanceConfigOperationsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + +def test_list_instance_config_operations_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_instance_config_operations + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_instance_config_operations + ] = mock_rpc + request = {} + client.list_instance_config_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_instance_config_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_instance_config_operations_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_config_operations), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstanceConfigOperationsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_instance_config_operations() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.ListInstanceConfigOperationsRequest() + + +@pytest.mark.asyncio +async def test_list_instance_config_operations_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_instance_config_operations + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_instance_config_operations + ] = mock_object + + request = {} + await client.list_instance_config_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_instance_config_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_list_instance_config_operations_async( transport: str = "grpc_asyncio", @@ -2284,7 +3590,8 @@ async def test_list_instance_config_operations_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.ListInstanceConfigOperationsRequest() + request = spanner_instance_admin.ListInstanceConfigOperationsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListInstanceConfigOperationsAsyncPager) @@ -2455,7 +3762,7 @@ async def test_list_instance_config_operations_flattened_error_async(): def test_list_instance_config_operations_pager(transport_name: str = "grpc"): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -2507,7 +3814,7 @@ def test_list_instance_config_operations_pager(transport_name: str = "grpc"): def test_list_instance_config_operations_pages(transport_name: str = "grpc"): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -2551,7 +3858,7 @@ def test_list_instance_config_operations_pages(transport_name: str = "grpc"): @pytest.mark.asyncio async def test_list_instance_config_operations_async_pager(): client = InstanceAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -2603,7 +3910,7 @@ async def test_list_instance_config_operations_async_pager(): @pytest.mark.asyncio async def test_list_instance_config_operations_async_pages(): client = InstanceAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -2673,17 +3980,20 @@ def test_list_instances(request_type, transport: str = "grpc"): # Designate an appropriate return value for the call. call.return_value = spanner_instance_admin.ListInstancesResponse( next_page_token="next_page_token_value", + unreachable=["unreachable_value"], ) response = client.list_instances(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.ListInstancesRequest() + request = spanner_instance_admin.ListInstancesRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListInstancesPager) assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] def test_list_instances_empty_call(): @@ -2696,68 +4006,211 @@ def test_list_instances_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_instances), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.list_instances() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner_instance_admin.ListInstancesRequest() -@pytest.mark.asyncio -async def test_list_instances_async( - transport: str = "grpc_asyncio", - request_type=spanner_instance_admin.ListInstancesRequest, -): - client = InstanceAdminAsyncClient( +def test_list_instances_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.ListInstancesRequest( + parent="parent_value", + page_token="page_token_value", + filter="filter_value", + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_instances), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - spanner_instance_admin.ListInstancesResponse( - next_page_token="next_page_token_value", - ) + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. ) - response = await client.list_instances(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) + client.list_instances(request=request) + call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.ListInstancesRequest() - - # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListInstancesAsyncPager) - assert response.next_page_token == "next_page_token_value" + assert args[0] == spanner_instance_admin.ListInstancesRequest( + parent="parent_value", + page_token="page_token_value", + filter="filter_value", + ) -@pytest.mark.asyncio -async def test_list_instances_async_from_dict(): - await test_list_instances_async(request_type=dict) +def test_list_instances_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() -def test_list_instances_field_headers(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - ) + # Ensure method has been cached + assert client._transport.list_instances in client._transport._wrapped_methods - # Any value that is part of the HTTP/1.1 URI should be sent as - # a field header. Set these to a non-empty value. - request = spanner_instance_admin.ListInstancesRequest() + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.list_instances] = mock_rpc + request = {} + client.list_instances(request) - request.parent = "parent_value" + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.list_instances), "__call__") as call: - call.return_value = spanner_instance_admin.ListInstancesResponse() client.list_instances(request) - # Establish that the underlying gRPC stub method was called. + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_instances_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_instances), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstancesResponse( + next_page_token="next_page_token_value", + unreachable=["unreachable_value"], + ) + ) + response = await client.list_instances() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.ListInstancesRequest() + + +@pytest.mark.asyncio +async def test_list_instances_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_instances + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_instances + ] = mock_object + + request = {} + await client.list_instances(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_instances(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_instances_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.ListInstancesRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_instances), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstancesResponse( + next_page_token="next_page_token_value", + unreachable=["unreachable_value"], + ) + ) + response = await client.list_instances(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.ListInstancesRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListInstancesAsyncPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] + + +@pytest.mark.asyncio +async def test_list_instances_async_from_dict(): + await test_list_instances_async(request_type=dict) + + +def test_list_instances_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.ListInstancesRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_instances), "__call__") as call: + call.return_value = spanner_instance_admin.ListInstancesResponse() + client.list_instances(request) + + # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] assert args[0] == request @@ -2886,7 +4339,7 @@ async def test_list_instances_flattened_error_async(): def test_list_instances_pager(transport_name: str = "grpc"): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -2936,7 +4389,7 @@ def test_list_instances_pager(transport_name: str = "grpc"): def test_list_instances_pages(transport_name: str = "grpc"): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -2978,7 +4431,7 @@ def test_list_instances_pages(transport_name: str = "grpc"): @pytest.mark.asyncio async def test_list_instances_async_pager(): client = InstanceAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -3028,7 +4481,7 @@ async def test_list_instances_async_pager(): @pytest.mark.asyncio async def test_list_instances_async_pages(): client = InstanceAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -3077,11 +4530,11 @@ async def test_list_instances_async_pages(): @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.GetInstanceRequest, + spanner_instance_admin.ListInstancePartitionsRequest, dict, ], ) -def test_get_instance(request_type, transport: str = "grpc"): +def test_list_instance_partitions(request_type, transport: str = "grpc"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3092,36 +4545,29 @@ def test_get_instance(request_type, transport: str = "grpc"): request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: # Designate an appropriate return value for the call. - call.return_value = spanner_instance_admin.Instance( - name="name_value", - config="config_value", - display_name="display_name_value", - node_count=1070, - processing_units=1743, - state=spanner_instance_admin.Instance.State.CREATING, - endpoint_uris=["endpoint_uris_value"], + call.return_value = spanner_instance_admin.ListInstancePartitionsResponse( + next_page_token="next_page_token_value", + unreachable=["unreachable_value"], ) - response = client.get_instance(request) + response = client.list_instance_partitions(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.GetInstanceRequest() + request = spanner_instance_admin.ListInstancePartitionsRequest() + assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, spanner_instance_admin.Instance) - assert response.name == "name_value" - assert response.config == "config_value" - assert response.display_name == "display_name_value" - assert response.node_count == 1070 - assert response.processing_units == 1743 - assert response.state == spanner_instance_admin.Instance.State.CREATING - assert response.endpoint_uris == ["endpoint_uris_value"] + assert isinstance(response, pagers.ListInstancePartitionsPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] -def test_get_instance_empty_call(): +def test_list_instance_partitions_empty_call(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. client = InstanceAdminClient( @@ -3130,17 +4576,166 @@ def test_get_instance_empty_call(): ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_instance), "__call__") as call: - client.get_instance() + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_instance_partitions() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.GetInstanceRequest() + assert args[0] == spanner_instance_admin.ListInstancePartitionsRequest() + + +def test_list_instance_partitions_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.ListInstancePartitionsRequest( + parent="parent_value", + page_token="page_token_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_instance_partitions(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.ListInstancePartitionsRequest( + parent="parent_value", + page_token="page_token_value", + ) + + +def test_list_instance_partitions_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_instance_partitions + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_instance_partitions + ] = mock_rpc + request = {} + client.list_instance_partitions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_instance_partitions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 @pytest.mark.asyncio -async def test_get_instance_async( +async def test_list_instance_partitions_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstancePartitionsResponse( + next_page_token="next_page_token_value", + unreachable=["unreachable_value"], + ) + ) + response = await client.list_instance_partitions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.ListInstancePartitionsRequest() + + +@pytest.mark.asyncio +async def test_list_instance_partitions_async_use_cached_wrapped_rpc( transport: str = "grpc_asyncio", - request_type=spanner_instance_admin.GetInstanceRequest, +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_instance_partitions + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_instance_partitions + ] = mock_object + + request = {} + await client.list_instance_partitions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_instance_partitions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_instance_partitions_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.ListInstancePartitionsRequest, ): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3152,57 +4747,52 @@ async def test_get_instance_async( request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - spanner_instance_admin.Instance( - name="name_value", - config="config_value", - display_name="display_name_value", - node_count=1070, - processing_units=1743, - state=spanner_instance_admin.Instance.State.CREATING, - endpoint_uris=["endpoint_uris_value"], + spanner_instance_admin.ListInstancePartitionsResponse( + next_page_token="next_page_token_value", + unreachable=["unreachable_value"], ) ) - response = await client.get_instance(request) + response = await client.list_instance_partitions(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.GetInstanceRequest() + request = spanner_instance_admin.ListInstancePartitionsRequest() + assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, spanner_instance_admin.Instance) - assert response.name == "name_value" - assert response.config == "config_value" - assert response.display_name == "display_name_value" - assert response.node_count == 1070 - assert response.processing_units == 1743 - assert response.state == spanner_instance_admin.Instance.State.CREATING - assert response.endpoint_uris == ["endpoint_uris_value"] + assert isinstance(response, pagers.ListInstancePartitionsAsyncPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] @pytest.mark.asyncio -async def test_get_instance_async_from_dict(): - await test_get_instance_async(request_type=dict) +async def test_list_instance_partitions_async_from_dict(): + await test_list_instance_partitions_async(request_type=dict) -def test_get_instance_field_headers(): +def test_list_instance_partitions_field_headers(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = spanner_instance_admin.GetInstanceRequest() + request = spanner_instance_admin.ListInstancePartitionsRequest() - request.name = "name_value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_instance), "__call__") as call: - call.return_value = spanner_instance_admin.Instance() - client.get_instance(request) + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: + call.return_value = spanner_instance_admin.ListInstancePartitionsResponse() + client.list_instance_partitions(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 @@ -3213,28 +4803,30 @@ def test_get_instance_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name_value", + "parent=parent_value", ) in kw["metadata"] @pytest.mark.asyncio -async def test_get_instance_field_headers_async(): +async def test_list_instance_partitions_field_headers_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = spanner_instance_admin.GetInstanceRequest() + request = spanner_instance_admin.ListInstancePartitionsRequest() - request.name = "name_value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - spanner_instance_admin.Instance() + spanner_instance_admin.ListInstancePartitionsResponse() ) - await client.get_instance(request) + await client.list_instance_partitions(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) @@ -3245,35 +4837,37 @@ async def test_get_instance_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "name=name_value", + "parent=parent_value", ) in kw["metadata"] -def test_get_instance_flattened(): +def test_list_instance_partitions_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: # Designate an appropriate return value for the call. - call.return_value = spanner_instance_admin.Instance() + call.return_value = spanner_instance_admin.ListInstancePartitionsResponse() # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - client.get_instance( - name="name_value", + client.list_instance_partitions( + parent="parent_value", ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - arg = args[0].name - mock_val = "name_value" + arg = args[0].parent + mock_val = "parent_value" assert arg == mock_val -def test_get_instance_flattened_error(): +def test_list_instance_partitions_flattened_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -3281,43 +4875,45 @@ def test_get_instance_flattened_error(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.get_instance( - spanner_instance_admin.GetInstanceRequest(), - name="name_value", + client.list_instance_partitions( + spanner_instance_admin.ListInstancePartitionsRequest(), + parent="parent_value", ) @pytest.mark.asyncio -async def test_get_instance_flattened_async(): +async def test_list_instance_partitions_flattened_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: # Designate an appropriate return value for the call. - call.return_value = spanner_instance_admin.Instance() + call.return_value = spanner_instance_admin.ListInstancePartitionsResponse() call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - spanner_instance_admin.Instance() + spanner_instance_admin.ListInstancePartitionsResponse() ) # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - response = await client.get_instance( - name="name_value", + response = await client.list_instance_partitions( + parent="parent_value", ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - arg = args[0].name - mock_val = "name_value" + arg = args[0].parent + mock_val = "parent_value" assert arg == mock_val @pytest.mark.asyncio -async def test_get_instance_flattened_error_async(): +async def test_list_instance_partitions_flattened_error_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -3325,20 +4921,222 @@ async def test_get_instance_flattened_error_async(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - await client.get_instance( - spanner_instance_admin.GetInstanceRequest(), - name="name_value", + await client.list_instance_partitions( + spanner_instance_admin.ListInstancePartitionsRequest(), + parent="parent_value", + ) + + +def test_list_instance_partitions_pager(transport_name: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport_name, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + ), + RuntimeError, + ) + + metadata = () + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)), + ) + pager = client.list_instance_partitions(request={}) + + assert pager._metadata == metadata + + results = list(pager) + assert len(results) == 6 + assert all( + isinstance(i, spanner_instance_admin.InstancePartition) for i in results + ) + + +def test_list_instance_partitions_pages(transport_name: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport_name, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partitions), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + ), + RuntimeError, + ) + pages = list(client.list_instance_partitions(request={}).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.asyncio +async def test_list_instance_partitions_async_pager(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partitions), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + ), + RuntimeError, + ) + async_pager = await client.list_instance_partitions( + request={}, + ) + assert async_pager.next_page_token == "abc" + responses = [] + async for response in async_pager: # pragma: no branch + responses.append(response) + + assert len(responses) == 6 + assert all( + isinstance(i, spanner_instance_admin.InstancePartition) for i in responses + ) + + +@pytest.mark.asyncio +async def test_list_instance_partitions_async_pages(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partitions), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + ), + RuntimeError, ) + pages = [] + # Workaround issue in python 3.9 related to code coverage by adding `# pragma: no branch` + # See https://github.com/googleapis/gapic-generator-python/pull/1174#issuecomment-1025132372 + async for page_ in ( # pragma: no branch + await client.list_instance_partitions(request={}) + ).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.CreateInstanceRequest, + spanner_instance_admin.GetInstanceRequest, dict, ], ) -def test_create_instance(request_type, transport: str = "grpc"): +def test_get_instance(request_type, transport: str = "grpc"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3349,21 +5147,37 @@ def test_create_instance(request_type, transport: str = "grpc"): request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.create_instance), "__call__") as call: + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = operations_pb2.Operation(name="operations/spam") - response = client.create_instance(request) + call.return_value = spanner_instance_admin.Instance( + name="name_value", + config="config_value", + display_name="display_name_value", + node_count=1070, + processing_units=1743, + state=spanner_instance_admin.Instance.State.CREATING, + endpoint_uris=["endpoint_uris_value"], + ) + response = client.get_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.CreateInstanceRequest() + request = spanner_instance_admin.GetInstanceRequest() + assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, future.Future) + assert isinstance(response, spanner_instance_admin.Instance) + assert response.name == "name_value" + assert response.config == "config_value" + assert response.display_name == "display_name_value" + assert response.node_count == 1070 + assert response.processing_units == 1743 + assert response.state == spanner_instance_admin.Instance.State.CREATING + assert response.endpoint_uris == ["endpoint_uris_value"] -def test_create_instance_empty_call(): +def test_get_instance_empty_call(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. client = InstanceAdminClient( @@ -3372,64 +5186,221 @@ def test_create_instance_empty_call(): ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.create_instance), "__call__") as call: - client.create_instance() + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_instance() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.CreateInstanceRequest() + assert args[0] == spanner_instance_admin.GetInstanceRequest() -@pytest.mark.asyncio -async def test_create_instance_async( - transport: str = "grpc_asyncio", - request_type=spanner_instance_admin.CreateInstanceRequest, -): - client = InstanceAdminAsyncClient( +def test_get_instance_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.GetInstanceRequest( + name="name_value", + ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.create_instance), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - operations_pb2.Operation(name="operations/spam") + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. ) - response = await client.create_instance(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) + client.get_instance(request=request) + call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.CreateInstanceRequest() + assert args[0] == spanner_instance_admin.GetInstanceRequest( + name="name_value", + ) - # Establish that the response is the type that we expect. - assert isinstance(response, future.Future) +def test_get_instance_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) -@pytest.mark.asyncio -async def test_create_instance_async_from_dict(): - await test_create_instance_async(request_type=dict) + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + # Ensure method has been cached + assert client._transport.get_instance in client._transport._wrapped_methods -def test_create_instance_field_headers(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - ) + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_instance] = mock_rpc + request = {} + client.get_instance(request) - # Any value that is part of the HTTP/1.1 URI should be sent as - # a field header. Set these to a non-empty value. - request = spanner_instance_admin.CreateInstanceRequest() + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 - request.parent = "parent_value" + client.get_instance(request) - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.create_instance), "__call__") as call: - call.return_value = operations_pb2.Operation(name="operations/op") - client.create_instance(request) + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_instance_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.Instance( + name="name_value", + config="config_value", + display_name="display_name_value", + node_count=1070, + processing_units=1743, + state=spanner_instance_admin.Instance.State.CREATING, + endpoint_uris=["endpoint_uris_value"], + ) + ) + response = await client.get_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.GetInstanceRequest() + + +@pytest.mark.asyncio +async def test_get_instance_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_instance + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.get_instance + ] = mock_object + + request = {} + await client.get_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.get_instance(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_instance_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.GetInstanceRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.Instance( + name="name_value", + config="config_value", + display_name="display_name_value", + node_count=1070, + processing_units=1743, + state=spanner_instance_admin.Instance.State.CREATING, + endpoint_uris=["endpoint_uris_value"], + ) + ) + response = await client.get_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.GetInstanceRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, spanner_instance_admin.Instance) + assert response.name == "name_value" + assert response.config == "config_value" + assert response.display_name == "display_name_value" + assert response.node_count == 1070 + assert response.processing_units == 1743 + assert response.state == spanner_instance_admin.Instance.State.CREATING + assert response.endpoint_uris == ["endpoint_uris_value"] + + +@pytest.mark.asyncio +async def test_get_instance_async_from_dict(): + await test_get_instance_async(request_type=dict) + + +def test_get_instance_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.GetInstanceRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: + call.return_value = spanner_instance_admin.Instance() + client.get_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 @@ -3440,28 +5411,28 @@ def test_create_instance_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "parent=parent_value", + "name=name_value", ) in kw["metadata"] @pytest.mark.asyncio -async def test_create_instance_field_headers_async(): +async def test_get_instance_field_headers_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = spanner_instance_admin.CreateInstanceRequest() + request = spanner_instance_admin.GetInstanceRequest() - request.parent = "parent_value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.create_instance), "__call__") as call: + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - operations_pb2.Operation(name="operations/op") + spanner_instance_admin.Instance() ) - await client.create_instance(request) + await client.get_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) @@ -3472,43 +5443,35 @@ async def test_create_instance_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "parent=parent_value", + "name=name_value", ) in kw["metadata"] -def test_create_instance_flattened(): +def test_get_instance_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.create_instance), "__call__") as call: + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = operations_pb2.Operation(name="operations/op") + call.return_value = spanner_instance_admin.Instance() # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - client.create_instance( - parent="parent_value", - instance_id="instance_id_value", - instance=spanner_instance_admin.Instance(name="name_value"), + client.get_instance( + name="name_value", ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - arg = args[0].parent - mock_val = "parent_value" - assert arg == mock_val - arg = args[0].instance_id - mock_val = "instance_id_value" - assert arg == mock_val - arg = args[0].instance - mock_val = spanner_instance_admin.Instance(name="name_value") + arg = args[0].name + mock_val = "name_value" assert arg == mock_val -def test_create_instance_flattened_error(): +def test_get_instance_flattened_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -3516,53 +5479,43 @@ def test_create_instance_flattened_error(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.create_instance( - spanner_instance_admin.CreateInstanceRequest(), - parent="parent_value", - instance_id="instance_id_value", - instance=spanner_instance_admin.Instance(name="name_value"), + client.get_instance( + spanner_instance_admin.GetInstanceRequest(), + name="name_value", ) @pytest.mark.asyncio -async def test_create_instance_flattened_async(): +async def test_get_instance_flattened_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.create_instance), "__call__") as call: + with mock.patch.object(type(client.transport.get_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = operations_pb2.Operation(name="operations/op") + call.return_value = spanner_instance_admin.Instance() call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - operations_pb2.Operation(name="operations/spam") + spanner_instance_admin.Instance() ) # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - response = await client.create_instance( - parent="parent_value", - instance_id="instance_id_value", - instance=spanner_instance_admin.Instance(name="name_value"), + response = await client.get_instance( + name="name_value", ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - arg = args[0].parent - mock_val = "parent_value" - assert arg == mock_val - arg = args[0].instance_id - mock_val = "instance_id_value" - assert arg == mock_val - arg = args[0].instance - mock_val = spanner_instance_admin.Instance(name="name_value") + arg = args[0].name + mock_val = "name_value" assert arg == mock_val @pytest.mark.asyncio -async def test_create_instance_flattened_error_async(): +async def test_get_instance_flattened_error_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -3570,22 +5523,20 @@ async def test_create_instance_flattened_error_async(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - await client.create_instance( - spanner_instance_admin.CreateInstanceRequest(), - parent="parent_value", - instance_id="instance_id_value", - instance=spanner_instance_admin.Instance(name="name_value"), + await client.get_instance( + spanner_instance_admin.GetInstanceRequest(), + name="name_value", ) @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.UpdateInstanceRequest, + spanner_instance_admin.CreateInstanceRequest, dict, ], ) -def test_update_instance(request_type, transport: str = "grpc"): +def test_create_instance(request_type, transport: str = "grpc"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3596,21 +5547,22 @@ def test_update_instance(request_type, transport: str = "grpc"): request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.update_instance), "__call__") as call: + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") - response = client.update_instance(request) + response = client.create_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.UpdateInstanceRequest() + request = spanner_instance_admin.CreateInstanceRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, future.Future) -def test_update_instance_empty_call(): +def test_create_instance_empty_call(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. client = InstanceAdminClient( @@ -3619,64 +5571,208 @@ def test_update_instance_empty_call(): ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.update_instance), "__call__") as call: - client.update_instance() + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.create_instance() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.UpdateInstanceRequest() + assert args[0] == spanner_instance_admin.CreateInstanceRequest() -@pytest.mark.asyncio -async def test_update_instance_async( - transport: str = "grpc_asyncio", - request_type=spanner_instance_admin.UpdateInstanceRequest, -): - client = InstanceAdminAsyncClient( +def test_create_instance_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.CreateInstanceRequest( + parent="parent_value", + instance_id="instance_id_value", + ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.update_instance), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - operations_pb2.Operation(name="operations/spam") + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. ) - response = await client.update_instance(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) + client.create_instance(request=request) + call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.UpdateInstanceRequest() + assert args[0] == spanner_instance_admin.CreateInstanceRequest( + parent="parent_value", + instance_id="instance_id_value", + ) - # Establish that the response is the type that we expect. - assert isinstance(response, future.Future) +def test_create_instance_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) -@pytest.mark.asyncio -async def test_update_instance_async_from_dict(): - await test_update_instance_async(request_type=dict) + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + # Ensure method has been cached + assert client._transport.create_instance in client._transport._wrapped_methods -def test_update_instance_field_headers(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.create_instance] = mock_rpc + request = {} + client.create_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.create_instance(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_create_instance_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.CreateInstanceRequest() + + +@pytest.mark.asyncio +async def test_create_instance_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.create_instance + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.create_instance + ] = mock_object + + request = {} + await client.create_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.create_instance(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_create_instance_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.CreateInstanceRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.CreateInstanceRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_create_instance_async_from_dict(): + await test_create_instance_async(request_type=dict) + + +def test_create_instance_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = spanner_instance_admin.UpdateInstanceRequest() + request = spanner_instance_admin.CreateInstanceRequest() - request.instance.name = "name_value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.update_instance), "__call__") as call: + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: call.return_value = operations_pb2.Operation(name="operations/op") - client.update_instance(request) + client.create_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 @@ -3687,28 +5783,28 @@ def test_update_instance_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "instance.name=name_value", + "parent=parent_value", ) in kw["metadata"] @pytest.mark.asyncio -async def test_update_instance_field_headers_async(): +async def test_create_instance_field_headers_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = spanner_instance_admin.UpdateInstanceRequest() + request = spanner_instance_admin.CreateInstanceRequest() - request.instance.name = "name_value" + request.parent = "parent_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.update_instance), "__call__") as call: + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") ) - await client.update_instance(request) + await client.create_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) @@ -3719,39 +5815,43 @@ async def test_update_instance_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "instance.name=name_value", + "parent=parent_value", ) in kw["metadata"] -def test_update_instance_flattened(): +def test_create_instance_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.update_instance), "__call__") as call: + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - client.update_instance( + client.create_instance( + parent="parent_value", + instance_id="instance_id_value", instance=spanner_instance_admin.Instance(name="name_value"), - field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].instance_id + mock_val = "instance_id_value" + assert arg == mock_val arg = args[0].instance mock_val = spanner_instance_admin.Instance(name="name_value") assert arg == mock_val - arg = args[0].field_mask - mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) - assert arg == mock_val -def test_update_instance_flattened_error(): +def test_create_instance_flattened_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -3759,21 +5859,22 @@ def test_update_instance_flattened_error(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.update_instance( - spanner_instance_admin.UpdateInstanceRequest(), + client.create_instance( + spanner_instance_admin.CreateInstanceRequest(), + parent="parent_value", + instance_id="instance_id_value", instance=spanner_instance_admin.Instance(name="name_value"), - field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) @pytest.mark.asyncio -async def test_update_instance_flattened_async(): +async def test_create_instance_flattened_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.update_instance), "__call__") as call: + with mock.patch.object(type(client.transport.create_instance), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -3782,25 +5883,29 @@ async def test_update_instance_flattened_async(): ) # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - response = await client.update_instance( + response = await client.create_instance( + parent="parent_value", + instance_id="instance_id_value", instance=spanner_instance_admin.Instance(name="name_value"), - field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].instance_id + mock_val = "instance_id_value" + assert arg == mock_val arg = args[0].instance mock_val = spanner_instance_admin.Instance(name="name_value") assert arg == mock_val - arg = args[0].field_mask - mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) - assert arg == mock_val @pytest.mark.asyncio -async def test_update_instance_flattened_error_async(): +async def test_create_instance_flattened_error_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -3808,21 +5913,22 @@ async def test_update_instance_flattened_error_async(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - await client.update_instance( - spanner_instance_admin.UpdateInstanceRequest(), + await client.create_instance( + spanner_instance_admin.CreateInstanceRequest(), + parent="parent_value", + instance_id="instance_id_value", instance=spanner_instance_admin.Instance(name="name_value"), - field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.DeleteInstanceRequest, + spanner_instance_admin.UpdateInstanceRequest, dict, ], ) -def test_delete_instance(request_type, transport: str = "grpc"): +def test_update_instance(request_type, transport: str = "grpc"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3833,21 +5939,22 @@ def test_delete_instance(request_type, transport: str = "grpc"): request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: + with mock.patch.object(type(client.transport.update_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = None - response = client.delete_instance(request) + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.update_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.DeleteInstanceRequest() + request = spanner_instance_admin.UpdateInstanceRequest() + assert args[0] == request # Establish that the response is the type that we expect. - assert response is None + assert isinstance(response, future.Future) -def test_delete_instance_empty_call(): +def test_update_instance_empty_call(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. client = InstanceAdminClient( @@ -3856,242 +5963,154 @@ def test_delete_instance_empty_call(): ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: - client.delete_instance() + with mock.patch.object(type(client.transport.update_instance), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_instance() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.DeleteInstanceRequest() + assert args[0] == spanner_instance_admin.UpdateInstanceRequest() -@pytest.mark.asyncio -async def test_delete_instance_async( - transport: str = "grpc_asyncio", - request_type=spanner_instance_admin.DeleteInstanceRequest, -): - client = InstanceAdminAsyncClient( +def test_update_instance_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.UpdateInstanceRequest() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - response = await client.delete_instance(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) + with mock.patch.object(type(client.transport.update_instance), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_instance(request=request) + call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == spanner_instance_admin.DeleteInstanceRequest() - - # Establish that the response is the type that we expect. - assert response is None + assert args[0] == spanner_instance_admin.UpdateInstanceRequest() -@pytest.mark.asyncio -async def test_delete_instance_async_from_dict(): - await test_delete_instance_async(request_type=dict) +def test_update_instance_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() -def test_delete_instance_field_headers(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - ) + # Ensure method has been cached + assert client._transport.update_instance in client._transport._wrapped_methods - # Any value that is part of the HTTP/1.1 URI should be sent as - # a field header. Set these to a non-empty value. - request = spanner_instance_admin.DeleteInstanceRequest() + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.update_instance] = mock_rpc + request = {} + client.update_instance(request) - request.name = "name_value" + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: - call.return_value = None - client.delete_instance(request) + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) == 1 - _, args, _ = call.mock_calls[0] - assert args[0] == request + client.update_instance(request) - # Establish that the field header was sent. - _, _, kw = call.mock_calls[0] - assert ( - "x-goog-request-params", - "name=name_value", - ) in kw["metadata"] + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 @pytest.mark.asyncio -async def test_delete_instance_field_headers_async(): +async def test_update_instance_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), - ) - - # Any value that is part of the HTTP/1.1 URI should be sent as - # a field header. Set these to a non-empty value. - request = spanner_instance_admin.DeleteInstanceRequest() - - request.name = "name_value" - - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - await client.delete_instance(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) - _, args, _ = call.mock_calls[0] - assert args[0] == request - - # Establish that the field header was sent. - _, _, kw = call.mock_calls[0] - assert ( - "x-goog-request-params", - "name=name_value", - ) in kw["metadata"] - - -def test_delete_instance_flattened(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: + with mock.patch.object(type(client.transport.update_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = None - # Call the method with a truthy value for each flattened field, - # using the keyword arguments to the method. - client.delete_instance( - name="name_value", + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") ) - - # Establish that the underlying call was made with the expected - # request object values. - assert len(call.mock_calls) == 1 + response = await client.update_instance() + call.assert_called() _, args, _ = call.mock_calls[0] - arg = args[0].name - mock_val = "name_value" - assert arg == mock_val - - -def test_delete_instance_flattened_error(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - ) - - # Attempting to call a method with both a request object and flattened - # fields is an error. - with pytest.raises(ValueError): - client.delete_instance( - spanner_instance_admin.DeleteInstanceRequest(), - name="name_value", - ) + assert args[0] == spanner_instance_admin.UpdateInstanceRequest() @pytest.mark.asyncio -async def test_delete_instance_flattened_async(): - client = InstanceAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials(), - ) - - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = None - - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) - # Call the method with a truthy value for each flattened field, - # using the keyword arguments to the method. - response = await client.delete_instance( - name="name_value", +async def test_update_instance_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, ) - # Establish that the underlying call was made with the expected - # request object values. - assert len(call.mock_calls) - _, args, _ = call.mock_calls[0] - arg = args[0].name - mock_val = "name_value" - assert arg == mock_val - - -@pytest.mark.asyncio -async def test_delete_instance_flattened_error_async(): - client = InstanceAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials(), - ) + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() - # Attempting to call a method with both a request object and flattened - # fields is an error. - with pytest.raises(ValueError): - await client.delete_instance( - spanner_instance_admin.DeleteInstanceRequest(), - name="name_value", + # Ensure method has been cached + assert ( + client._client._transport.update_instance + in client._client._transport._wrapped_methods ) + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) -@pytest.mark.parametrize( - "request_type", - [ - iam_policy_pb2.SetIamPolicyRequest, - dict, - ], -) -def test_set_iam_policy(request_type, transport: str = "grpc"): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - transport=transport, - ) - - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.update_instance + ] = mock_object - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = policy_pb2.Policy( - version=774, - etag=b"etag_blob", - ) - response = client.set_iam_policy(request) + request = {} + await client.update_instance(request) # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) == 1 - _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.SetIamPolicyRequest() - - # Establish that the response is the type that we expect. - assert isinstance(response, policy_pb2.Policy) - assert response.version == 774 - assert response.etag == b"etag_blob" + assert mock_object.call_count == 1 + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() -def test_set_iam_policy_empty_call(): - # This test is a coverage failsafe to make sure that totally empty calls, - # i.e. request == None and no flattened fields passed, work. - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - transport="grpc", - ) + await client.update_instance(request) - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: - client.set_iam_policy() - call.assert_called() - _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.SetIamPolicyRequest() + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 @pytest.mark.asyncio -async def test_set_iam_policy_async( - transport: str = "grpc_asyncio", request_type=iam_policy_pb2.SetIamPolicyRequest +async def test_update_instance_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.UpdateInstanceRequest, ): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4103,47 +6122,43 @@ async def test_set_iam_policy_async( request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + with mock.patch.object(type(client.transport.update_instance), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - policy_pb2.Policy( - version=774, - etag=b"etag_blob", - ) + operations_pb2.Operation(name="operations/spam") ) - response = await client.set_iam_policy(request) + response = await client.update_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.SetIamPolicyRequest() + request = spanner_instance_admin.UpdateInstanceRequest() + assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, policy_pb2.Policy) - assert response.version == 774 - assert response.etag == b"etag_blob" + assert isinstance(response, future.Future) @pytest.mark.asyncio -async def test_set_iam_policy_async_from_dict(): - await test_set_iam_policy_async(request_type=dict) +async def test_update_instance_async_from_dict(): + await test_update_instance_async(request_type=dict) -def test_set_iam_policy_field_headers(): +def test_update_instance_field_headers(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = iam_policy_pb2.SetIamPolicyRequest() + request = spanner_instance_admin.UpdateInstanceRequest() - request.resource = "resource_value" + request.instance.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: - call.return_value = policy_pb2.Policy() - client.set_iam_policy(request) + with mock.patch.object(type(client.transport.update_instance), "__call__") as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.update_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 @@ -4154,26 +6169,28 @@ def test_set_iam_policy_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource_value", + "instance.name=name_value", ) in kw["metadata"] @pytest.mark.asyncio -async def test_set_iam_policy_field_headers_async(): +async def test_update_instance_field_headers_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = iam_policy_pb2.SetIamPolicyRequest() + request = spanner_instance_admin.UpdateInstanceRequest() - request.resource = "resource_value" + request.instance.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy_pb2.Policy()) - await client.set_iam_policy(request) + with mock.patch.object(type(client.transport.update_instance), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.update_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) @@ -4184,53 +6201,39 @@ async def test_set_iam_policy_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource_value", + "instance.name=name_value", ) in kw["metadata"] -def test_set_iam_policy_from_dict_foreign(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - ) - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = policy_pb2.Policy() - response = client.set_iam_policy( - request={ - "resource": "resource_value", - "policy": policy_pb2.Policy(version=774), - "update_mask": field_mask_pb2.FieldMask(paths=["paths_value"]), - } - ) - call.assert_called() - - -def test_set_iam_policy_flattened(): +def test_update_instance_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + with mock.patch.object(type(client.transport.update_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = policy_pb2.Policy() + call.return_value = operations_pb2.Operation(name="operations/op") # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - client.set_iam_policy( - resource="resource_value", + client.update_instance( + instance=spanner_instance_admin.Instance(name="name_value"), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - arg = args[0].resource - mock_val = "resource_value" + arg = args[0].instance + mock_val = spanner_instance_admin.Instance(name="name_value") + assert arg == mock_val + arg = args[0].field_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) assert arg == mock_val -def test_set_iam_policy_flattened_error(): +def test_update_instance_flattened_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -4238,41 +6241,48 @@ def test_set_iam_policy_flattened_error(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.set_iam_policy( - iam_policy_pb2.SetIamPolicyRequest(), - resource="resource_value", + client.update_instance( + spanner_instance_admin.UpdateInstanceRequest(), + instance=spanner_instance_admin.Instance(name="name_value"), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) @pytest.mark.asyncio -async def test_set_iam_policy_flattened_async(): +async def test_update_instance_flattened_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + with mock.patch.object(type(client.transport.update_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = policy_pb2.Policy() + call.return_value = operations_pb2.Operation(name="operations/op") - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy_pb2.Policy()) + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - response = await client.set_iam_policy( - resource="resource_value", + response = await client.update_instance( + instance=spanner_instance_admin.Instance(name="name_value"), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - arg = args[0].resource - mock_val = "resource_value" + arg = args[0].instance + mock_val = spanner_instance_admin.Instance(name="name_value") + assert arg == mock_val + arg = args[0].field_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) assert arg == mock_val @pytest.mark.asyncio -async def test_set_iam_policy_flattened_error_async(): +async def test_update_instance_flattened_error_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -4280,20 +6290,21 @@ async def test_set_iam_policy_flattened_error_async(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - await client.set_iam_policy( - iam_policy_pb2.SetIamPolicyRequest(), - resource="resource_value", + await client.update_instance( + spanner_instance_admin.UpdateInstanceRequest(), + instance=spanner_instance_admin.Instance(name="name_value"), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) @pytest.mark.parametrize( "request_type", [ - iam_policy_pb2.GetIamPolicyRequest, + spanner_instance_admin.DeleteInstanceRequest, dict, ], ) -def test_get_iam_policy(request_type, transport: str = "grpc"): +def test_delete_instance(request_type, transport: str = "grpc"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -4304,26 +6315,22 @@ def test_get_iam_policy(request_type, transport: str = "grpc"): request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = policy_pb2.Policy( - version=774, - etag=b"etag_blob", - ) - response = client.get_iam_policy(request) + call.return_value = None + response = client.delete_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.GetIamPolicyRequest() + request = spanner_instance_admin.DeleteInstanceRequest() + assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, policy_pb2.Policy) - assert response.version == 774 - assert response.etag == b"etag_blob" + assert response is None -def test_get_iam_policy_empty_call(): +def test_delete_instance_empty_call(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. client = InstanceAdminClient( @@ -4332,16 +6339,148 @@ def test_get_iam_policy_empty_call(): ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: - client.get_iam_policy() + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_instance() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.GetIamPolicyRequest() + assert args[0] == spanner_instance_admin.DeleteInstanceRequest() + + +def test_delete_instance_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.DeleteInstanceRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_instance(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.DeleteInstanceRequest( + name="name_value", + ) + + +def test_delete_instance_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.delete_instance in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.delete_instance] = mock_rpc + request = {} + client.delete_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.delete_instance(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 @pytest.mark.asyncio -async def test_get_iam_policy_async( - transport: str = "grpc_asyncio", request_type=iam_policy_pb2.GetIamPolicyRequest +async def test_delete_instance_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_instance() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.DeleteInstanceRequest() + + +@pytest.mark.asyncio +async def test_delete_instance_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.delete_instance + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.delete_instance + ] = mock_object + + request = {} + await client.delete_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.delete_instance(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_instance_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.DeleteInstanceRequest, ): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4353,47 +6492,41 @@ async def test_get_iam_policy_async( request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - policy_pb2.Policy( - version=774, - etag=b"etag_blob", - ) - ) - response = await client.get_iam_policy(request) + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.GetIamPolicyRequest() + request = spanner_instance_admin.DeleteInstanceRequest() + assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, policy_pb2.Policy) - assert response.version == 774 - assert response.etag == b"etag_blob" + assert response is None @pytest.mark.asyncio -async def test_get_iam_policy_async_from_dict(): - await test_get_iam_policy_async(request_type=dict) +async def test_delete_instance_async_from_dict(): + await test_delete_instance_async(request_type=dict) -def test_get_iam_policy_field_headers(): +def test_delete_instance_field_headers(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = iam_policy_pb2.GetIamPolicyRequest() + request = spanner_instance_admin.DeleteInstanceRequest() - request.resource = "resource_value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: - call.return_value = policy_pb2.Policy() - client.get_iam_policy(request) + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: + call.return_value = None + client.delete_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 @@ -4404,26 +6537,26 @@ def test_get_iam_policy_field_headers(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource_value", + "name=name_value", ) in kw["metadata"] @pytest.mark.asyncio -async def test_get_iam_policy_field_headers_async(): +async def test_delete_instance_field_headers_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = iam_policy_pb2.GetIamPolicyRequest() + request = spanner_instance_admin.DeleteInstanceRequest() - request.resource = "resource_value" + request.name = "name_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy_pb2.Policy()) - await client.get_iam_policy(request) + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + await client.delete_instance(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) @@ -4434,52 +6567,35 @@ async def test_get_iam_policy_field_headers_async(): _, _, kw = call.mock_calls[0] assert ( "x-goog-request-params", - "resource=resource_value", + "name=name_value", ) in kw["metadata"] -def test_get_iam_policy_from_dict_foreign(): - client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - ) - # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = policy_pb2.Policy() - response = client.get_iam_policy( - request={ - "resource": "resource_value", - "options": options_pb2.GetPolicyOptions(requested_policy_version=2598), - } - ) - call.assert_called() - - -def test_get_iam_policy_flattened(): +def test_delete_instance_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = policy_pb2.Policy() + call.return_value = None # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - client.get_iam_policy( - resource="resource_value", + client.delete_instance( + name="name_value", ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - arg = args[0].resource - mock_val = "resource_value" + arg = args[0].name + mock_val = "name_value" assert arg == mock_val -def test_get_iam_policy_flattened_error(): +def test_delete_instance_flattened_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -4487,41 +6603,41 @@ def test_get_iam_policy_flattened_error(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.get_iam_policy( - iam_policy_pb2.GetIamPolicyRequest(), - resource="resource_value", + client.delete_instance( + spanner_instance_admin.DeleteInstanceRequest(), + name="name_value", ) @pytest.mark.asyncio -async def test_get_iam_policy_flattened_async(): +async def test_delete_instance_flattened_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + with mock.patch.object(type(client.transport.delete_instance), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = policy_pb2.Policy() + call.return_value = None - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy_pb2.Policy()) + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - response = await client.get_iam_policy( - resource="resource_value", + response = await client.delete_instance( + name="name_value", ) # Establish that the underlying call was made with the expected # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - arg = args[0].resource - mock_val = "resource_value" + arg = args[0].name + mock_val = "name_value" assert arg == mock_val @pytest.mark.asyncio -async def test_get_iam_policy_flattened_error_async(): +async def test_delete_instance_flattened_error_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -4529,20 +6645,20 @@ async def test_get_iam_policy_flattened_error_async(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - await client.get_iam_policy( - iam_policy_pb2.GetIamPolicyRequest(), - resource="resource_value", + await client.delete_instance( + spanner_instance_admin.DeleteInstanceRequest(), + name="name_value", ) @pytest.mark.parametrize( "request_type", [ - iam_policy_pb2.TestIamPermissionsRequest, + iam_policy_pb2.SetIamPolicyRequest, dict, ], ) -def test_test_iam_permissions(request_type, transport: str = "grpc"): +def test_set_iam_policy(request_type, transport: str = "grpc"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -4553,26 +6669,27 @@ def test_test_iam_permissions(request_type, transport: str = "grpc"): request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.test_iam_permissions), "__call__" - ) as call: + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = iam_policy_pb2.TestIamPermissionsResponse( - permissions=["permissions_value"], + call.return_value = policy_pb2.Policy( + version=774, + etag=b"etag_blob", ) - response = client.test_iam_permissions(request) + response = client.set_iam_policy(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.TestIamPermissionsRequest() + request = iam_policy_pb2.SetIamPolicyRequest() + assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, iam_policy_pb2.TestIamPermissionsResponse) - assert response.permissions == ["permissions_value"] - + assert isinstance(response, policy_pb2.Policy) + assert response.version == 774 + assert response.etag == b"etag_blob" -def test_test_iam_permissions_empty_call(): + +def test_set_iam_policy_empty_call(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. client = InstanceAdminClient( @@ -4581,19 +6698,152 @@ def test_test_iam_permissions_empty_call(): ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.test_iam_permissions), "__call__" - ) as call: - client.test_iam_permissions() + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.set_iam_policy() call.assert_called() _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.TestIamPermissionsRequest() + assert args[0] == iam_policy_pb2.SetIamPolicyRequest() + + +def test_set_iam_policy_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = iam_policy_pb2.SetIamPolicyRequest( + resource="resource_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.set_iam_policy(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.SetIamPolicyRequest( + resource="resource_value", + ) + + +def test_set_iam_policy_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.set_iam_policy in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.set_iam_policy] = mock_rpc + request = {} + client.set_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.set_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 @pytest.mark.asyncio -async def test_test_iam_permissions_async( +async def test_set_iam_policy_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + policy_pb2.Policy( + version=774, + etag=b"etag_blob", + ) + ) + response = await client.set_iam_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.SetIamPolicyRequest() + + +@pytest.mark.asyncio +async def test_set_iam_policy_async_use_cached_wrapped_rpc( transport: str = "grpc_asyncio", - request_type=iam_policy_pb2.TestIamPermissionsRequest, +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.set_iam_policy + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.set_iam_policy + ] = mock_object + + request = {} + await client.set_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.set_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_set_iam_policy_async( + transport: str = "grpc_asyncio", request_type=iam_policy_pb2.SetIamPolicyRequest ): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4605,49 +6855,48 @@ async def test_test_iam_permissions_async( request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.test_iam_permissions), "__call__" - ) as call: + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - iam_policy_pb2.TestIamPermissionsResponse( - permissions=["permissions_value"], + policy_pb2.Policy( + version=774, + etag=b"etag_blob", ) ) - response = await client.test_iam_permissions(request) + response = await client.set_iam_policy(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == iam_policy_pb2.TestIamPermissionsRequest() + request = iam_policy_pb2.SetIamPolicyRequest() + assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, iam_policy_pb2.TestIamPermissionsResponse) - assert response.permissions == ["permissions_value"] + assert isinstance(response, policy_pb2.Policy) + assert response.version == 774 + assert response.etag == b"etag_blob" @pytest.mark.asyncio -async def test_test_iam_permissions_async_from_dict(): - await test_test_iam_permissions_async(request_type=dict) +async def test_set_iam_policy_async_from_dict(): + await test_set_iam_policy_async(request_type=dict) -def test_test_iam_permissions_field_headers(): +def test_set_iam_policy_field_headers(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = iam_policy_pb2.TestIamPermissionsRequest() + request = iam_policy_pb2.SetIamPolicyRequest() request.resource = "resource_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.test_iam_permissions), "__call__" - ) as call: - call.return_value = iam_policy_pb2.TestIamPermissionsResponse() - client.test_iam_permissions(request) + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + call.return_value = policy_pb2.Policy() + client.set_iam_policy(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 @@ -4663,25 +6912,21 @@ def test_test_iam_permissions_field_headers(): @pytest.mark.asyncio -async def test_test_iam_permissions_field_headers_async(): +async def test_set_iam_policy_field_headers_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Any value that is part of the HTTP/1.1 URI should be sent as # a field header. Set these to a non-empty value. - request = iam_policy_pb2.TestIamPermissionsRequest() + request = iam_policy_pb2.SetIamPolicyRequest() request.resource = "resource_value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.test_iam_permissions), "__call__" - ) as call: - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - iam_policy_pb2.TestIamPermissionsResponse() - ) - await client.test_iam_permissions(request) + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy_pb2.Policy()) + await client.set_iam_policy(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) @@ -4696,41 +6941,37 @@ async def test_test_iam_permissions_field_headers_async(): ) in kw["metadata"] -def test_test_iam_permissions_from_dict_foreign(): +def test_set_iam_policy_from_dict_foreign(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.test_iam_permissions), "__call__" - ) as call: + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = iam_policy_pb2.TestIamPermissionsResponse() - response = client.test_iam_permissions( + call.return_value = policy_pb2.Policy() + response = client.set_iam_policy( request={ "resource": "resource_value", - "permissions": ["permissions_value"], + "policy": policy_pb2.Policy(version=774), + "update_mask": field_mask_pb2.FieldMask(paths=["paths_value"]), } ) call.assert_called() -def test_test_iam_permissions_flattened(): +def test_set_iam_policy_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.test_iam_permissions), "__call__" - ) as call: + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = iam_policy_pb2.TestIamPermissionsResponse() + call.return_value = policy_pb2.Policy() # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - client.test_iam_permissions( + client.set_iam_policy( resource="resource_value", - permissions=["permissions_value"], ) # Establish that the underlying call was made with the expected @@ -4740,12 +6981,9 @@ def test_test_iam_permissions_flattened(): arg = args[0].resource mock_val = "resource_value" assert arg == mock_val - arg = args[0].permissions - mock_val = ["permissions_value"] - assert arg == mock_val -def test_test_iam_permissions_flattened_error(): +def test_set_iam_policy_flattened_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), ) @@ -4753,72 +6991,5184 @@ def test_test_iam_permissions_flattened_error(): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.test_iam_permissions( - iam_policy_pb2.TestIamPermissionsRequest(), + client.set_iam_policy( + iam_policy_pb2.SetIamPolicyRequest(), resource="resource_value", - permissions=["permissions_value"], ) @pytest.mark.asyncio -async def test_test_iam_permissions_flattened_async(): +async def test_set_iam_policy_flattened_async(): client = InstanceAdminAsyncClient( credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client.transport.test_iam_permissions), "__call__" - ) as call: + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = iam_policy_pb2.TestIamPermissionsResponse() + call.return_value = policy_pb2.Policy() - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - iam_policy_pb2.TestIamPermissionsResponse() - ) + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy_pb2.Policy()) # Call the method with a truthy value for each flattened field, # using the keyword arguments to the method. - response = await client.test_iam_permissions( + response = await client.set_iam_policy( resource="resource_value", - permissions=["permissions_value"], ) - # Establish that the underlying call was made with the expected - # request object values. - assert len(call.mock_calls) - _, args, _ = call.mock_calls[0] - arg = args[0].resource - mock_val = "resource_value" - assert arg == mock_val - arg = args[0].permissions - mock_val = ["permissions_value"] - assert arg == mock_val + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].resource + mock_val = "resource_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_set_iam_policy_flattened_error_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.set_iam_policy( + iam_policy_pb2.SetIamPolicyRequest(), + resource="resource_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + iam_policy_pb2.GetIamPolicyRequest, + dict, + ], +) +def test_get_iam_policy(request_type, transport: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = policy_pb2.Policy( + version=774, + etag=b"etag_blob", + ) + response = client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = iam_policy_pb2.GetIamPolicyRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, policy_pb2.Policy) + assert response.version == 774 + assert response.etag == b"etag_blob" + + +def test_get_iam_policy_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_iam_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.GetIamPolicyRequest() + + +def test_get_iam_policy_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = iam_policy_pb2.GetIamPolicyRequest( + resource="resource_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_iam_policy(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.GetIamPolicyRequest( + resource="resource_value", + ) + + +def test_get_iam_policy_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_iam_policy in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_iam_policy] = mock_rpc + request = {} + client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_iam_policy_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + policy_pb2.Policy( + version=774, + etag=b"etag_blob", + ) + ) + response = await client.get_iam_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.GetIamPolicyRequest() + + +@pytest.mark.asyncio +async def test_get_iam_policy_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_iam_policy + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.get_iam_policy + ] = mock_object + + request = {} + await client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.get_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_iam_policy_async( + transport: str = "grpc_asyncio", request_type=iam_policy_pb2.GetIamPolicyRequest +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + policy_pb2.Policy( + version=774, + etag=b"etag_blob", + ) + ) + response = await client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = iam_policy_pb2.GetIamPolicyRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, policy_pb2.Policy) + assert response.version == 774 + assert response.etag == b"etag_blob" + + +@pytest.mark.asyncio +async def test_get_iam_policy_async_from_dict(): + await test_get_iam_policy_async(request_type=dict) + + +def test_get_iam_policy_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = iam_policy_pb2.GetIamPolicyRequest() + + request.resource = "resource_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + call.return_value = policy_pb2.Policy() + client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "resource=resource_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_iam_policy_field_headers_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = iam_policy_pb2.GetIamPolicyRequest() + + request.resource = "resource_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy_pb2.Policy()) + await client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "resource=resource_value", + ) in kw["metadata"] + + +def test_get_iam_policy_from_dict_foreign(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = policy_pb2.Policy() + response = client.get_iam_policy( + request={ + "resource": "resource_value", + "options": options_pb2.GetPolicyOptions(requested_policy_version=2598), + } + ) + call.assert_called() + + +def test_get_iam_policy_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = policy_pb2.Policy() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_iam_policy( + resource="resource_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].resource + mock_val = "resource_value" + assert arg == mock_val + + +def test_get_iam_policy_flattened_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_iam_policy( + iam_policy_pb2.GetIamPolicyRequest(), + resource="resource_value", + ) + + +@pytest.mark.asyncio +async def test_get_iam_policy_flattened_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = policy_pb2.Policy() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy_pb2.Policy()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_iam_policy( + resource="resource_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].resource + mock_val = "resource_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_get_iam_policy_flattened_error_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_iam_policy( + iam_policy_pb2.GetIamPolicyRequest(), + resource="resource_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + iam_policy_pb2.TestIamPermissionsRequest, + dict, + ], +) +def test_test_iam_permissions(request_type, transport: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = iam_policy_pb2.TestIamPermissionsResponse( + permissions=["permissions_value"], + ) + response = client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = iam_policy_pb2.TestIamPermissionsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, iam_policy_pb2.TestIamPermissionsResponse) + assert response.permissions == ["permissions_value"] + + +def test_test_iam_permissions_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.test_iam_permissions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.TestIamPermissionsRequest() + + +def test_test_iam_permissions_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = iam_policy_pb2.TestIamPermissionsRequest( + resource="resource_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.test_iam_permissions(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.TestIamPermissionsRequest( + resource="resource_value", + ) + + +def test_test_iam_permissions_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.test_iam_permissions in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.test_iam_permissions + ] = mock_rpc + request = {} + client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.test_iam_permissions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_test_iam_permissions_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + iam_policy_pb2.TestIamPermissionsResponse( + permissions=["permissions_value"], + ) + ) + response = await client.test_iam_permissions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == iam_policy_pb2.TestIamPermissionsRequest() + + +@pytest.mark.asyncio +async def test_test_iam_permissions_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.test_iam_permissions + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.test_iam_permissions + ] = mock_object + + request = {} + await client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.test_iam_permissions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_test_iam_permissions_async( + transport: str = "grpc_asyncio", + request_type=iam_policy_pb2.TestIamPermissionsRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + iam_policy_pb2.TestIamPermissionsResponse( + permissions=["permissions_value"], + ) + ) + response = await client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = iam_policy_pb2.TestIamPermissionsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, iam_policy_pb2.TestIamPermissionsResponse) + assert response.permissions == ["permissions_value"] + + +@pytest.mark.asyncio +async def test_test_iam_permissions_async_from_dict(): + await test_test_iam_permissions_async(request_type=dict) + + +def test_test_iam_permissions_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = iam_policy_pb2.TestIamPermissionsRequest() + + request.resource = "resource_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + call.return_value = iam_policy_pb2.TestIamPermissionsResponse() + client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "resource=resource_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_test_iam_permissions_field_headers_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = iam_policy_pb2.TestIamPermissionsRequest() + + request.resource = "resource_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + iam_policy_pb2.TestIamPermissionsResponse() + ) + await client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "resource=resource_value", + ) in kw["metadata"] + + +def test_test_iam_permissions_from_dict_foreign(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = iam_policy_pb2.TestIamPermissionsResponse() + response = client.test_iam_permissions( + request={ + "resource": "resource_value", + "permissions": ["permissions_value"], + } + ) + call.assert_called() + + +def test_test_iam_permissions_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = iam_policy_pb2.TestIamPermissionsResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.test_iam_permissions( + resource="resource_value", + permissions=["permissions_value"], + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].resource + mock_val = "resource_value" + assert arg == mock_val + arg = args[0].permissions + mock_val = ["permissions_value"] + assert arg == mock_val + + +def test_test_iam_permissions_flattened_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.test_iam_permissions( + iam_policy_pb2.TestIamPermissionsRequest(), + resource="resource_value", + permissions=["permissions_value"], + ) + + +@pytest.mark.asyncio +async def test_test_iam_permissions_flattened_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = iam_policy_pb2.TestIamPermissionsResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + iam_policy_pb2.TestIamPermissionsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.test_iam_permissions( + resource="resource_value", + permissions=["permissions_value"], + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].resource + mock_val = "resource_value" + assert arg == mock_val + arg = args[0].permissions + mock_val = ["permissions_value"] + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_test_iam_permissions_flattened_error_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.test_iam_permissions( + iam_policy_pb2.TestIamPermissionsRequest(), + resource="resource_value", + permissions=["permissions_value"], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.GetInstancePartitionRequest, + dict, + ], +) +def test_get_instance_partition(request_type, transport: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = spanner_instance_admin.InstancePartition( + name="name_value", + config="config_value", + display_name="display_name_value", + state=spanner_instance_admin.InstancePartition.State.CREATING, + referencing_databases=["referencing_databases_value"], + referencing_backups=["referencing_backups_value"], + etag="etag_value", + node_count=1070, + ) + response = client.get_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.GetInstancePartitionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, spanner_instance_admin.InstancePartition) + assert response.name == "name_value" + assert response.config == "config_value" + assert response.display_name == "display_name_value" + assert response.state == spanner_instance_admin.InstancePartition.State.CREATING + assert response.referencing_databases == ["referencing_databases_value"] + assert response.referencing_backups == ["referencing_backups_value"] + assert response.etag == "etag_value" + + +def test_get_instance_partition_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_partition), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_instance_partition() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.GetInstancePartitionRequest() + + +def test_get_instance_partition_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.GetInstancePartitionRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_partition), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_instance_partition(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.GetInstancePartitionRequest( + name="name_value", + ) + + +def test_get_instance_partition_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_instance_partition + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_instance_partition + ] = mock_rpc + request = {} + client.get_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_instance_partition_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.InstancePartition( + name="name_value", + config="config_value", + display_name="display_name_value", + state=spanner_instance_admin.InstancePartition.State.CREATING, + referencing_databases=["referencing_databases_value"], + referencing_backups=["referencing_backups_value"], + etag="etag_value", + ) + ) + response = await client.get_instance_partition() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.GetInstancePartitionRequest() + + +@pytest.mark.asyncio +async def test_get_instance_partition_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_instance_partition + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.get_instance_partition + ] = mock_object + + request = {} + await client.get_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.get_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_instance_partition_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.GetInstancePartitionRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.InstancePartition( + name="name_value", + config="config_value", + display_name="display_name_value", + state=spanner_instance_admin.InstancePartition.State.CREATING, + referencing_databases=["referencing_databases_value"], + referencing_backups=["referencing_backups_value"], + etag="etag_value", + ) + ) + response = await client.get_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.GetInstancePartitionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, spanner_instance_admin.InstancePartition) + assert response.name == "name_value" + assert response.config == "config_value" + assert response.display_name == "display_name_value" + assert response.state == spanner_instance_admin.InstancePartition.State.CREATING + assert response.referencing_databases == ["referencing_databases_value"] + assert response.referencing_backups == ["referencing_backups_value"] + assert response.etag == "etag_value" + + +@pytest.mark.asyncio +async def test_get_instance_partition_async_from_dict(): + await test_get_instance_partition_async(request_type=dict) + + +def test_get_instance_partition_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.GetInstancePartitionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_partition), "__call__" + ) as call: + call.return_value = spanner_instance_admin.InstancePartition() + client.get_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_instance_partition_field_headers_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.GetInstancePartitionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_partition), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.InstancePartition() + ) + await client.get_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +def test_get_instance_partition_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = spanner_instance_admin.InstancePartition() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_instance_partition( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +def test_get_instance_partition_flattened_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_instance_partition( + spanner_instance_admin.GetInstancePartitionRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_instance_partition_flattened_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = spanner_instance_admin.InstancePartition() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.InstancePartition() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_instance_partition( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_get_instance_partition_flattened_error_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_instance_partition( + spanner_instance_admin.GetInstancePartitionRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.CreateInstancePartitionRequest, + dict, + ], +) +def test_create_instance_partition(request_type, transport: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.create_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.CreateInstancePartitionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_create_instance_partition_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_partition), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.create_instance_partition() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.CreateInstancePartitionRequest() + + +def test_create_instance_partition_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.CreateInstancePartitionRequest( + parent="parent_value", + instance_partition_id="instance_partition_id_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_partition), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.create_instance_partition(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.CreateInstancePartitionRequest( + parent="parent_value", + instance_partition_id="instance_partition_id_value", + ) + + +def test_create_instance_partition_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.create_instance_partition + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.create_instance_partition + ] = mock_rpc + request = {} + client.create_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.create_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_create_instance_partition_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_instance_partition() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.CreateInstancePartitionRequest() + + +@pytest.mark.asyncio +async def test_create_instance_partition_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.create_instance_partition + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.create_instance_partition + ] = mock_object + + request = {} + await client.create_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.create_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_create_instance_partition_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.CreateInstancePartitionRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.CreateInstancePartitionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_create_instance_partition_async_from_dict(): + await test_create_instance_partition_async(request_type=dict) + + +def test_create_instance_partition_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.CreateInstancePartitionRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_partition), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.create_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_create_instance_partition_field_headers_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.CreateInstancePartitionRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_partition), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.create_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_create_instance_partition_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.create_instance_partition( + parent="parent_value", + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + instance_partition_id="instance_partition_id_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].instance_partition + mock_val = spanner_instance_admin.InstancePartition(name="name_value") + assert arg == mock_val + arg = args[0].instance_partition_id + mock_val = "instance_partition_id_value" + assert arg == mock_val + + +def test_create_instance_partition_flattened_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.create_instance_partition( + spanner_instance_admin.CreateInstancePartitionRequest(), + parent="parent_value", + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + instance_partition_id="instance_partition_id_value", + ) + + +@pytest.mark.asyncio +async def test_create_instance_partition_flattened_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.create_instance_partition( + parent="parent_value", + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + instance_partition_id="instance_partition_id_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].instance_partition + mock_val = spanner_instance_admin.InstancePartition(name="name_value") + assert arg == mock_val + arg = args[0].instance_partition_id + mock_val = "instance_partition_id_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_create_instance_partition_flattened_error_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.create_instance_partition( + spanner_instance_admin.CreateInstancePartitionRequest(), + parent="parent_value", + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + instance_partition_id="instance_partition_id_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.DeleteInstancePartitionRequest, + dict, + ], +) +def test_delete_instance_partition(request_type, transport: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = None + response = client.delete_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.DeleteInstancePartitionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_instance_partition_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_partition), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_instance_partition() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.DeleteInstancePartitionRequest() + + +def test_delete_instance_partition_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.DeleteInstancePartitionRequest( + name="name_value", + etag="etag_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_partition), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_instance_partition(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.DeleteInstancePartitionRequest( + name="name_value", + etag="etag_value", + ) + + +def test_delete_instance_partition_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.delete_instance_partition + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.delete_instance_partition + ] = mock_rpc + request = {} + client.delete_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.delete_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_instance_partition_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_instance_partition() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.DeleteInstancePartitionRequest() + + +@pytest.mark.asyncio +async def test_delete_instance_partition_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.delete_instance_partition + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.delete_instance_partition + ] = mock_object + + request = {} + await client.delete_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.delete_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_instance_partition_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.DeleteInstancePartitionRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.DeleteInstancePartitionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert response is None + + +@pytest.mark.asyncio +async def test_delete_instance_partition_async_from_dict(): + await test_delete_instance_partition_async(request_type=dict) + + +def test_delete_instance_partition_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.DeleteInstancePartitionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_partition), "__call__" + ) as call: + call.return_value = None + client.delete_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_delete_instance_partition_field_headers_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.DeleteInstancePartitionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_partition), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + await client.delete_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +def test_delete_instance_partition_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = None + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.delete_instance_partition( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +def test_delete_instance_partition_flattened_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.delete_instance_partition( + spanner_instance_admin.DeleteInstancePartitionRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_delete_instance_partition_flattened_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = None + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.delete_instance_partition( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_delete_instance_partition_flattened_error_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.delete_instance_partition( + spanner_instance_admin.DeleteInstancePartitionRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.UpdateInstancePartitionRequest, + dict, + ], +) +def test_update_instance_partition(request_type, transport: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.update_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.UpdateInstancePartitionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_update_instance_partition_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_partition), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_instance_partition() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.UpdateInstancePartitionRequest() + + +def test_update_instance_partition_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.UpdateInstancePartitionRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_partition), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_instance_partition(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.UpdateInstancePartitionRequest() + + +def test_update_instance_partition_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_instance_partition + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_instance_partition + ] = mock_rpc + request = {} + client.update_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.update_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_instance_partition_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.update_instance_partition() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.UpdateInstancePartitionRequest() + + +@pytest.mark.asyncio +async def test_update_instance_partition_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_instance_partition + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.update_instance_partition + ] = mock_object + + request = {} + await client.update_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.update_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_instance_partition_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.UpdateInstancePartitionRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.update_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.UpdateInstancePartitionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_update_instance_partition_async_from_dict(): + await test_update_instance_partition_async(request_type=dict) + + +def test_update_instance_partition_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.UpdateInstancePartitionRequest() + + request.instance_partition.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_partition), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.update_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "instance_partition.name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_instance_partition_field_headers_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.UpdateInstancePartitionRequest() + + request.instance_partition.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_partition), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.update_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "instance_partition.name=name_value", + ) in kw["metadata"] + + +def test_update_instance_partition_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_instance_partition( + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].instance_partition + mock_val = spanner_instance_admin.InstancePartition(name="name_value") + assert arg == mock_val + arg = args[0].field_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_instance_partition_flattened_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_instance_partition( + spanner_instance_admin.UpdateInstancePartitionRequest(), + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_instance_partition_flattened_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_instance_partition), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_instance_partition( + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].instance_partition + mock_val = spanner_instance_admin.InstancePartition(name="name_value") + assert arg == mock_val + arg = args[0].field_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_update_instance_partition_flattened_error_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_instance_partition( + spanner_instance_admin.UpdateInstancePartitionRequest(), + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.ListInstancePartitionOperationsRequest, + dict, + ], +) +def test_list_instance_partition_operations(request_type, transport: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse( + next_page_token="next_page_token_value", + unreachable_instance_partitions=[ + "unreachable_instance_partitions_value" + ], + ) + ) + response = client.list_instance_partition_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.ListInstancePartitionOperationsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListInstancePartitionOperationsPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable_instance_partitions == [ + "unreachable_instance_partitions_value" + ] + + +def test_list_instance_partition_operations_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_instance_partition_operations() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] == spanner_instance_admin.ListInstancePartitionOperationsRequest() + ) + + +def test_list_instance_partition_operations_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner_instance_admin.ListInstancePartitionOperationsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_instance_partition_operations(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner_instance_admin.ListInstancePartitionOperationsRequest( + parent="parent_value", + filter="filter_value", + page_token="page_token_value", + ) + + +def test_list_instance_partition_operations_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_instance_partition_operations + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_instance_partition_operations + ] = mock_rpc + request = {} + client.list_instance_partition_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_instance_partition_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_instance_partition_operations_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstancePartitionOperationsResponse( + next_page_token="next_page_token_value", + unreachable_instance_partitions=[ + "unreachable_instance_partitions_value" + ], + ) + ) + response = await client.list_instance_partition_operations() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] == spanner_instance_admin.ListInstancePartitionOperationsRequest() + ) + + +@pytest.mark.asyncio +async def test_list_instance_partition_operations_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_instance_partition_operations + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_instance_partition_operations + ] = mock_object + + request = {} + await client.list_instance_partition_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_instance_partition_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_instance_partition_operations_async( + transport: str = "grpc_asyncio", + request_type=spanner_instance_admin.ListInstancePartitionOperationsRequest, +): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstancePartitionOperationsResponse( + next_page_token="next_page_token_value", + unreachable_instance_partitions=[ + "unreachable_instance_partitions_value" + ], + ) + ) + response = await client.list_instance_partition_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner_instance_admin.ListInstancePartitionOperationsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListInstancePartitionOperationsAsyncPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable_instance_partitions == [ + "unreachable_instance_partitions_value" + ] + + +@pytest.mark.asyncio +async def test_list_instance_partition_operations_async_from_dict(): + await test_list_instance_partition_operations_async(request_type=dict) + + +def test_list_instance_partition_operations_field_headers(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.ListInstancePartitionOperationsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + call.return_value = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse() + ) + client.list_instance_partition_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_instance_partition_operations_field_headers_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = spanner_instance_admin.ListInstancePartitionOperationsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstancePartitionOperationsResponse() + ) + await client.list_instance_partition_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_list_instance_partition_operations_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.list_instance_partition_operations( + parent="parent_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + + +def test_list_instance_partition_operations_flattened_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_instance_partition_operations( + spanner_instance_admin.ListInstancePartitionOperationsRequest(), + parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_list_instance_partition_operations_flattened_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse() + ) + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner_instance_admin.ListInstancePartitionOperationsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.list_instance_partition_operations( + parent="parent_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_list_instance_partition_operations_flattened_error_async(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.list_instance_partition_operations( + spanner_instance_admin.ListInstancePartitionOperationsRequest(), + parent="parent_value", + ) + + +def test_list_instance_partition_operations_pager(transport_name: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport_name, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + ), + RuntimeError, + ) + + metadata = () + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)), + ) + pager = client.list_instance_partition_operations(request={}) + + assert pager._metadata == metadata + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, operations_pb2.Operation) for i in results) + + +def test_list_instance_partition_operations_pages(transport_name: str = "grpc"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport_name, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + ), + RuntimeError, + ) + pages = list(client.list_instance_partition_operations(request={}).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.asyncio +async def test_list_instance_partition_operations_async_pager(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + ), + RuntimeError, + ) + async_pager = await client.list_instance_partition_operations( + request={}, + ) + assert async_pager.next_page_token == "abc" + responses = [] + async for response in async_pager: # pragma: no branch + responses.append(response) + + assert len(responses) == 6 + assert all(isinstance(i, operations_pb2.Operation) for i in responses) + + +@pytest.mark.asyncio +async def test_list_instance_partition_operations_async_pages(): + client = InstanceAdminAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_instance_partition_operations), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + ), + RuntimeError, + ) + pages = [] + # Workaround issue in python 3.9 related to code coverage by adding `# pragma: no branch` + # See https://github.com/googleapis/gapic-generator-python/pull/1174#issuecomment-1025132372 + async for page_ in ( # pragma: no branch + await client.list_instance_partition_operations(request={}) + ).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.ListInstanceConfigsRequest, + dict, + ], +) +def test_list_instance_configs_rest(request_type): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = spanner_instance_admin.ListInstanceConfigsResponse( + next_page_token="next_page_token_value", + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.ListInstanceConfigsResponse.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.list_instance_configs(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListInstanceConfigsPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_instance_configs_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_instance_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_instance_configs + ] = mock_rpc + + request = {} + client.list_instance_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_instance_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_instance_configs_rest_required_fields( + request_type=spanner_instance_admin.ListInstanceConfigsRequest, +): + transport_class = transports.InstanceAdminRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_instance_configs._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_instance_configs._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "page_size", + "page_token", + ) + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = spanner_instance_admin.ListInstanceConfigsResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = spanner_instance_admin.ListInstanceConfigsResponse.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_instance_configs(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_instance_configs_rest_unset_required_fields(): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.list_instance_configs._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "pageSize", + "pageToken", + ) + ) + & set(("parent",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_instance_configs_rest_interceptors(null_interceptor): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.InstanceAdminRestInterceptor(), + ) + client = InstanceAdminClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.InstanceAdminRestInterceptor, "post_list_instance_configs" + ) as post, mock.patch.object( + transports.InstanceAdminRestInterceptor, "pre_list_instance_configs" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = spanner_instance_admin.ListInstanceConfigsRequest.pb( + spanner_instance_admin.ListInstanceConfigsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + spanner_instance_admin.ListInstanceConfigsResponse.to_json( + spanner_instance_admin.ListInstanceConfigsResponse() + ) + ) + + request = spanner_instance_admin.ListInstanceConfigsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = spanner_instance_admin.ListInstanceConfigsResponse() + + client.list_instance_configs( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_list_instance_configs_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.ListInstanceConfigsRequest, +): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_instance_configs(request) + + +def test_list_instance_configs_rest_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = spanner_instance_admin.ListInstanceConfigsResponse() + + # get arguments that satisfy an http rule for this method + sample_request = {"parent": "projects/sample1"} + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.ListInstanceConfigsResponse.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.list_instance_configs(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{parent=projects/*}/instanceConfigs" % client.transport._host, + args[1], + ) + + +def test_list_instance_configs_rest_flattened_error(transport: str = "rest"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_instance_configs( + spanner_instance_admin.ListInstanceConfigsRequest(), + parent="parent_value", + ) + + +def test_list_instance_configs_rest_pager(transport: str = "rest"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + spanner_instance_admin.ListInstanceConfigsResponse( + instance_configs=[ + spanner_instance_admin.InstanceConfig(), + spanner_instance_admin.InstanceConfig(), + spanner_instance_admin.InstanceConfig(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstanceConfigsResponse( + instance_configs=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstanceConfigsResponse( + instance_configs=[ + spanner_instance_admin.InstanceConfig(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstanceConfigsResponse( + instance_configs=[ + spanner_instance_admin.InstanceConfig(), + spanner_instance_admin.InstanceConfig(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple( + spanner_instance_admin.ListInstanceConfigsResponse.to_json(x) + for x in response + ) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = {"parent": "projects/sample1"} + + pager = client.list_instance_configs(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all( + isinstance(i, spanner_instance_admin.InstanceConfig) for i in results + ) + + pages = list(client.list_instance_configs(request=sample_request).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.GetInstanceConfigRequest, + dict, + ], +) +def test_get_instance_config_rest(request_type): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/instanceConfigs/sample2"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = spanner_instance_admin.InstanceConfig( + name="name_value", + display_name="display_name_value", + config_type=spanner_instance_admin.InstanceConfig.Type.GOOGLE_MANAGED, + base_config="base_config_value", + etag="etag_value", + leader_options=["leader_options_value"], + reconciling=True, + state=spanner_instance_admin.InstanceConfig.State.CREATING, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.InstanceConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.get_instance_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, spanner_instance_admin.InstanceConfig) + assert response.name == "name_value" + assert response.display_name == "display_name_value" + assert ( + response.config_type + == spanner_instance_admin.InstanceConfig.Type.GOOGLE_MANAGED + ) + assert response.base_config == "base_config_value" + assert response.etag == "etag_value" + assert response.leader_options == ["leader_options_value"] + assert response.reconciling is True + assert response.state == spanner_instance_admin.InstanceConfig.State.CREATING + + +def test_get_instance_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_instance_config in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_instance_config + ] = mock_rpc + + request = {} + client.get_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_get_instance_config_rest_required_fields( + request_type=spanner_instance_admin.GetInstanceConfigRequest, +): + transport_class = transports.InstanceAdminRestTransport + + request_init = {} + request_init["name"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_instance_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["name"] = "name_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_instance_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" + + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = spanner_instance_admin.InstanceConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = spanner_instance_admin.InstanceConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_instance_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_instance_config_rest_unset_required_fields(): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_instance_config._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_instance_config_rest_interceptors(null_interceptor): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.InstanceAdminRestInterceptor(), + ) + client = InstanceAdminClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.InstanceAdminRestInterceptor, "post_get_instance_config" + ) as post, mock.patch.object( + transports.InstanceAdminRestInterceptor, "pre_get_instance_config" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = spanner_instance_admin.GetInstanceConfigRequest.pb( + spanner_instance_admin.GetInstanceConfigRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = spanner_instance_admin.InstanceConfig.to_json( + spanner_instance_admin.InstanceConfig() + ) + + request = spanner_instance_admin.GetInstanceConfigRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = spanner_instance_admin.InstanceConfig() + + client.get_instance_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_instance_config_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.GetInstanceConfigRequest, +): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/instanceConfigs/sample2"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_instance_config(request) + + +def test_get_instance_config_rest_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = spanner_instance_admin.InstanceConfig() + + # get arguments that satisfy an http rule for this method + sample_request = {"name": "projects/sample1/instanceConfigs/sample2"} + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.InstanceConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.get_instance_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{name=projects/*/instanceConfigs/*}" % client.transport._host, + args[1], + ) + + +def test_get_instance_config_rest_flattened_error(transport: str = "rest"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_instance_config( + spanner_instance_admin.GetInstanceConfigRequest(), + name="name_value", + ) + + +def test_get_instance_config_rest_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.CreateInstanceConfigRequest, + dict, + ], +) +def test_create_instance_config_rest(request_type): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.create_instance_config(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_create_instance_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.create_instance_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.create_instance_config + ] = mock_rpc + + request = {} + client.create_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.create_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_create_instance_config_rest_required_fields( + request_type=spanner_instance_admin.CreateInstanceConfigRequest, +): + transport_class = transports.InstanceAdminRestTransport + + request_init = {} + request_init["parent"] = "" + request_init["instance_config_id"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).create_instance_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + jsonified_request["instanceConfigId"] = "instance_config_id_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).create_instance_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + assert "instanceConfigId" in jsonified_request + assert jsonified_request["instanceConfigId"] == "instance_config_id_value" + + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.create_instance_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_create_instance_config_rest_unset_required_fields(): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.create_instance_config._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "parent", + "instanceConfigId", + "instanceConfig", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_create_instance_config_rest_interceptors(null_interceptor): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.InstanceAdminRestInterceptor(), + ) + client = InstanceAdminClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.InstanceAdminRestInterceptor, "post_create_instance_config" + ) as post, mock.patch.object( + transports.InstanceAdminRestInterceptor, "pre_create_instance_config" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = spanner_instance_admin.CreateInstanceConfigRequest.pb( + spanner_instance_admin.CreateInstanceConfigRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() + ) + + request = spanner_instance_admin.CreateInstanceConfigRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + + client.create_instance_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_create_instance_config_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.CreateInstanceConfigRequest, +): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.create_instance_config(request) + + +def test_create_instance_config_rest_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # get arguments that satisfy an http rule for this method + sample_request = {"parent": "projects/sample1"} + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + instance_config=spanner_instance_admin.InstanceConfig(name="name_value"), + instance_config_id="instance_config_id_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.create_instance_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{parent=projects/*}/instanceConfigs" % client.transport._host, + args[1], + ) + + +def test_create_instance_config_rest_flattened_error(transport: str = "rest"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.create_instance_config( + spanner_instance_admin.CreateInstanceConfigRequest(), + parent="parent_value", + instance_config=spanner_instance_admin.InstanceConfig(name="name_value"), + instance_config_id="instance_config_id_value", + ) + + +def test_create_instance_config_rest_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.UpdateInstanceConfigRequest, + dict, + ], +) +def test_update_instance_config_rest(request_type): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "instance_config": {"name": "projects/sample1/instanceConfigs/sample2"} + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.update_instance_config(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_update_instance_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_instance_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_instance_config + ] = mock_rpc + + request = {} + client.update_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.update_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_instance_config_rest_required_fields( + request_type=spanner_instance_admin.UpdateInstanceConfigRequest, +): + transport_class = transports.InstanceAdminRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_instance_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_instance_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "patch", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.update_instance_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_instance_config_rest_unset_required_fields(): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.update_instance_config._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "instanceConfig", + "updateMask", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_instance_config_rest_interceptors(null_interceptor): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.InstanceAdminRestInterceptor(), + ) + client = InstanceAdminClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.InstanceAdminRestInterceptor, "post_update_instance_config" + ) as post, mock.patch.object( + transports.InstanceAdminRestInterceptor, "pre_update_instance_config" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = spanner_instance_admin.UpdateInstanceConfigRequest.pb( + spanner_instance_admin.UpdateInstanceConfigRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() + ) + + request = spanner_instance_admin.UpdateInstanceConfigRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + + client.update_instance_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_instance_config_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.UpdateInstanceConfigRequest, +): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "instance_config": {"name": "projects/sample1/instanceConfigs/sample2"} + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.update_instance_config(request) + + +def test_update_instance_config_rest_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # get arguments that satisfy an http rule for this method + sample_request = { + "instance_config": {"name": "projects/sample1/instanceConfigs/sample2"} + } + + # get truthy value for each flattened field + mock_args = dict( + instance_config=spanner_instance_admin.InstanceConfig(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.update_instance_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{instance_config.name=projects/*/instanceConfigs/*}" + % client.transport._host, + args[1], + ) + + +def test_update_instance_config_rest_flattened_error(transport: str = "rest"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_instance_config( + spanner_instance_admin.UpdateInstanceConfigRequest(), + instance_config=spanner_instance_admin.InstanceConfig(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_instance_config_rest_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.DeleteInstanceConfigRequest, + dict, + ], +) +def test_delete_instance_config_rest(request_type): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/instanceConfigs/sample2"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = None + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.delete_instance_config(request) + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_instance_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.delete_instance_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.delete_instance_config + ] = mock_rpc + + request = {} + client.delete_instance_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.delete_instance_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_delete_instance_config_rest_required_fields( + request_type=spanner_instance_admin.DeleteInstanceConfigRequest, +): + transport_class = transports.InstanceAdminRestTransport + + request_init = {} + request_init["name"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).delete_instance_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["name"] = "name_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).delete_instance_config._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "etag", + "validate_only", + ) + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" + + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = None + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "delete", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.delete_instance_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_delete_instance_config_rest_unset_required_fields(): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_instance_config._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "etag", + "validateOnly", + ) + ) + & set(("name",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_delete_instance_config_rest_interceptors(null_interceptor): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.InstanceAdminRestInterceptor(), + ) + client = InstanceAdminClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.InstanceAdminRestInterceptor, "pre_delete_instance_config" + ) as pre: + pre.assert_not_called() + pb_message = spanner_instance_admin.DeleteInstanceConfigRequest.pb( + spanner_instance_admin.DeleteInstanceConfigRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + + request = spanner_instance_admin.DeleteInstanceConfigRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + + client.delete_instance_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + + +def test_delete_instance_config_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.DeleteInstanceConfigRequest, +): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/instanceConfigs/sample2"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.delete_instance_config(request) + + +def test_delete_instance_config_rest_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = None + + # get arguments that satisfy an http rule for this method + sample_request = {"name": "projects/sample1/instanceConfigs/sample2"} + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.delete_instance_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{name=projects/*/instanceConfigs/*}" % client.transport._host, + args[1], + ) + + +def test_delete_instance_config_rest_flattened_error(transport: str = "rest"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.delete_instance_config( + spanner_instance_admin.DeleteInstanceConfigRequest(), + name="name_value", + ) + + +def test_delete_instance_config_rest_error(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + spanner_instance_admin.ListInstanceConfigOperationsRequest, + dict, + ], +) +def test_list_instance_config_operations_rest(request_type): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse( + next_page_token="next_page_token_value", + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.list_instance_config_operations(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListInstanceConfigOperationsPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_instance_config_operations_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_instance_config_operations + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_instance_config_operations + ] = mock_rpc + + request = {} + client.list_instance_config_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_instance_config_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_instance_config_operations_rest_required_fields( + request_type=spanner_instance_admin.ListInstanceConfigOperationsRequest, +): + transport_class = transports.InstanceAdminRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_instance_config_operations._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_instance_config_operations._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "filter", + "page_size", + "page_token", + ) + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = ( + spanner_instance_admin.ListInstanceConfigOperationsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_instance_config_operations(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_instance_config_operations_rest_unset_required_fields(): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.list_instance_config_operations._get_unset_required_fields( + {} + ) + assert set(unset_fields) == ( + set( + ( + "filter", + "pageSize", + "pageToken", + ) + ) + & set(("parent",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_instance_config_operations_rest_interceptors(null_interceptor): + transport = transports.InstanceAdminRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.InstanceAdminRestInterceptor(), + ) + client = InstanceAdminClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.InstanceAdminRestInterceptor, "post_list_instance_config_operations" + ) as post, mock.patch.object( + transports.InstanceAdminRestInterceptor, "pre_list_instance_config_operations" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = spanner_instance_admin.ListInstanceConfigOperationsRequest.pb( + spanner_instance_admin.ListInstanceConfigOperationsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + spanner_instance_admin.ListInstanceConfigOperationsResponse.to_json( + spanner_instance_admin.ListInstanceConfigOperationsResponse() + ) + ) + + request = spanner_instance_admin.ListInstanceConfigOperationsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = ( + spanner_instance_admin.ListInstanceConfigOperationsResponse() + ) + + client.list_instance_config_operations( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_list_instance_config_operations_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.ListInstanceConfigOperationsRequest, +): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_instance_config_operations(request) + + +def test_list_instance_config_operations_rest_flattened(): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse() + + # get arguments that satisfy an http rule for this method + sample_request = {"parent": "projects/sample1"} + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.list_instance_config_operations(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{parent=projects/*}/instanceConfigOperations" + % client.transport._host, + args[1], + ) + + +def test_list_instance_config_operations_rest_flattened_error(transport: str = "rest"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_instance_config_operations( + spanner_instance_admin.ListInstanceConfigOperationsRequest(), + parent="parent_value", + ) + + +def test_list_instance_config_operations_rest_pager(transport: str = "rest"): + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + spanner_instance_admin.ListInstanceConfigOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstanceConfigOperationsResponse( + operations=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstanceConfigOperationsResponse( + operations=[ + operations_pb2.Operation(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstanceConfigOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple( + spanner_instance_admin.ListInstanceConfigOperationsResponse.to_json(x) + for x in response + ) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = {"parent": "projects/sample1"} + pager = client.list_instance_config_operations(request=sample_request) -@pytest.mark.asyncio -async def test_test_iam_permissions_flattened_error_async(): - client = InstanceAdminAsyncClient( - credentials=ga_credentials.AnonymousCredentials(), - ) + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, operations_pb2.Operation) for i in results) - # Attempting to call a method with both a request object and flattened - # fields is an error. - with pytest.raises(ValueError): - await client.test_iam_permissions( - iam_policy_pb2.TestIamPermissionsRequest(), - resource="resource_value", - permissions=["permissions_value"], + pages = list( + client.list_instance_config_operations(request=sample_request).pages ) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.ListInstanceConfigsRequest, + spanner_instance_admin.ListInstancesRequest, dict, ], ) -def test_list_instance_configs_rest(request_type): +def test_list_instances_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4831,30 +12181,66 @@ def test_list_instance_configs_rest(request_type): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.ListInstanceConfigsResponse( + return_value = spanner_instance_admin.ListInstancesResponse( next_page_token="next_page_token_value", + unreachable=["unreachable_value"], ) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = spanner_instance_admin.ListInstanceConfigsResponse.pb( - return_value - ) + return_value = spanner_instance_admin.ListInstancesResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.list_instance_configs(request) + response = client.list_instances(request) # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListInstanceConfigsPager) + assert isinstance(response, pagers.ListInstancesPager) assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] -def test_list_instance_configs_rest_required_fields( - request_type=spanner_instance_admin.ListInstanceConfigsRequest, +def test_list_instances_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.list_instances in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.list_instances] = mock_rpc + + request = {} + client.list_instances(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_instances(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_instances_rest_required_fields( + request_type=spanner_instance_admin.ListInstancesRequest, ): transport_class = transports.InstanceAdminRestTransport @@ -4863,18 +12249,14 @@ def test_list_instance_configs_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_instance_configs._get_unset_required_fields(jsonified_request) + ).list_instances._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -4883,10 +12265,12 @@ def test_list_instance_configs_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_instance_configs._get_unset_required_fields(jsonified_request) + ).list_instances._get_unset_required_fields(jsonified_request) # Check that path parameters and body parameters are not mixing in. assert not set(unset_fields) - set( ( + "filter", + "instance_deadline", "page_size", "page_token", ) @@ -4904,7 +12288,7 @@ def test_list_instance_configs_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.ListInstanceConfigsResponse() + return_value = spanner_instance_admin.ListInstancesResponse() # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -4925,30 +12309,30 @@ def test_list_instance_configs_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = spanner_instance_admin.ListInstanceConfigsResponse.pb( - return_value - ) + return_value = spanner_instance_admin.ListInstancesResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.list_instance_configs(request) + response = client.list_instances(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_list_instance_configs_rest_unset_required_fields(): +def test_list_instances_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.list_instance_configs._get_unset_required_fields({}) + unset_fields = transport.list_instances._get_unset_required_fields({}) assert set(unset_fields) == ( set( ( + "filter", + "instanceDeadline", "pageSize", "pageToken", ) @@ -4958,7 +12342,7 @@ def test_list_instance_configs_rest_unset_required_fields(): @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_list_instance_configs_rest_interceptors(null_interceptor): +def test_list_instances_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -4971,14 +12355,14 @@ def test_list_instance_configs_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_list_instance_configs" + transports.InstanceAdminRestInterceptor, "post_list_instances" ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_list_instance_configs" + transports.InstanceAdminRestInterceptor, "pre_list_instances" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = spanner_instance_admin.ListInstanceConfigsRequest.pb( - spanner_instance_admin.ListInstanceConfigsRequest() + pb_message = spanner_instance_admin.ListInstancesRequest.pb( + spanner_instance_admin.ListInstancesRequest() ) transcode.return_value = { "method": "post", @@ -4991,20 +12375,20 @@ def test_list_instance_configs_rest_interceptors(null_interceptor): req.return_value.status_code = 200 req.return_value.request = PreparedRequest() req.return_value._content = ( - spanner_instance_admin.ListInstanceConfigsResponse.to_json( - spanner_instance_admin.ListInstanceConfigsResponse() + spanner_instance_admin.ListInstancesResponse.to_json( + spanner_instance_admin.ListInstancesResponse() ) ) - request = spanner_instance_admin.ListInstanceConfigsRequest() + request = spanner_instance_admin.ListInstancesRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = spanner_instance_admin.ListInstanceConfigsResponse() + post.return_value = spanner_instance_admin.ListInstancesResponse() - client.list_instance_configs( + client.list_instances( request, metadata=[ ("key", "val"), @@ -5016,9 +12400,8 @@ def test_list_instance_configs_rest_interceptors(null_interceptor): post.assert_called_once() -def test_list_instance_configs_rest_bad_request( - transport: str = "rest", - request_type=spanner_instance_admin.ListInstanceConfigsRequest, +def test_list_instances_rest_bad_request( + transport: str = "rest", request_type=spanner_instance_admin.ListInstancesRequest ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -5038,10 +12421,10 @@ def test_list_instance_configs_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.list_instance_configs(request) + client.list_instances(request) -def test_list_instance_configs_rest_flattened(): +def test_list_instances_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -5050,7 +12433,7 @@ def test_list_instance_configs_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.ListInstanceConfigsResponse() + return_value = spanner_instance_admin.ListInstancesResponse() # get arguments that satisfy an http rule for this method sample_request = {"parent": "projects/sample1"} @@ -5065,26 +12448,23 @@ def test_list_instance_configs_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = spanner_instance_admin.ListInstanceConfigsResponse.pb( - return_value - ) + return_value = spanner_instance_admin.ListInstancesResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.list_instance_configs(**mock_args) + client.list_instances(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{parent=projects/*}/instanceConfigs" % client.transport._host, - args[1], + "%s/v1/{parent=projects/*}/instances" % client.transport._host, args[1] ) -def test_list_instance_configs_rest_flattened_error(transport: str = "rest"): +def test_list_instances_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -5093,13 +12473,13 @@ def test_list_instance_configs_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.list_instance_configs( - spanner_instance_admin.ListInstanceConfigsRequest(), + client.list_instances( + spanner_instance_admin.ListInstancesRequest(), parent="parent_value", ) -def test_list_instance_configs_rest_pager(transport: str = "rest"): +def test_list_instances_rest_pager(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -5111,28 +12491,28 @@ def test_list_instance_configs_rest_pager(transport: str = "rest"): # with mock.patch.object(path_template, 'transcode') as transcode: # Set the response as a series of pages response = ( - spanner_instance_admin.ListInstanceConfigsResponse( - instance_configs=[ - spanner_instance_admin.InstanceConfig(), - spanner_instance_admin.InstanceConfig(), - spanner_instance_admin.InstanceConfig(), + spanner_instance_admin.ListInstancesResponse( + instances=[ + spanner_instance_admin.Instance(), + spanner_instance_admin.Instance(), + spanner_instance_admin.Instance(), ], next_page_token="abc", ), - spanner_instance_admin.ListInstanceConfigsResponse( - instance_configs=[], + spanner_instance_admin.ListInstancesResponse( + instances=[], next_page_token="def", ), - spanner_instance_admin.ListInstanceConfigsResponse( - instance_configs=[ - spanner_instance_admin.InstanceConfig(), + spanner_instance_admin.ListInstancesResponse( + instances=[ + spanner_instance_admin.Instance(), ], next_page_token="ghi", ), - spanner_instance_admin.ListInstanceConfigsResponse( - instance_configs=[ - spanner_instance_admin.InstanceConfig(), - spanner_instance_admin.InstanceConfig(), + spanner_instance_admin.ListInstancesResponse( + instances=[ + spanner_instance_admin.Instance(), + spanner_instance_admin.Instance(), ], ), ) @@ -5141,8 +12521,7 @@ def test_list_instance_configs_rest_pager(transport: str = "rest"): # Wrap the values into proper Response objs response = tuple( - spanner_instance_admin.ListInstanceConfigsResponse.to_json(x) - for x in response + spanner_instance_admin.ListInstancesResponse.to_json(x) for x in response ) return_values = tuple(Response() for i in response) for return_val, response_val in zip(return_values, response): @@ -5152,15 +12531,13 @@ def test_list_instance_configs_rest_pager(transport: str = "rest"): sample_request = {"parent": "projects/sample1"} - pager = client.list_instance_configs(request=sample_request) + pager = client.list_instances(request=sample_request) results = list(pager) assert len(results) == 6 - assert all( - isinstance(i, spanner_instance_admin.InstanceConfig) for i in results - ) + assert all(isinstance(i, spanner_instance_admin.Instance) for i in results) - pages = list(client.list_instance_configs(request=sample_request).pages) + pages = list(client.list_instances(request=sample_request).pages) for page_, token in zip(pages, ["abc", "def", "ghi", ""]): assert page_.raw_page.next_page_token == token @@ -5168,96 +12545,128 @@ def test_list_instance_configs_rest_pager(transport: str = "rest"): @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.GetInstanceConfigRequest, + spanner_instance_admin.ListInstancePartitionsRequest, dict, ], ) -def test_get_instance_config_rest(request_type): +def test_list_instance_partitions_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"name": "projects/sample1/instanceConfigs/sample2"} + request_init = {"parent": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.InstanceConfig( - name="name_value", - display_name="display_name_value", - config_type=spanner_instance_admin.InstanceConfig.Type.GOOGLE_MANAGED, - base_config="base_config_value", - etag="etag_value", - leader_options=["leader_options_value"], - reconciling=True, - state=spanner_instance_admin.InstanceConfig.State.CREATING, + return_value = spanner_instance_admin.ListInstancePartitionsResponse( + next_page_token="next_page_token_value", + unreachable=["unreachable_value"], ) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = spanner_instance_admin.InstanceConfig.pb(return_value) + return_value = spanner_instance_admin.ListInstancePartitionsResponse.pb( + return_value + ) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.get_instance_config(request) + response = client.list_instance_partitions(request) # Establish that the response is the type that we expect. - assert isinstance(response, spanner_instance_admin.InstanceConfig) - assert response.name == "name_value" - assert response.display_name == "display_name_value" - assert ( - response.config_type - == spanner_instance_admin.InstanceConfig.Type.GOOGLE_MANAGED - ) - assert response.base_config == "base_config_value" - assert response.etag == "etag_value" - assert response.leader_options == ["leader_options_value"] - assert response.reconciling is True - assert response.state == spanner_instance_admin.InstanceConfig.State.CREATING + assert isinstance(response, pagers.ListInstancePartitionsPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] -def test_get_instance_config_rest_required_fields( - request_type=spanner_instance_admin.GetInstanceConfigRequest, +def test_list_instance_partitions_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_instance_partitions + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_instance_partitions + ] = mock_rpc + + request = {} + client.list_instance_partitions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_instance_partitions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_instance_partitions_rest_required_fields( + request_type=spanner_instance_admin.ListInstancePartitionsRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["name"] = "" + request_init["parent"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_instance_config._get_unset_required_fields(jsonified_request) + ).list_instance_partitions._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["name"] = "name_value" + jsonified_request["parent"] = "parent_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_instance_config._get_unset_required_fields(jsonified_request) + ).list_instance_partitions._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "instance_partition_deadline", + "page_size", + "page_token", + ) + ) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "name" in jsonified_request - assert jsonified_request["name"] == "name_value" + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -5266,7 +12675,7 @@ def test_get_instance_config_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.InstanceConfig() + return_value = spanner_instance_admin.ListInstancePartitionsResponse() # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -5287,30 +12696,41 @@ def test_get_instance_config_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = spanner_instance_admin.InstanceConfig.pb(return_value) + return_value = spanner_instance_admin.ListInstancePartitionsResponse.pb( + return_value + ) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.get_instance_config(request) + response = client.list_instance_partitions(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_get_instance_config_rest_unset_required_fields(): +def test_list_instance_partitions_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.get_instance_config._get_unset_required_fields({}) - assert set(unset_fields) == (set(()) & set(("name",))) + unset_fields = transport.list_instance_partitions._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "instancePartitionDeadline", + "pageSize", + "pageToken", + ) + ) + & set(("parent",)) + ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_get_instance_config_rest_interceptors(null_interceptor): +def test_list_instance_partitions_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -5323,14 +12743,14 @@ def test_get_instance_config_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_get_instance_config" + transports.InstanceAdminRestInterceptor, "post_list_instance_partitions" ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_get_instance_config" + transports.InstanceAdminRestInterceptor, "pre_list_instance_partitions" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = spanner_instance_admin.GetInstanceConfigRequest.pb( - spanner_instance_admin.GetInstanceConfigRequest() + pb_message = spanner_instance_admin.ListInstancePartitionsRequest.pb( + spanner_instance_admin.ListInstancePartitionsRequest() ) transcode.return_value = { "method": "post", @@ -5342,19 +12762,21 @@ def test_get_instance_config_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = spanner_instance_admin.InstanceConfig.to_json( - spanner_instance_admin.InstanceConfig() + req.return_value._content = ( + spanner_instance_admin.ListInstancePartitionsResponse.to_json( + spanner_instance_admin.ListInstancePartitionsResponse() + ) ) - request = spanner_instance_admin.GetInstanceConfigRequest() + request = spanner_instance_admin.ListInstancePartitionsRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = spanner_instance_admin.InstanceConfig() + post.return_value = spanner_instance_admin.ListInstancePartitionsResponse() - client.get_instance_config( + client.list_instance_partitions( request, metadata=[ ("key", "val"), @@ -5366,9 +12788,9 @@ def test_get_instance_config_rest_interceptors(null_interceptor): post.assert_called_once() -def test_get_instance_config_rest_bad_request( +def test_list_instance_partitions_rest_bad_request( transport: str = "rest", - request_type=spanner_instance_admin.GetInstanceConfigRequest, + request_type=spanner_instance_admin.ListInstancePartitionsRequest, ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -5376,7 +12798,7 @@ def test_get_instance_config_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"name": "projects/sample1/instanceConfigs/sample2"} + request_init = {"parent": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -5388,10 +12810,10 @@ def test_get_instance_config_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.get_instance_config(request) + client.list_instance_partitions(request) -def test_get_instance_config_rest_flattened(): +def test_list_instance_partitions_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -5400,14 +12822,14 @@ def test_get_instance_config_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.InstanceConfig() + return_value = spanner_instance_admin.ListInstancePartitionsResponse() # get arguments that satisfy an http rule for this method - sample_request = {"name": "projects/sample1/instanceConfigs/sample2"} + sample_request = {"parent": "projects/sample1/instances/sample2"} # get truthy value for each flattened field mock_args = dict( - name="name_value", + parent="parent_value", ) mock_args.update(sample_request) @@ -5415,24 +12837,27 @@ def test_get_instance_config_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = spanner_instance_admin.InstanceConfig.pb(return_value) + return_value = spanner_instance_admin.ListInstancePartitionsResponse.pb( + return_value + ) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.get_instance_config(**mock_args) + client.list_instance_partitions(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{name=projects/*/instanceConfigs/*}" % client.transport._host, + "%s/v1/{parent=projects/*/instances/*}/instancePartitions" + % client.transport._host, args[1], ) -def test_get_instance_config_rest_flattened_error(transport: str = "rest"): +def test_list_instance_partitions_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -5441,93 +12866,200 @@ def test_get_instance_config_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.get_instance_config( - spanner_instance_admin.GetInstanceConfigRequest(), - name="name_value", + client.list_instance_partitions( + spanner_instance_admin.ListInstancePartitionsRequest(), + parent="parent_value", ) -def test_get_instance_config_rest_error(): +def test_list_instance_partitions_rest_pager(transport: str = "rest"): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), transport="rest" + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, ) + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionsResponse( + instance_partitions=[ + spanner_instance_admin.InstancePartition(), + spanner_instance_admin.InstancePartition(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple( + spanner_instance_admin.ListInstancePartitionsResponse.to_json(x) + for x in response + ) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = {"parent": "projects/sample1/instances/sample2"} + + pager = client.list_instance_partitions(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all( + isinstance(i, spanner_instance_admin.InstancePartition) for i in results + ) + + pages = list(client.list_instance_partitions(request=sample_request).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.CreateInstanceConfigRequest, + spanner_instance_admin.GetInstanceRequest, dict, ], ) -def test_create_instance_config_rest(request_type): +def test_get_instance_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1"} + request_init = {"name": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = spanner_instance_admin.Instance( + name="name_value", + config="config_value", + display_name="display_name_value", + node_count=1070, + processing_units=1743, + state=spanner_instance_admin.Instance.State.CREATING, + endpoint_uris=["endpoint_uris_value"], + ) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.Instance.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.create_instance_config(request) + response = client.get_instance(request) # Establish that the response is the type that we expect. - assert response.operation.name == "operations/spam" + assert isinstance(response, spanner_instance_admin.Instance) + assert response.name == "name_value" + assert response.config == "config_value" + assert response.display_name == "display_name_value" + assert response.node_count == 1070 + assert response.processing_units == 1743 + assert response.state == spanner_instance_admin.Instance.State.CREATING + assert response.endpoint_uris == ["endpoint_uris_value"] -def test_create_instance_config_rest_required_fields( - request_type=spanner_instance_admin.CreateInstanceConfigRequest, +def test_get_instance_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_instance in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_instance] = mock_rpc + + request = {} + client.get_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_instance(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_get_instance_rest_required_fields( + request_type=spanner_instance_admin.GetInstanceRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["parent"] = "" - request_init["instance_config_id"] = "" + request_init["name"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_instance_config._get_unset_required_fields(jsonified_request) + ).get_instance._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["parent"] = "parent_value" - jsonified_request["instanceConfigId"] = "instance_config_id_value" + jsonified_request["name"] = "name_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_instance_config._get_unset_required_fields(jsonified_request) + ).get_instance._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("field_mask",)) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "parent" in jsonified_request - assert jsonified_request["parent"] == "parent_value" - assert "instanceConfigId" in jsonified_request - assert jsonified_request["instanceConfigId"] == "instance_config_id_value" + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -5536,7 +13068,7 @@ def test_create_instance_config_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = spanner_instance_admin.Instance() # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -5548,46 +13080,39 @@ def test_create_instance_config_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "post", + "method": "get", "query_params": pb_request, } - transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = spanner_instance_admin.Instance.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.create_instance_config(request) + response = client.get_instance(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_create_instance_config_rest_unset_required_fields(): +def test_get_instance_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.create_instance_config._get_unset_required_fields({}) - assert set(unset_fields) == ( - set(()) - & set( - ( - "parent", - "instanceConfigId", - "instanceConfig", - ) - ) - ) + unset_fields = transport.get_instance._get_unset_required_fields({}) + assert set(unset_fields) == (set(("fieldMask",)) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_create_instance_config_rest_interceptors(null_interceptor): +def test_get_instance_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -5600,16 +13125,14 @@ def test_create_instance_config_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - operation.Operation, "_set_result_from_operation" - ), mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_create_instance_config" + transports.InstanceAdminRestInterceptor, "post_get_instance" ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_create_instance_config" + transports.InstanceAdminRestInterceptor, "pre_get_instance" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = spanner_instance_admin.CreateInstanceConfigRequest.pb( - spanner_instance_admin.CreateInstanceConfigRequest() + pb_message = spanner_instance_admin.GetInstanceRequest.pb( + spanner_instance_admin.GetInstanceRequest() ) transcode.return_value = { "method": "post", @@ -5621,19 +13144,19 @@ def test_create_instance_config_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = json_format.MessageToJson( - operations_pb2.Operation() + req.return_value._content = spanner_instance_admin.Instance.to_json( + spanner_instance_admin.Instance() ) - request = spanner_instance_admin.CreateInstanceConfigRequest() + request = spanner_instance_admin.GetInstanceRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = operations_pb2.Operation() + post.return_value = spanner_instance_admin.Instance() - client.create_instance_config( + client.get_instance( request, metadata=[ ("key", "val"), @@ -5645,9 +13168,8 @@ def test_create_instance_config_rest_interceptors(null_interceptor): post.assert_called_once() -def test_create_instance_config_rest_bad_request( - transport: str = "rest", - request_type=spanner_instance_admin.CreateInstanceConfigRequest, +def test_get_instance_rest_bad_request( + transport: str = "rest", request_type=spanner_instance_admin.GetInstanceRequest ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -5655,7 +13177,7 @@ def test_create_instance_config_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1"} + request_init = {"name": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -5667,10 +13189,10 @@ def test_create_instance_config_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.create_instance_config(request) + client.get_instance(request) -def test_create_instance_config_rest_flattened(): +def test_get_instance_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -5679,39 +13201,38 @@ def test_create_instance_config_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = spanner_instance_admin.Instance() # get arguments that satisfy an http rule for this method - sample_request = {"parent": "projects/sample1"} + sample_request = {"name": "projects/sample1/instances/sample2"} # get truthy value for each flattened field mock_args = dict( - parent="parent_value", - instance_config=spanner_instance_admin.InstanceConfig(name="name_value"), - instance_config_id="instance_config_id_value", + name="name_value", ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.Instance.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.create_instance_config(**mock_args) + client.get_instance(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{parent=projects/*}/instanceConfigs" % client.transport._host, - args[1], + "%s/v1/{name=projects/*/instances/*}" % client.transport._host, args[1] ) -def test_create_instance_config_rest_flattened_error(transport: str = "rest"): +def test_get_instance_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -5720,15 +13241,13 @@ def test_create_instance_config_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.create_instance_config( - spanner_instance_admin.CreateInstanceConfigRequest(), - parent="parent_value", - instance_config=spanner_instance_admin.InstanceConfig(name="name_value"), - instance_config_id="instance_config_id_value", + client.get_instance( + spanner_instance_admin.GetInstanceRequest(), + name="name_value", ) -def test_create_instance_config_rest_error(): +def test_get_instance_rest_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -5737,20 +13256,18 @@ def test_create_instance_config_rest_error(): @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.UpdateInstanceConfigRequest, + spanner_instance_admin.CreateInstanceRequest, dict, ], ) -def test_update_instance_config_rest(request_type): +def test_create_instance_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = { - "instance_config": {"name": "projects/sample1/instanceConfigs/sample2"} - } + request_init = {"parent": "projects/sample1"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. @@ -5763,45 +13280,90 @@ def test_update_instance_config_rest(request_type): response_value.status_code = 200 json_return_value = json_format.MessageToJson(return_value) - response_value._content = json_return_value.encode("UTF-8") - req.return_value = response_value - response = client.update_instance_config(request) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.create_instance(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_create_instance_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.create_instance in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.create_instance] = mock_rpc + + request = {} + client.create_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 - # Establish that the response is the type that we expect. - assert response.operation.name == "operations/spam" + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + client.create_instance(request) -def test_update_instance_config_rest_required_fields( - request_type=spanner_instance_admin.UpdateInstanceConfigRequest, + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_create_instance_rest_required_fields( + request_type=spanner_instance_admin.CreateInstanceRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} + request_init["parent"] = "" + request_init["instance_id"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).update_instance_config._get_unset_required_fields(jsonified_request) + ).create_instance._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present + jsonified_request["parent"] = "parent_value" + jsonified_request["instanceId"] = "instance_id_value" + unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).update_instance_config._get_unset_required_fields(jsonified_request) + ).create_instance._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + assert "instanceId" in jsonified_request + assert jsonified_request["instanceId"] == "instance_id_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -5822,7 +13384,7 @@ def test_update_instance_config_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "patch", + "method": "post", "query_params": pb_request, } transcode_result["body"] = pb_request @@ -5835,32 +13397,33 @@ def test_update_instance_config_rest_required_fields( response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.update_instance_config(request) + response = client.create_instance(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_update_instance_config_rest_unset_required_fields(): +def test_create_instance_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.update_instance_config._get_unset_required_fields({}) + unset_fields = transport.create_instance._get_unset_required_fields({}) assert set(unset_fields) == ( set(()) & set( ( - "instanceConfig", - "updateMask", + "parent", + "instanceId", + "instance", ) ) ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_update_instance_config_rest_interceptors(null_interceptor): +def test_create_instance_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -5875,14 +13438,14 @@ def test_update_instance_config_rest_interceptors(null_interceptor): ) as transcode, mock.patch.object( operation.Operation, "_set_result_from_operation" ), mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_update_instance_config" + transports.InstanceAdminRestInterceptor, "post_create_instance" ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_update_instance_config" + transports.InstanceAdminRestInterceptor, "pre_create_instance" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = spanner_instance_admin.UpdateInstanceConfigRequest.pb( - spanner_instance_admin.UpdateInstanceConfigRequest() + pb_message = spanner_instance_admin.CreateInstanceRequest.pb( + spanner_instance_admin.CreateInstanceRequest() ) transcode.return_value = { "method": "post", @@ -5898,7 +13461,7 @@ def test_update_instance_config_rest_interceptors(null_interceptor): operations_pb2.Operation() ) - request = spanner_instance_admin.UpdateInstanceConfigRequest() + request = spanner_instance_admin.CreateInstanceRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), @@ -5906,7 +13469,7 @@ def test_update_instance_config_rest_interceptors(null_interceptor): pre.return_value = request, metadata post.return_value = operations_pb2.Operation() - client.update_instance_config( + client.create_instance( request, metadata=[ ("key", "val"), @@ -5918,9 +13481,8 @@ def test_update_instance_config_rest_interceptors(null_interceptor): post.assert_called_once() -def test_update_instance_config_rest_bad_request( - transport: str = "rest", - request_type=spanner_instance_admin.UpdateInstanceConfigRequest, +def test_create_instance_rest_bad_request( + transport: str = "rest", request_type=spanner_instance_admin.CreateInstanceRequest ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -5928,9 +13490,7 @@ def test_update_instance_config_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = { - "instance_config": {"name": "projects/sample1/instanceConfigs/sample2"} - } + request_init = {"parent": "projects/sample1"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -5942,10 +13502,10 @@ def test_update_instance_config_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.update_instance_config(request) + client.create_instance(request) -def test_update_instance_config_rest_flattened(): +def test_create_instance_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -5957,14 +13517,13 @@ def test_update_instance_config_rest_flattened(): return_value = operations_pb2.Operation(name="operations/spam") # get arguments that satisfy an http rule for this method - sample_request = { - "instance_config": {"name": "projects/sample1/instanceConfigs/sample2"} - } + sample_request = {"parent": "projects/sample1"} # get truthy value for each flattened field mock_args = dict( - instance_config=spanner_instance_admin.InstanceConfig(name="name_value"), - update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + parent="parent_value", + instance_id="instance_id_value", + instance=spanner_instance_admin.Instance(name="name_value"), ) mock_args.update(sample_request) @@ -5975,20 +13534,18 @@ def test_update_instance_config_rest_flattened(): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.update_instance_config(**mock_args) + client.create_instance(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{instance_config.name=projects/*/instanceConfigs/*}" - % client.transport._host, - args[1], + "%s/v1/{parent=projects/*}/instances" % client.transport._host, args[1] ) -def test_update_instance_config_rest_flattened_error(transport: str = "rest"): +def test_create_instance_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -5997,14 +13554,15 @@ def test_update_instance_config_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.update_instance_config( - spanner_instance_admin.UpdateInstanceConfigRequest(), - instance_config=spanner_instance_admin.InstanceConfig(name="name_value"), - update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + client.create_instance( + spanner_instance_admin.CreateInstanceRequest(), + parent="parent_value", + instance_id="instance_id_value", + instance=spanner_instance_admin.Instance(name="name_value"), ) -def test_update_instance_config_rest_error(): +def test_create_instance_rest_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -6013,81 +13571,105 @@ def test_update_instance_config_rest_error(): @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.DeleteInstanceConfigRequest, + spanner_instance_admin.UpdateInstanceRequest, dict, ], ) -def test_delete_instance_config_rest(request_type): +def test_update_instance_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"name": "projects/sample1/instanceConfigs/sample2"} + request_init = {"instance": {"name": "projects/sample1/instances/sample2"}} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = None + return_value = operations_pb2.Operation(name="operations/spam") # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - json_return_value = "" + json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.delete_instance_config(request) + response = client.update_instance(request) # Establish that the response is the type that we expect. - assert response is None + assert response.operation.name == "operations/spam" -def test_delete_instance_config_rest_required_fields( - request_type=spanner_instance_admin.DeleteInstanceConfigRequest, +def test_update_instance_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.update_instance in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.update_instance] = mock_rpc + + request = {} + client.update_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.update_instance(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_instance_rest_required_fields( + request_type=spanner_instance_admin.UpdateInstanceRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["name"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_instance_config._get_unset_required_fields(jsonified_request) + ).update_instance._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["name"] = "name_value" - unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_instance_config._get_unset_required_fields(jsonified_request) - # Check that path parameters and body parameters are not mixing in. - assert not set(unset_fields) - set( - ( - "etag", - "validate_only", - ) - ) + ).update_instance._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "name" in jsonified_request - assert jsonified_request["name"] == "name_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -6096,7 +13678,7 @@ def test_delete_instance_config_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = None + return_value = operations_pb2.Operation(name="operations/spam") # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -6108,44 +13690,45 @@ def test_delete_instance_config_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "delete", + "method": "patch", "query_params": pb_request, } + transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 - json_return_value = "" + json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.delete_instance_config(request) + response = client.update_instance(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_delete_instance_config_rest_unset_required_fields(): +def test_update_instance_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.delete_instance_config._get_unset_required_fields({}) + unset_fields = transport.update_instance._get_unset_required_fields({}) assert set(unset_fields) == ( - set( + set(()) + & set( ( - "etag", - "validateOnly", + "instance", + "fieldMask", ) ) - & set(("name",)) ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_delete_instance_config_rest_interceptors(null_interceptor): +def test_update_instance_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -6158,11 +13741,16 @@ def test_delete_instance_config_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_delete_instance_config" + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.InstanceAdminRestInterceptor, "post_update_instance" + ) as post, mock.patch.object( + transports.InstanceAdminRestInterceptor, "pre_update_instance" ) as pre: pre.assert_not_called() - pb_message = spanner_instance_admin.DeleteInstanceConfigRequest.pb( - spanner_instance_admin.DeleteInstanceConfigRequest() + post.assert_not_called() + pb_message = spanner_instance_admin.UpdateInstanceRequest.pb( + spanner_instance_admin.UpdateInstanceRequest() ) transcode.return_value = { "method": "post", @@ -6174,15 +13762,19 @@ def test_delete_instance_config_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() + ) - request = spanner_instance_admin.DeleteInstanceConfigRequest() + request = spanner_instance_admin.UpdateInstanceRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() - client.delete_instance_config( + client.update_instance( request, metadata=[ ("key", "val"), @@ -6191,11 +13783,11 @@ def test_delete_instance_config_rest_interceptors(null_interceptor): ) pre.assert_called_once() + post.assert_called_once() -def test_delete_instance_config_rest_bad_request( - transport: str = "rest", - request_type=spanner_instance_admin.DeleteInstanceConfigRequest, +def test_update_instance_rest_bad_request( + transport: str = "rest", request_type=spanner_instance_admin.UpdateInstanceRequest ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -6203,7 +13795,7 @@ def test_delete_instance_config_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"name": "projects/sample1/instanceConfigs/sample2"} + request_init = {"instance": {"name": "projects/sample1/instances/sample2"}} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -6215,10 +13807,10 @@ def test_delete_instance_config_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.delete_instance_config(request) + client.update_instance(request) -def test_delete_instance_config_rest_flattened(): +def test_update_instance_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -6227,37 +13819,38 @@ def test_delete_instance_config_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = None + return_value = operations_pb2.Operation(name="operations/spam") # get arguments that satisfy an http rule for this method - sample_request = {"name": "projects/sample1/instanceConfigs/sample2"} + sample_request = {"instance": {"name": "projects/sample1/instances/sample2"}} # get truthy value for each flattened field mock_args = dict( - name="name_value", + instance=spanner_instance_admin.Instance(name="name_value"), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - json_return_value = "" + json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.delete_instance_config(**mock_args) + client.update_instance(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{name=projects/*/instanceConfigs/*}" % client.transport._host, + "%s/v1/{instance.name=projects/*/instances/*}" % client.transport._host, args[1], ) -def test_delete_instance_config_rest_flattened_error(transport: str = "rest"): +def test_update_instance_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -6266,13 +13859,14 @@ def test_delete_instance_config_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.delete_instance_config( - spanner_instance_admin.DeleteInstanceConfigRequest(), - name="name_value", + client.update_instance( + spanner_instance_admin.UpdateInstanceRequest(), + instance=spanner_instance_admin.Instance(name="name_value"), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) -def test_delete_instance_config_rest_error(): +def test_update_instance_rest_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -6281,89 +13875,106 @@ def test_delete_instance_config_rest_error(): @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.ListInstanceConfigOperationsRequest, + spanner_instance_admin.DeleteInstanceRequest, dict, ], ) -def test_list_instance_config_operations_rest(request_type): +def test_delete_instance_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1"} + request_init = {"name": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse( - next_page_token="next_page_token_value", - ) + return_value = None # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - # Convert return value to protobuf type - return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse.pb( - return_value + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.delete_instance(request) + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_instance_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", ) - json_return_value = json_format.MessageToJson(return_value) - response_value._content = json_return_value.encode("UTF-8") - req.return_value = response_value - response = client.list_instance_config_operations(request) + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.delete_instance in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.delete_instance] = mock_rpc + + request = {} + client.delete_instance(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 - # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListInstanceConfigOperationsPager) - assert response.next_page_token == "next_page_token_value" + client.delete_instance(request) + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 -def test_list_instance_config_operations_rest_required_fields( - request_type=spanner_instance_admin.ListInstanceConfigOperationsRequest, + +def test_delete_instance_rest_required_fields( + request_type=spanner_instance_admin.DeleteInstanceRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["parent"] = "" + request_init["name"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_instance_config_operations._get_unset_required_fields(jsonified_request) + ).delete_instance._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["parent"] = "parent_value" + jsonified_request["name"] = "name_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_instance_config_operations._get_unset_required_fields(jsonified_request) - # Check that path parameters and body parameters are not mixing in. - assert not set(unset_fields) - set( - ( - "filter", - "page_size", - "page_token", - ) - ) + ).delete_instance._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "parent" in jsonified_request - assert jsonified_request["parent"] == "parent_value" + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -6372,7 +13983,7 @@ def test_list_instance_config_operations_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse() + return_value = None # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -6384,54 +13995,36 @@ def test_list_instance_config_operations_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "get", + "method": "delete", "query_params": pb_request, } transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 - - # Convert return value to protobuf type - return_value = ( - spanner_instance_admin.ListInstanceConfigOperationsResponse.pb( - return_value - ) - ) - json_return_value = json_format.MessageToJson(return_value) + json_return_value = "" response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.list_instance_config_operations(request) + response = client.delete_instance(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_list_instance_config_operations_rest_unset_required_fields(): +def test_delete_instance_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.list_instance_config_operations._get_unset_required_fields( - {} - ) - assert set(unset_fields) == ( - set( - ( - "filter", - "pageSize", - "pageToken", - ) - ) - & set(("parent",)) - ) + unset_fields = transport.delete_instance._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_list_instance_config_operations_rest_interceptors(null_interceptor): +def test_delete_instance_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -6444,14 +14037,11 @@ def test_list_instance_config_operations_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_list_instance_config_operations" - ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_list_instance_config_operations" + transports.InstanceAdminRestInterceptor, "pre_delete_instance" ) as pre: pre.assert_not_called() - post.assert_not_called() - pb_message = spanner_instance_admin.ListInstanceConfigOperationsRequest.pb( - spanner_instance_admin.ListInstanceConfigOperationsRequest() + pb_message = spanner_instance_admin.DeleteInstanceRequest.pb( + spanner_instance_admin.DeleteInstanceRequest() ) transcode.return_value = { "method": "post", @@ -6463,23 +14053,15 @@ def test_list_instance_config_operations_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = ( - spanner_instance_admin.ListInstanceConfigOperationsResponse.to_json( - spanner_instance_admin.ListInstanceConfigOperationsResponse() - ) - ) - request = spanner_instance_admin.ListInstanceConfigOperationsRequest() + request = spanner_instance_admin.DeleteInstanceRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = ( - spanner_instance_admin.ListInstanceConfigOperationsResponse() - ) - client.list_instance_config_operations( + client.delete_instance( request, metadata=[ ("key", "val"), @@ -6488,12 +14070,10 @@ def test_list_instance_config_operations_rest_interceptors(null_interceptor): ) pre.assert_called_once() - post.assert_called_once() -def test_list_instance_config_operations_rest_bad_request( - transport: str = "rest", - request_type=spanner_instance_admin.ListInstanceConfigOperationsRequest, +def test_delete_instance_rest_bad_request( + transport: str = "rest", request_type=spanner_instance_admin.DeleteInstanceRequest ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -6501,7 +14081,7 @@ def test_list_instance_config_operations_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1"} + request_init = {"name": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -6513,10 +14093,10 @@ def test_list_instance_config_operations_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.list_instance_config_operations(request) + client.delete_instance(request) -def test_list_instance_config_operations_rest_flattened(): +def test_delete_instance_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -6525,42 +14105,36 @@ def test_list_instance_config_operations_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse() + return_value = None # get arguments that satisfy an http rule for this method - sample_request = {"parent": "projects/sample1"} + sample_request = {"name": "projects/sample1/instances/sample2"} # get truthy value for each flattened field mock_args = dict( - parent="parent_value", + name="name_value", ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - # Convert return value to protobuf type - return_value = spanner_instance_admin.ListInstanceConfigOperationsResponse.pb( - return_value - ) - json_return_value = json_format.MessageToJson(return_value) + json_return_value = "" response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.list_instance_config_operations(**mock_args) + client.delete_instance(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{parent=projects/*}/instanceConfigOperations" - % client.transport._host, - args[1], + "%s/v1/{name=projects/*/instances/*}" % client.transport._host, args[1] ) -def test_list_instance_config_operations_rest_flattened_error(transport: str = "rest"): +def test_delete_instance_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -6569,162 +14143,126 @@ def test_list_instance_config_operations_rest_flattened_error(transport: str = " # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.list_instance_config_operations( - spanner_instance_admin.ListInstanceConfigOperationsRequest(), - parent="parent_value", + client.delete_instance( + spanner_instance_admin.DeleteInstanceRequest(), + name="name_value", ) -def test_list_instance_config_operations_rest_pager(transport: str = "rest"): +def test_delete_instance_rest_error(): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) - # Mock the http request call within the method and fake a response. - with mock.patch.object(Session, "request") as req: - # TODO(kbandes): remove this mock unless there's a good reason for it. - # with mock.patch.object(path_template, 'transcode') as transcode: - # Set the response as a series of pages - response = ( - spanner_instance_admin.ListInstanceConfigOperationsResponse( - operations=[ - operations_pb2.Operation(), - operations_pb2.Operation(), - operations_pb2.Operation(), - ], - next_page_token="abc", - ), - spanner_instance_admin.ListInstanceConfigOperationsResponse( - operations=[], - next_page_token="def", - ), - spanner_instance_admin.ListInstanceConfigOperationsResponse( - operations=[ - operations_pb2.Operation(), - ], - next_page_token="ghi", - ), - spanner_instance_admin.ListInstanceConfigOperationsResponse( - operations=[ - operations_pb2.Operation(), - operations_pb2.Operation(), - ], - ), - ) - # Two responses for two calls - response = response + response - - # Wrap the values into proper Response objs - response = tuple( - spanner_instance_admin.ListInstanceConfigOperationsResponse.to_json(x) - for x in response - ) - return_values = tuple(Response() for i in response) - for return_val, response_val in zip(return_values, response): - return_val._content = response_val.encode("UTF-8") - return_val.status_code = 200 - req.side_effect = return_values - - sample_request = {"parent": "projects/sample1"} - - pager = client.list_instance_config_operations(request=sample_request) - - results = list(pager) - assert len(results) == 6 - assert all(isinstance(i, operations_pb2.Operation) for i in results) - - pages = list( - client.list_instance_config_operations(request=sample_request).pages - ) - for page_, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page_.raw_page.next_page_token == token - @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.ListInstancesRequest, + iam_policy_pb2.SetIamPolicyRequest, dict, ], ) -def test_list_instances_rest(request_type): +def test_set_iam_policy_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1"} + request_init = {"resource": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.ListInstancesResponse( - next_page_token="next_page_token_value", + return_value = policy_pb2.Policy( + version=774, + etag=b"etag_blob", ) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - # Convert return value to protobuf type - return_value = spanner_instance_admin.ListInstancesResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.list_instances(request) + response = client.set_iam_policy(request) # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListInstancesPager) - assert response.next_page_token == "next_page_token_value" + assert isinstance(response, policy_pb2.Policy) + assert response.version == 774 + assert response.etag == b"etag_blob" -def test_list_instances_rest_required_fields( - request_type=spanner_instance_admin.ListInstancesRequest, +def test_set_iam_policy_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.set_iam_policy in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.set_iam_policy] = mock_rpc + + request = {} + client.set_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.set_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_set_iam_policy_rest_required_fields( + request_type=iam_policy_pb2.SetIamPolicyRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["parent"] = "" + request_init["resource"] = "" request = request_type(**request_init) - pb_request = request_type.pb(request) + pb_request = request jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_instances._get_unset_required_fields(jsonified_request) + ).set_iam_policy._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["parent"] = "parent_value" + jsonified_request["resource"] = "resource_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_instances._get_unset_required_fields(jsonified_request) - # Check that path parameters and body parameters are not mixing in. - assert not set(unset_fields) - set( - ( - "filter", - "page_size", - "page_token", - ) - ) + ).set_iam_policy._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "parent" in jsonified_request - assert jsonified_request["parent"] == "parent_value" + assert "resource" in jsonified_request + assert jsonified_request["resource"] == "resource_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -6733,7 +14271,7 @@ def test_list_instances_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.ListInstancesResponse() + return_value = policy_pb2.Policy() # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -6742,51 +14280,49 @@ def test_list_instances_rest_required_fields( with mock.patch.object(path_template, "transcode") as transcode: # A uri without fields and an empty body will force all the # request fields to show up in the query_params. - pb_request = request_type.pb(request) + pb_request = request transcode_result = { "uri": "v1/sample_method", - "method": "get", + "method": "post", "query_params": pb_request, } + transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 - # Convert return value to protobuf type - return_value = spanner_instance_admin.ListInstancesResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.list_instances(request) + response = client.set_iam_policy(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_list_instances_rest_unset_required_fields(): +def test_set_iam_policy_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.list_instances._get_unset_required_fields({}) + unset_fields = transport.set_iam_policy._get_unset_required_fields({}) assert set(unset_fields) == ( - set( + set(()) + & set( ( - "filter", - "pageSize", - "pageToken", + "resource", + "policy", ) ) - & set(("parent",)) ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_list_instances_rest_interceptors(null_interceptor): +def test_set_iam_policy_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -6799,15 +14335,13 @@ def test_list_instances_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_list_instances" + transports.InstanceAdminRestInterceptor, "post_set_iam_policy" ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_list_instances" + transports.InstanceAdminRestInterceptor, "pre_set_iam_policy" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = spanner_instance_admin.ListInstancesRequest.pb( - spanner_instance_admin.ListInstancesRequest() - ) + pb_message = iam_policy_pb2.SetIamPolicyRequest() transcode.return_value = { "method": "post", "uri": "my_uri", @@ -6818,21 +14352,17 @@ def test_list_instances_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = ( - spanner_instance_admin.ListInstancesResponse.to_json( - spanner_instance_admin.ListInstancesResponse() - ) - ) + req.return_value._content = json_format.MessageToJson(policy_pb2.Policy()) - request = spanner_instance_admin.ListInstancesRequest() + request = iam_policy_pb2.SetIamPolicyRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = spanner_instance_admin.ListInstancesResponse() + post.return_value = policy_pb2.Policy() - client.list_instances( + client.set_iam_policy( request, metadata=[ ("key", "val"), @@ -6844,8 +14374,8 @@ def test_list_instances_rest_interceptors(null_interceptor): post.assert_called_once() -def test_list_instances_rest_bad_request( - transport: str = "rest", request_type=spanner_instance_admin.ListInstancesRequest +def test_set_iam_policy_rest_bad_request( + transport: str = "rest", request_type=iam_policy_pb2.SetIamPolicyRequest ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -6853,7 +14383,7 @@ def test_list_instances_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1"} + request_init = {"resource": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -6865,10 +14395,10 @@ def test_list_instances_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.list_instances(request) + client.set_iam_policy(request) -def test_list_instances_rest_flattened(): +def test_set_iam_policy_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -6877,38 +14407,38 @@ def test_list_instances_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.ListInstancesResponse() + return_value = policy_pb2.Policy() # get arguments that satisfy an http rule for this method - sample_request = {"parent": "projects/sample1"} + sample_request = {"resource": "projects/sample1/instances/sample2"} # get truthy value for each flattened field mock_args = dict( - parent="parent_value", + resource="resource_value", ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - # Convert return value to protobuf type - return_value = spanner_instance_admin.ListInstancesResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.list_instances(**mock_args) + client.set_iam_policy(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{parent=projects/*}/instances" % client.transport._host, args[1] + "%s/v1/{resource=projects/*/instances/*}:setIamPolicy" + % client.transport._host, + args[1], ) -def test_list_instances_rest_flattened_error(transport: str = "rest"): +def test_set_iam_policy_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -6917,165 +14447,126 @@ def test_list_instances_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.list_instances( - spanner_instance_admin.ListInstancesRequest(), - parent="parent_value", + client.set_iam_policy( + iam_policy_pb2.SetIamPolicyRequest(), + resource="resource_value", ) -def test_list_instances_rest_pager(transport: str = "rest"): +def test_set_iam_policy_rest_error(): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) - # Mock the http request call within the method and fake a response. - with mock.patch.object(Session, "request") as req: - # TODO(kbandes): remove this mock unless there's a good reason for it. - # with mock.patch.object(path_template, 'transcode') as transcode: - # Set the response as a series of pages - response = ( - spanner_instance_admin.ListInstancesResponse( - instances=[ - spanner_instance_admin.Instance(), - spanner_instance_admin.Instance(), - spanner_instance_admin.Instance(), - ], - next_page_token="abc", - ), - spanner_instance_admin.ListInstancesResponse( - instances=[], - next_page_token="def", - ), - spanner_instance_admin.ListInstancesResponse( - instances=[ - spanner_instance_admin.Instance(), - ], - next_page_token="ghi", - ), - spanner_instance_admin.ListInstancesResponse( - instances=[ - spanner_instance_admin.Instance(), - spanner_instance_admin.Instance(), - ], - ), - ) - # Two responses for two calls - response = response + response - - # Wrap the values into proper Response objs - response = tuple( - spanner_instance_admin.ListInstancesResponse.to_json(x) for x in response - ) - return_values = tuple(Response() for i in response) - for return_val, response_val in zip(return_values, response): - return_val._content = response_val.encode("UTF-8") - return_val.status_code = 200 - req.side_effect = return_values - - sample_request = {"parent": "projects/sample1"} - - pager = client.list_instances(request=sample_request) - - results = list(pager) - assert len(results) == 6 - assert all(isinstance(i, spanner_instance_admin.Instance) for i in results) - - pages = list(client.list_instances(request=sample_request).pages) - for page_, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page_.raw_page.next_page_token == token - @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.GetInstanceRequest, + iam_policy_pb2.GetIamPolicyRequest, dict, ], ) -def test_get_instance_rest(request_type): +def test_get_iam_policy_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"name": "projects/sample1/instances/sample2"} + request_init = {"resource": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.Instance( - name="name_value", - config="config_value", - display_name="display_name_value", - node_count=1070, - processing_units=1743, - state=spanner_instance_admin.Instance.State.CREATING, - endpoint_uris=["endpoint_uris_value"], + return_value = policy_pb2.Policy( + version=774, + etag=b"etag_blob", ) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - # Convert return value to protobuf type - return_value = spanner_instance_admin.Instance.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.get_instance(request) + response = client.get_iam_policy(request) # Establish that the response is the type that we expect. - assert isinstance(response, spanner_instance_admin.Instance) - assert response.name == "name_value" - assert response.config == "config_value" - assert response.display_name == "display_name_value" - assert response.node_count == 1070 - assert response.processing_units == 1743 - assert response.state == spanner_instance_admin.Instance.State.CREATING - assert response.endpoint_uris == ["endpoint_uris_value"] + assert isinstance(response, policy_pb2.Policy) + assert response.version == 774 + assert response.etag == b"etag_blob" -def test_get_instance_rest_required_fields( - request_type=spanner_instance_admin.GetInstanceRequest, +def test_get_iam_policy_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_iam_policy in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_iam_policy] = mock_rpc + + request = {} + client.get_iam_policy(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_iam_policy(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_get_iam_policy_rest_required_fields( + request_type=iam_policy_pb2.GetIamPolicyRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["name"] = "" + request_init["resource"] = "" request = request_type(**request_init) - pb_request = request_type.pb(request) + pb_request = request jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_instance._get_unset_required_fields(jsonified_request) + ).get_iam_policy._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["name"] = "name_value" + jsonified_request["resource"] = "resource_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_instance._get_unset_required_fields(jsonified_request) - # Check that path parameters and body parameters are not mixing in. - assert not set(unset_fields) - set(("field_mask",)) + ).get_iam_policy._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "name" in jsonified_request - assert jsonified_request["name"] == "name_value" + assert "resource" in jsonified_request + assert jsonified_request["resource"] == "resource_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -7084,7 +14575,7 @@ def test_get_instance_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.Instance() + return_value = policy_pb2.Policy() # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -7093,42 +14584,41 @@ def test_get_instance_rest_required_fields( with mock.patch.object(path_template, "transcode") as transcode: # A uri without fields and an empty body will force all the # request fields to show up in the query_params. - pb_request = request_type.pb(request) + pb_request = request transcode_result = { "uri": "v1/sample_method", - "method": "get", + "method": "post", "query_params": pb_request, } + transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 - # Convert return value to protobuf type - return_value = spanner_instance_admin.Instance.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.get_instance(request) + response = client.get_iam_policy(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_get_instance_rest_unset_required_fields(): +def test_get_iam_policy_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.get_instance._get_unset_required_fields({}) - assert set(unset_fields) == (set(("fieldMask",)) & set(("name",))) + unset_fields = transport.get_iam_policy._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("resource",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_get_instance_rest_interceptors(null_interceptor): +def test_get_iam_policy_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -7141,15 +14631,13 @@ def test_get_instance_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_get_instance" + transports.InstanceAdminRestInterceptor, "post_get_iam_policy" ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_get_instance" + transports.InstanceAdminRestInterceptor, "pre_get_iam_policy" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = spanner_instance_admin.GetInstanceRequest.pb( - spanner_instance_admin.GetInstanceRequest() - ) + pb_message = iam_policy_pb2.GetIamPolicyRequest() transcode.return_value = { "method": "post", "uri": "my_uri", @@ -7160,19 +14648,17 @@ def test_get_instance_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = spanner_instance_admin.Instance.to_json( - spanner_instance_admin.Instance() - ) + req.return_value._content = json_format.MessageToJson(policy_pb2.Policy()) - request = spanner_instance_admin.GetInstanceRequest() + request = iam_policy_pb2.GetIamPolicyRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = spanner_instance_admin.Instance() + post.return_value = policy_pb2.Policy() - client.get_instance( + client.get_iam_policy( request, metadata=[ ("key", "val"), @@ -7184,8 +14670,8 @@ def test_get_instance_rest_interceptors(null_interceptor): post.assert_called_once() -def test_get_instance_rest_bad_request( - transport: str = "rest", request_type=spanner_instance_admin.GetInstanceRequest +def test_get_iam_policy_rest_bad_request( + transport: str = "rest", request_type=iam_policy_pb2.GetIamPolicyRequest ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -7193,7 +14679,7 @@ def test_get_instance_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"name": "projects/sample1/instances/sample2"} + request_init = {"resource": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -7205,10 +14691,10 @@ def test_get_instance_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.get_instance(request) + client.get_iam_policy(request) -def test_get_instance_rest_flattened(): +def test_get_iam_policy_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -7217,38 +14703,38 @@ def test_get_instance_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = spanner_instance_admin.Instance() + return_value = policy_pb2.Policy() # get arguments that satisfy an http rule for this method - sample_request = {"name": "projects/sample1/instances/sample2"} + sample_request = {"resource": "projects/sample1/instances/sample2"} # get truthy value for each flattened field mock_args = dict( - name="name_value", + resource="resource_value", ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - # Convert return value to protobuf type - return_value = spanner_instance_admin.Instance.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.get_instance(**mock_args) + client.get_iam_policy(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{name=projects/*/instances/*}" % client.transport._host, args[1] + "%s/v1/{resource=projects/*/instances/*}:getIamPolicy" + % client.transport._host, + args[1], ) -def test_get_instance_rest_flattened_error(transport: str = "rest"): +def test_get_iam_policy_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -7257,13 +14743,13 @@ def test_get_instance_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.get_instance( - spanner_instance_admin.GetInstanceRequest(), - name="name_value", + client.get_iam_policy( + iam_policy_pb2.GetIamPolicyRequest(), + resource="resource_value", ) -def test_get_instance_rest_error(): +def test_get_iam_policy_rest_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -7272,24 +14758,26 @@ def test_get_instance_rest_error(): @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.CreateInstanceRequest, + iam_policy_pb2.TestIamPermissionsRequest, dict, ], ) -def test_create_instance_rest(request_type): +def test_test_iam_permissions_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1"} + request_init = {"resource": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = iam_policy_pb2.TestIamPermissionsResponse( + permissions=["permissions_value"], + ) # Wrap the value into a proper Response obj response_value = Response() @@ -7298,52 +14786,89 @@ def test_create_instance_rest(request_type): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.create_instance(request) + response = client.test_iam_permissions(request) # Establish that the response is the type that we expect. - assert response.operation.name == "operations/spam" + assert isinstance(response, iam_policy_pb2.TestIamPermissionsResponse) + assert response.permissions == ["permissions_value"] -def test_create_instance_rest_required_fields( - request_type=spanner_instance_admin.CreateInstanceRequest, +def test_test_iam_permissions_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.test_iam_permissions in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.test_iam_permissions + ] = mock_rpc + + request = {} + client.test_iam_permissions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.test_iam_permissions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_test_iam_permissions_rest_required_fields( + request_type=iam_policy_pb2.TestIamPermissionsRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["parent"] = "" - request_init["instance_id"] = "" + request_init["resource"] = "" + request_init["permissions"] = "" request = request_type(**request_init) - pb_request = request_type.pb(request) + pb_request = request jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_instance._get_unset_required_fields(jsonified_request) + ).test_iam_permissions._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["parent"] = "parent_value" - jsonified_request["instanceId"] = "instance_id_value" + jsonified_request["resource"] = "resource_value" + jsonified_request["permissions"] = "permissions_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_instance._get_unset_required_fields(jsonified_request) + ).test_iam_permissions._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "parent" in jsonified_request - assert jsonified_request["parent"] == "parent_value" - assert "instanceId" in jsonified_request - assert jsonified_request["instanceId"] == "instance_id_value" + assert "resource" in jsonified_request + assert jsonified_request["resource"] == "resource_value" + assert "permissions" in jsonified_request + assert jsonified_request["permissions"] == "permissions_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -7352,7 +14877,7 @@ def test_create_instance_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = iam_policy_pb2.TestIamPermissionsResponse() # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -7361,7 +14886,7 @@ def test_create_instance_rest_required_fields( with mock.patch.object(path_template, "transcode") as transcode: # A uri without fields and an empty body will force all the # request fields to show up in the query_params. - pb_request = request_type.pb(request) + pb_request = request transcode_result = { "uri": "v1/sample_method", "method": "post", @@ -7372,38 +14897,38 @@ def test_create_instance_rest_required_fields( response_value = Response() response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.create_instance(request) + response = client.test_iam_permissions(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_create_instance_rest_unset_required_fields(): +def test_test_iam_permissions_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.create_instance._get_unset_required_fields({}) + unset_fields = transport.test_iam_permissions._get_unset_required_fields({}) assert set(unset_fields) == ( set(()) & set( ( - "parent", - "instanceId", - "instance", + "resource", + "permissions", ) ) ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_create_instance_rest_interceptors(null_interceptor): +def test_test_iam_permissions_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -7416,17 +14941,13 @@ def test_create_instance_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - operation.Operation, "_set_result_from_operation" - ), mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_create_instance" + transports.InstanceAdminRestInterceptor, "post_test_iam_permissions" ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_create_instance" + transports.InstanceAdminRestInterceptor, "pre_test_iam_permissions" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = spanner_instance_admin.CreateInstanceRequest.pb( - spanner_instance_admin.CreateInstanceRequest() - ) + pb_message = iam_policy_pb2.TestIamPermissionsRequest() transcode.return_value = { "method": "post", "uri": "my_uri", @@ -7438,18 +14959,18 @@ def test_create_instance_rest_interceptors(null_interceptor): req.return_value.status_code = 200 req.return_value.request = PreparedRequest() req.return_value._content = json_format.MessageToJson( - operations_pb2.Operation() + iam_policy_pb2.TestIamPermissionsResponse() ) - request = spanner_instance_admin.CreateInstanceRequest() + request = iam_policy_pb2.TestIamPermissionsRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = operations_pb2.Operation() + post.return_value = iam_policy_pb2.TestIamPermissionsResponse() - client.create_instance( + client.test_iam_permissions( request, metadata=[ ("key", "val"), @@ -7461,8 +14982,8 @@ def test_create_instance_rest_interceptors(null_interceptor): post.assert_called_once() -def test_create_instance_rest_bad_request( - transport: str = "rest", request_type=spanner_instance_admin.CreateInstanceRequest +def test_test_iam_permissions_rest_bad_request( + transport: str = "rest", request_type=iam_policy_pb2.TestIamPermissionsRequest ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -7470,7 +14991,7 @@ def test_create_instance_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1"} + request_init = {"resource": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -7482,10 +15003,10 @@ def test_create_instance_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.create_instance(request) + client.test_iam_permissions(request) -def test_create_instance_rest_flattened(): +def test_test_iam_permissions_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -7494,16 +15015,15 @@ def test_create_instance_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = iam_policy_pb2.TestIamPermissionsResponse() # get arguments that satisfy an http rule for this method - sample_request = {"parent": "projects/sample1"} + sample_request = {"resource": "projects/sample1/instances/sample2"} # get truthy value for each flattened field mock_args = dict( - parent="parent_value", - instance_id="instance_id_value", - instance=spanner_instance_admin.Instance(name="name_value"), + resource="resource_value", + permissions=["permissions_value"], ) mock_args.update(sample_request) @@ -7514,18 +15034,20 @@ def test_create_instance_rest_flattened(): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.create_instance(**mock_args) + client.test_iam_permissions(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{parent=projects/*}/instances" % client.transport._host, args[1] + "%s/v1/{resource=projects/*/instances/*}:testIamPermissions" + % client.transport._host, + args[1], ) -def test_create_instance_rest_flattened_error(transport: str = "rest"): +def test_test_iam_permissions_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -7534,15 +15056,14 @@ def test_create_instance_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.create_instance( - spanner_instance_admin.CreateInstanceRequest(), - parent="parent_value", - instance_id="instance_id_value", - instance=spanner_instance_admin.Instance(name="name_value"), + client.test_iam_permissions( + iam_policy_pb2.TestIamPermissionsRequest(), + resource="resource_value", + permissions=["permissions_value"], ) -def test_create_instance_rest_error(): +def test_test_iam_permissions_rest_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -7551,69 +15072,131 @@ def test_create_instance_rest_error(): @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.UpdateInstanceRequest, + spanner_instance_admin.GetInstancePartitionRequest, dict, ], ) -def test_update_instance_rest(request_type): +def test_get_instance_partition_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"instance": {"name": "projects/sample1/instances/sample2"}} + request_init = { + "name": "projects/sample1/instances/sample2/instancePartitions/sample3" + } request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = spanner_instance_admin.InstancePartition( + name="name_value", + config="config_value", + display_name="display_name_value", + state=spanner_instance_admin.InstancePartition.State.CREATING, + referencing_databases=["referencing_databases_value"], + referencing_backups=["referencing_backups_value"], + etag="etag_value", + node_count=1070, + ) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.InstancePartition.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.update_instance(request) + response = client.get_instance_partition(request) # Establish that the response is the type that we expect. - assert response.operation.name == "operations/spam" + assert isinstance(response, spanner_instance_admin.InstancePartition) + assert response.name == "name_value" + assert response.config == "config_value" + assert response.display_name == "display_name_value" + assert response.state == spanner_instance_admin.InstancePartition.State.CREATING + assert response.referencing_databases == ["referencing_databases_value"] + assert response.referencing_backups == ["referencing_backups_value"] + assert response.etag == "etag_value" -def test_update_instance_rest_required_fields( - request_type=spanner_instance_admin.UpdateInstanceRequest, +def test_get_instance_partition_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_instance_partition + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_instance_partition + ] = mock_rpc + + request = {} + client.get_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_get_instance_partition_rest_required_fields( + request_type=spanner_instance_admin.GetInstancePartitionRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} + request_init["name"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).update_instance._get_unset_required_fields(jsonified_request) + ).get_instance_partition._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present + jsonified_request["name"] = "name_value" + unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).update_instance._get_unset_required_fields(jsonified_request) + ).get_instance_partition._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -7622,7 +15205,7 @@ def test_update_instance_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = spanner_instance_admin.InstancePartition() # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -7634,45 +15217,39 @@ def test_update_instance_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "patch", + "method": "get", "query_params": pb_request, } - transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = spanner_instance_admin.InstancePartition.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.update_instance(request) + response = client.get_instance_partition(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_update_instance_rest_unset_required_fields(): +def test_get_instance_partition_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.update_instance._get_unset_required_fields({}) - assert set(unset_fields) == ( - set(()) - & set( - ( - "instance", - "fieldMask", - ) - ) - ) + unset_fields = transport.get_instance_partition._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_update_instance_rest_interceptors(null_interceptor): +def test_get_instance_partition_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -7685,16 +15262,14 @@ def test_update_instance_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - operation.Operation, "_set_result_from_operation" - ), mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_update_instance" + transports.InstanceAdminRestInterceptor, "post_get_instance_partition" ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_update_instance" + transports.InstanceAdminRestInterceptor, "pre_get_instance_partition" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = spanner_instance_admin.UpdateInstanceRequest.pb( - spanner_instance_admin.UpdateInstanceRequest() + pb_message = spanner_instance_admin.GetInstancePartitionRequest.pb( + spanner_instance_admin.GetInstancePartitionRequest() ) transcode.return_value = { "method": "post", @@ -7706,19 +15281,19 @@ def test_update_instance_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = json_format.MessageToJson( - operations_pb2.Operation() + req.return_value._content = spanner_instance_admin.InstancePartition.to_json( + spanner_instance_admin.InstancePartition() ) - request = spanner_instance_admin.UpdateInstanceRequest() + request = spanner_instance_admin.GetInstancePartitionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = operations_pb2.Operation() + post.return_value = spanner_instance_admin.InstancePartition() - client.update_instance( + client.get_instance_partition( request, metadata=[ ("key", "val"), @@ -7730,8 +15305,9 @@ def test_update_instance_rest_interceptors(null_interceptor): post.assert_called_once() -def test_update_instance_rest_bad_request( - transport: str = "rest", request_type=spanner_instance_admin.UpdateInstanceRequest +def test_get_instance_partition_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.GetInstancePartitionRequest, ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -7739,7 +15315,9 @@ def test_update_instance_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"instance": {"name": "projects/sample1/instances/sample2"}} + request_init = { + "name": "projects/sample1/instances/sample2/instancePartitions/sample3" + } request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -7751,10 +15329,10 @@ def test_update_instance_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.update_instance(request) + client.get_instance_partition(request) -def test_update_instance_rest_flattened(): +def test_get_instance_partition_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -7763,54 +15341,57 @@ def test_update_instance_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = spanner_instance_admin.InstancePartition() # get arguments that satisfy an http rule for this method - sample_request = {"instance": {"name": "projects/sample1/instances/sample2"}} + sample_request = { + "name": "projects/sample1/instances/sample2/instancePartitions/sample3" + } # get truthy value for each flattened field mock_args = dict( - instance=spanner_instance_admin.Instance(name="name_value"), - field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + name="name_value", ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner_instance_admin.InstancePartition.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.update_instance(**mock_args) + client.get_instance_partition(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{instance.name=projects/*/instances/*}" % client.transport._host, + "%s/v1/{name=projects/*/instances/*/instancePartitions/*}" + % client.transport._host, args[1], ) -def test_update_instance_rest_flattened_error(transport: str = "rest"): +def test_get_instance_partition_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, ) # Attempting to call a method with both a request object and flattened - # fields is an error. - with pytest.raises(ValueError): - client.update_instance( - spanner_instance_admin.UpdateInstanceRequest(), - instance=spanner_instance_admin.Instance(name="name_value"), - field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + # fields is an error. + with pytest.raises(ValueError): + client.get_instance_partition( + spanner_instance_admin.GetInstancePartitionRequest(), + name="name_value", ) -def test_update_instance_rest_error(): +def test_get_instance_partition_rest_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -7819,74 +15400,119 @@ def test_update_instance_rest_error(): @pytest.mark.parametrize( "request_type", [ - spanner_instance_admin.DeleteInstanceRequest, + spanner_instance_admin.CreateInstancePartitionRequest, dict, ], ) -def test_delete_instance_rest(request_type): +def test_create_instance_partition_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"name": "projects/sample1/instances/sample2"} + request_init = {"parent": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = None + return_value = operations_pb2.Operation(name="operations/spam") # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - json_return_value = "" + json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.delete_instance(request) + response = client.create_instance_partition(request) # Establish that the response is the type that we expect. - assert response is None + assert response.operation.name == "operations/spam" -def test_delete_instance_rest_required_fields( - request_type=spanner_instance_admin.DeleteInstanceRequest, +def test_create_instance_partition_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.create_instance_partition + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.create_instance_partition + ] = mock_rpc + + request = {} + client.create_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.create_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_create_instance_partition_rest_required_fields( + request_type=spanner_instance_admin.CreateInstancePartitionRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["name"] = "" + request_init["parent"] = "" + request_init["instance_partition_id"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_instance._get_unset_required_fields(jsonified_request) + ).create_instance_partition._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["name"] = "name_value" + jsonified_request["parent"] = "parent_value" + jsonified_request["instancePartitionId"] = "instance_partition_id_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_instance._get_unset_required_fields(jsonified_request) + ).create_instance_partition._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "name" in jsonified_request - assert jsonified_request["name"] == "name_value" + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + assert "instancePartitionId" in jsonified_request + assert jsonified_request["instancePartitionId"] == "instance_partition_id_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -7895,7 +15521,7 @@ def test_delete_instance_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = None + return_value = operations_pb2.Operation(name="operations/spam") # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -7907,36 +15533,46 @@ def test_delete_instance_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "delete", + "method": "post", "query_params": pb_request, } + transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 - json_return_value = "" + json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.delete_instance(request) + response = client.create_instance_partition(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_delete_instance_rest_unset_required_fields(): +def test_create_instance_partition_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.delete_instance._get_unset_required_fields({}) - assert set(unset_fields) == (set(()) & set(("name",))) + unset_fields = transport.create_instance_partition._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "parent", + "instancePartitionId", + "instancePartition", + ) + ) + ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_delete_instance_rest_interceptors(null_interceptor): +def test_create_instance_partition_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -7949,11 +15585,16 @@ def test_delete_instance_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_delete_instance" + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.InstanceAdminRestInterceptor, "post_create_instance_partition" + ) as post, mock.patch.object( + transports.InstanceAdminRestInterceptor, "pre_create_instance_partition" ) as pre: pre.assert_not_called() - pb_message = spanner_instance_admin.DeleteInstanceRequest.pb( - spanner_instance_admin.DeleteInstanceRequest() + post.assert_not_called() + pb_message = spanner_instance_admin.CreateInstancePartitionRequest.pb( + spanner_instance_admin.CreateInstancePartitionRequest() ) transcode.return_value = { "method": "post", @@ -7965,15 +15606,19 @@ def test_delete_instance_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() + ) - request = spanner_instance_admin.DeleteInstanceRequest() + request = spanner_instance_admin.CreateInstancePartitionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() - client.delete_instance( + client.create_instance_partition( request, metadata=[ ("key", "val"), @@ -7982,10 +15627,12 @@ def test_delete_instance_rest_interceptors(null_interceptor): ) pre.assert_called_once() + post.assert_called_once() -def test_delete_instance_rest_bad_request( - transport: str = "rest", request_type=spanner_instance_admin.DeleteInstanceRequest +def test_create_instance_partition_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.CreateInstancePartitionRequest, ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -7993,7 +15640,7 @@ def test_delete_instance_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"name": "projects/sample1/instances/sample2"} + request_init = {"parent": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -8005,10 +15652,10 @@ def test_delete_instance_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.delete_instance(request) + client.create_instance_partition(request) -def test_delete_instance_rest_flattened(): +def test_create_instance_partition_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -8017,36 +15664,42 @@ def test_delete_instance_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = None + return_value = operations_pb2.Operation(name="operations/spam") # get arguments that satisfy an http rule for this method - sample_request = {"name": "projects/sample1/instances/sample2"} + sample_request = {"parent": "projects/sample1/instances/sample2"} # get truthy value for each flattened field mock_args = dict( - name="name_value", + parent="parent_value", + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + instance_partition_id="instance_partition_id_value", ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - json_return_value = "" + json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.delete_instance(**mock_args) + client.create_instance_partition(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{name=projects/*/instances/*}" % client.transport._host, args[1] + "%s/v1/{parent=projects/*/instances/*}/instancePartitions" + % client.transport._host, + args[1], ) -def test_delete_instance_rest_flattened_error(transport: str = "rest"): +def test_create_instance_partition_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -8055,13 +15708,17 @@ def test_delete_instance_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.delete_instance( - spanner_instance_admin.DeleteInstanceRequest(), - name="name_value", + client.create_instance_partition( + spanner_instance_admin.CreateInstancePartitionRequest(), + parent="parent_value", + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + instance_partition_id="instance_partition_id_value", ) -def test_delete_instance_rest_error(): +def test_create_instance_partition_rest_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -8070,79 +15727,115 @@ def test_delete_instance_rest_error(): @pytest.mark.parametrize( "request_type", [ - iam_policy_pb2.SetIamPolicyRequest, + spanner_instance_admin.DeleteInstancePartitionRequest, dict, ], ) -def test_set_iam_policy_rest(request_type): +def test_delete_instance_partition_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"resource": "projects/sample1/instances/sample2"} + request_init = { + "name": "projects/sample1/instances/sample2/instancePartitions/sample3" + } request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = policy_pb2.Policy( - version=774, - etag=b"etag_blob", - ) + return_value = None # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - json_return_value = json_format.MessageToJson(return_value) + json_return_value = "" response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.set_iam_policy(request) + response = client.delete_instance_partition(request) # Establish that the response is the type that we expect. - assert isinstance(response, policy_pb2.Policy) - assert response.version == 774 - assert response.etag == b"etag_blob" + assert response is None -def test_set_iam_policy_rest_required_fields( - request_type=iam_policy_pb2.SetIamPolicyRequest, +def test_delete_instance_partition_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.delete_instance_partition + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.delete_instance_partition + ] = mock_rpc + + request = {} + client.delete_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.delete_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_delete_instance_partition_rest_required_fields( + request_type=spanner_instance_admin.DeleteInstancePartitionRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["resource"] = "" + request_init["name"] = "" request = request_type(**request_init) - pb_request = request + pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).set_iam_policy._get_unset_required_fields(jsonified_request) + ).delete_instance_partition._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["resource"] = "resource_value" + jsonified_request["name"] = "name_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).set_iam_policy._get_unset_required_fields(jsonified_request) + ).delete_instance_partition._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("etag",)) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "resource" in jsonified_request - assert jsonified_request["resource"] == "resource_value" + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -8151,7 +15844,7 @@ def test_set_iam_policy_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = policy_pb2.Policy() + return_value = None # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -8160,49 +15853,39 @@ def test_set_iam_policy_rest_required_fields( with mock.patch.object(path_template, "transcode") as transcode: # A uri without fields and an empty body will force all the # request fields to show up in the query_params. - pb_request = request + pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "post", + "method": "delete", "query_params": pb_request, } - transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 - - json_return_value = json_format.MessageToJson(return_value) + json_return_value = "" response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.set_iam_policy(request) + response = client.delete_instance_partition(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_set_iam_policy_rest_unset_required_fields(): +def test_delete_instance_partition_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.set_iam_policy._get_unset_required_fields({}) - assert set(unset_fields) == ( - set(()) - & set( - ( - "resource", - "policy", - ) - ) - ) + unset_fields = transport.delete_instance_partition._get_unset_required_fields({}) + assert set(unset_fields) == (set(("etag",)) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_set_iam_policy_rest_interceptors(null_interceptor): +def test_delete_instance_partition_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -8215,13 +15898,12 @@ def test_set_iam_policy_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_set_iam_policy" - ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_set_iam_policy" + transports.InstanceAdminRestInterceptor, "pre_delete_instance_partition" ) as pre: pre.assert_not_called() - post.assert_not_called() - pb_message = iam_policy_pb2.SetIamPolicyRequest() + pb_message = spanner_instance_admin.DeleteInstancePartitionRequest.pb( + spanner_instance_admin.DeleteInstancePartitionRequest() + ) transcode.return_value = { "method": "post", "uri": "my_uri", @@ -8232,17 +15914,15 @@ def test_set_iam_policy_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = json_format.MessageToJson(policy_pb2.Policy()) - request = iam_policy_pb2.SetIamPolicyRequest() + request = spanner_instance_admin.DeleteInstancePartitionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = policy_pb2.Policy() - client.set_iam_policy( + client.delete_instance_partition( request, metadata=[ ("key", "val"), @@ -8251,11 +15931,11 @@ def test_set_iam_policy_rest_interceptors(null_interceptor): ) pre.assert_called_once() - post.assert_called_once() -def test_set_iam_policy_rest_bad_request( - transport: str = "rest", request_type=iam_policy_pb2.SetIamPolicyRequest +def test_delete_instance_partition_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.DeleteInstancePartitionRequest, ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -8263,7 +15943,9 @@ def test_set_iam_policy_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"resource": "projects/sample1/instances/sample2"} + request_init = { + "name": "projects/sample1/instances/sample2/instancePartitions/sample3" + } request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -8275,10 +15957,10 @@ def test_set_iam_policy_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.set_iam_policy(request) + client.delete_instance_partition(request) -def test_set_iam_policy_rest_flattened(): +def test_delete_instance_partition_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -8287,38 +15969,40 @@ def test_set_iam_policy_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = policy_pb2.Policy() + return_value = None # get arguments that satisfy an http rule for this method - sample_request = {"resource": "projects/sample1/instances/sample2"} + sample_request = { + "name": "projects/sample1/instances/sample2/instancePartitions/sample3" + } # get truthy value for each flattened field mock_args = dict( - resource="resource_value", + name="name_value", ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - json_return_value = json_format.MessageToJson(return_value) + json_return_value = "" response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.set_iam_policy(**mock_args) + client.delete_instance_partition(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{resource=projects/*/instances/*}:setIamPolicy" + "%s/v1/{name=projects/*/instances/*/instancePartitions/*}" % client.transport._host, args[1], ) -def test_set_iam_policy_rest_flattened_error(transport: str = "rest"): +def test_delete_instance_partition_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -8327,13 +16011,13 @@ def test_set_iam_policy_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.set_iam_policy( - iam_policy_pb2.SetIamPolicyRequest(), - resource="resource_value", + client.delete_instance_partition( + spanner_instance_admin.DeleteInstancePartitionRequest(), + name="name_value", ) -def test_set_iam_policy_rest_error(): +def test_delete_instance_partition_rest_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -8342,27 +16026,28 @@ def test_set_iam_policy_rest_error(): @pytest.mark.parametrize( "request_type", [ - iam_policy_pb2.GetIamPolicyRequest, + spanner_instance_admin.UpdateInstancePartitionRequest, dict, ], ) -def test_get_iam_policy_rest(request_type): +def test_update_instance_partition_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"resource": "projects/sample1/instances/sample2"} + request_init = { + "instance_partition": { + "name": "projects/sample1/instances/sample2/instancePartitions/sample3" + } + } request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = policy_pb2.Policy( - version=774, - etag=b"etag_blob", - ) + return_value = operations_pb2.Operation(name="operations/spam") # Wrap the value into a proper Response obj response_value = Response() @@ -8371,50 +16056,84 @@ def test_get_iam_policy_rest(request_type): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.get_iam_policy(request) + response = client.update_instance_partition(request) # Establish that the response is the type that we expect. - assert isinstance(response, policy_pb2.Policy) - assert response.version == 774 - assert response.etag == b"etag_blob" + assert response.operation.name == "operations/spam" -def test_get_iam_policy_rest_required_fields( - request_type=iam_policy_pb2.GetIamPolicyRequest, +def test_update_instance_partition_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_instance_partition + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_instance_partition + ] = mock_rpc + + request = {} + client.update_instance_partition(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.update_instance_partition(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_instance_partition_rest_required_fields( + request_type=spanner_instance_admin.UpdateInstancePartitionRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["resource"] = "" request = request_type(**request_init) - pb_request = request + pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_iam_policy._get_unset_required_fields(jsonified_request) + ).update_instance_partition._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["resource"] = "resource_value" - unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_iam_policy._get_unset_required_fields(jsonified_request) + ).update_instance_partition._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "resource" in jsonified_request - assert jsonified_request["resource"] == "resource_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -8423,7 +16142,7 @@ def test_get_iam_policy_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = policy_pb2.Policy() + return_value = operations_pb2.Operation(name="operations/spam") # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -8432,10 +16151,10 @@ def test_get_iam_policy_rest_required_fields( with mock.patch.object(path_template, "transcode") as transcode: # A uri without fields and an empty body will force all the # request fields to show up in the query_params. - pb_request = request + pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "post", + "method": "patch", "query_params": pb_request, } transcode_result["body"] = pb_request @@ -8443,30 +16162,37 @@ def test_get_iam_policy_rest_required_fields( response_value = Response() response_value.status_code = 200 - json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.get_iam_policy(request) + response = client.update_instance_partition(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_get_iam_policy_rest_unset_required_fields(): +def test_update_instance_partition_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.get_iam_policy._get_unset_required_fields({}) - assert set(unset_fields) == (set(()) & set(("resource",))) + unset_fields = transport.update_instance_partition._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "instancePartition", + "fieldMask", + ) + ) + ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_get_iam_policy_rest_interceptors(null_interceptor): +def test_update_instance_partition_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -8479,13 +16205,17 @@ def test_get_iam_policy_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_get_iam_policy" + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.InstanceAdminRestInterceptor, "post_update_instance_partition" ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_get_iam_policy" + transports.InstanceAdminRestInterceptor, "pre_update_instance_partition" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = iam_policy_pb2.GetIamPolicyRequest() + pb_message = spanner_instance_admin.UpdateInstancePartitionRequest.pb( + spanner_instance_admin.UpdateInstancePartitionRequest() + ) transcode.return_value = { "method": "post", "uri": "my_uri", @@ -8496,17 +16226,19 @@ def test_get_iam_policy_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = json_format.MessageToJson(policy_pb2.Policy()) + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() + ) - request = iam_policy_pb2.GetIamPolicyRequest() + request = spanner_instance_admin.UpdateInstancePartitionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = policy_pb2.Policy() + post.return_value = operations_pb2.Operation() - client.get_iam_policy( + client.update_instance_partition( request, metadata=[ ("key", "val"), @@ -8518,8 +16250,9 @@ def test_get_iam_policy_rest_interceptors(null_interceptor): post.assert_called_once() -def test_get_iam_policy_rest_bad_request( - transport: str = "rest", request_type=iam_policy_pb2.GetIamPolicyRequest +def test_update_instance_partition_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.UpdateInstancePartitionRequest, ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -8527,7 +16260,11 @@ def test_get_iam_policy_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"resource": "projects/sample1/instances/sample2"} + request_init = { + "instance_partition": { + "name": "projects/sample1/instances/sample2/instancePartitions/sample3" + } + } request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -8539,10 +16276,10 @@ def test_get_iam_policy_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.get_iam_policy(request) + client.update_instance_partition(request) -def test_get_iam_policy_rest_flattened(): +def test_update_instance_partition_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -8551,14 +16288,21 @@ def test_get_iam_policy_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = policy_pb2.Policy() + return_value = operations_pb2.Operation(name="operations/spam") # get arguments that satisfy an http rule for this method - sample_request = {"resource": "projects/sample1/instances/sample2"} + sample_request = { + "instance_partition": { + "name": "projects/sample1/instances/sample2/instancePartitions/sample3" + } + } # get truthy value for each flattened field mock_args = dict( - resource="resource_value", + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) mock_args.update(sample_request) @@ -8569,20 +16313,20 @@ def test_get_iam_policy_rest_flattened(): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.get_iam_policy(**mock_args) + client.update_instance_partition(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{resource=projects/*/instances/*}:getIamPolicy" + "%s/v1/{instance_partition.name=projects/*/instances/*/instancePartitions/*}" % client.transport._host, args[1], ) -def test_get_iam_policy_rest_flattened_error(transport: str = "rest"): +def test_update_instance_partition_rest_flattened_error(transport: str = "rest"): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -8591,13 +16335,16 @@ def test_get_iam_policy_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.get_iam_policy( - iam_policy_pb2.GetIamPolicyRequest(), - resource="resource_value", + client.update_instance_partition( + spanner_instance_admin.UpdateInstancePartitionRequest(), + instance_partition=spanner_instance_admin.InstancePartition( + name="name_value" + ), + field_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) -def test_get_iam_policy_rest_error(): +def test_update_instance_partition_rest_error(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -8606,81 +16353,133 @@ def test_get_iam_policy_rest_error(): @pytest.mark.parametrize( "request_type", [ - iam_policy_pb2.TestIamPermissionsRequest, + spanner_instance_admin.ListInstancePartitionOperationsRequest, dict, ], ) -def test_test_iam_permissions_rest(request_type): +def test_list_instance_partition_operations_rest(request_type): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"resource": "projects/sample1/instances/sample2"} + request_init = {"parent": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = iam_policy_pb2.TestIamPermissionsResponse( - permissions=["permissions_value"], + return_value = spanner_instance_admin.ListInstancePartitionOperationsResponse( + next_page_token="next_page_token_value", + unreachable_instance_partitions=["unreachable_instance_partitions_value"], ) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse.pb( + return_value + ) + ) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.test_iam_permissions(request) + response = client.list_instance_partition_operations(request) # Establish that the response is the type that we expect. - assert isinstance(response, iam_policy_pb2.TestIamPermissionsResponse) - assert response.permissions == ["permissions_value"] + assert isinstance(response, pagers.ListInstancePartitionOperationsPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable_instance_partitions == [ + "unreachable_instance_partitions_value" + ] -def test_test_iam_permissions_rest_required_fields( - request_type=iam_policy_pb2.TestIamPermissionsRequest, +def test_list_instance_partition_operations_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = InstanceAdminClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_instance_partition_operations + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_instance_partition_operations + ] = mock_rpc + + request = {} + client.list_instance_partition_operations(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_instance_partition_operations(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_instance_partition_operations_rest_required_fields( + request_type=spanner_instance_admin.ListInstancePartitionOperationsRequest, ): transport_class = transports.InstanceAdminRestTransport request_init = {} - request_init["resource"] = "" - request_init["permissions"] = "" + request_init["parent"] = "" request = request_type(**request_init) - pb_request = request + pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).test_iam_permissions._get_unset_required_fields(jsonified_request) + ).list_instance_partition_operations._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - jsonified_request["resource"] = "resource_value" - jsonified_request["permissions"] = "permissions_value" + jsonified_request["parent"] = "parent_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).test_iam_permissions._get_unset_required_fields(jsonified_request) + ).list_instance_partition_operations._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "filter", + "instance_partition_deadline", + "page_size", + "page_token", + ) + ) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone - assert "resource" in jsonified_request - assert jsonified_request["resource"] == "resource_value" - assert "permissions" in jsonified_request - assert jsonified_request["permissions"] == "permissions_value" + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -8689,7 +16488,7 @@ def test_test_iam_permissions_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = iam_policy_pb2.TestIamPermissionsResponse() + return_value = spanner_instance_admin.ListInstancePartitionOperationsResponse() # Mock the http request call within the method and fake a response. with mock.patch.object(Session, "request") as req: # We need to mock transcode() because providing default values @@ -8698,49 +16497,58 @@ def test_test_iam_permissions_rest_required_fields( with mock.patch.object(path_template, "transcode") as transcode: # A uri without fields and an empty body will force all the # request fields to show up in the query_params. - pb_request = request + pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "post", + "method": "get", "query_params": pb_request, } - transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse.pb( + return_value + ) + ) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.test_iam_permissions(request) + response = client.list_instance_partition_operations(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_test_iam_permissions_rest_unset_required_fields(): +def test_list_instance_partition_operations_rest_unset_required_fields(): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.test_iam_permissions._get_unset_required_fields({}) + unset_fields = ( + transport.list_instance_partition_operations._get_unset_required_fields({}) + ) assert set(unset_fields) == ( - set(()) - & set( + set( ( - "resource", - "permissions", + "filter", + "instancePartitionDeadline", + "pageSize", + "pageToken", ) ) + & set(("parent",)) ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_test_iam_permissions_rest_interceptors(null_interceptor): +def test_list_instance_partition_operations_rest_interceptors(null_interceptor): transport = transports.InstanceAdminRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -8753,13 +16561,17 @@ def test_test_iam_permissions_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.InstanceAdminRestInterceptor, "post_test_iam_permissions" + transports.InstanceAdminRestInterceptor, + "post_list_instance_partition_operations", ) as post, mock.patch.object( - transports.InstanceAdminRestInterceptor, "pre_test_iam_permissions" + transports.InstanceAdminRestInterceptor, + "pre_list_instance_partition_operations", ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = iam_policy_pb2.TestIamPermissionsRequest() + pb_message = spanner_instance_admin.ListInstancePartitionOperationsRequest.pb( + spanner_instance_admin.ListInstancePartitionOperationsRequest() + ) transcode.return_value = { "method": "post", "uri": "my_uri", @@ -8770,19 +16582,23 @@ def test_test_iam_permissions_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = json_format.MessageToJson( - iam_policy_pb2.TestIamPermissionsResponse() + req.return_value._content = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse.to_json( + spanner_instance_admin.ListInstancePartitionOperationsResponse() + ) ) - request = iam_policy_pb2.TestIamPermissionsRequest() + request = spanner_instance_admin.ListInstancePartitionOperationsRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = iam_policy_pb2.TestIamPermissionsResponse() + post.return_value = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse() + ) - client.test_iam_permissions( + client.list_instance_partition_operations( request, metadata=[ ("key", "val"), @@ -8794,8 +16610,9 @@ def test_test_iam_permissions_rest_interceptors(null_interceptor): post.assert_called_once() -def test_test_iam_permissions_rest_bad_request( - transport: str = "rest", request_type=iam_policy_pb2.TestIamPermissionsRequest +def test_list_instance_partition_operations_rest_bad_request( + transport: str = "rest", + request_type=spanner_instance_admin.ListInstancePartitionOperationsRequest, ): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), @@ -8803,7 +16620,7 @@ def test_test_iam_permissions_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"resource": "projects/sample1/instances/sample2"} + request_init = {"parent": "projects/sample1/instances/sample2"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -8815,10 +16632,10 @@ def test_test_iam_permissions_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.test_iam_permissions(request) + client.list_instance_partition_operations(request) -def test_test_iam_permissions_rest_flattened(): +def test_list_instance_partition_operations_rest_flattened(): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -8827,39 +16644,46 @@ def test_test_iam_permissions_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = iam_policy_pb2.TestIamPermissionsResponse() + return_value = spanner_instance_admin.ListInstancePartitionOperationsResponse() # get arguments that satisfy an http rule for this method - sample_request = {"resource": "projects/sample1/instances/sample2"} + sample_request = {"parent": "projects/sample1/instances/sample2"} # get truthy value for each flattened field mock_args = dict( - resource="resource_value", - permissions=["permissions_value"], + parent="parent_value", ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse.pb( + return_value + ) + ) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.test_iam_permissions(**mock_args) + client.list_instance_partition_operations(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1/{resource=projects/*/instances/*}:testIamPermissions" + "%s/v1/{parent=projects/*/instances/*}/instancePartitionOperations" % client.transport._host, args[1], ) -def test_test_iam_permissions_rest_flattened_error(transport: str = "rest"): +def test_list_instance_partition_operations_rest_flattened_error( + transport: str = "rest", +): client = InstanceAdminClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -8868,18 +16692,77 @@ def test_test_iam_permissions_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.test_iam_permissions( - iam_policy_pb2.TestIamPermissionsRequest(), - resource="resource_value", - permissions=["permissions_value"], + client.list_instance_partition_operations( + spanner_instance_admin.ListInstancePartitionOperationsRequest(), + parent="parent_value", ) -def test_test_iam_permissions_rest_error(): +def test_list_instance_partition_operations_rest_pager(transport: str = "rest"): client = InstanceAdminClient( - credentials=ga_credentials.AnonymousCredentials(), transport="rest" + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, ) + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + next_page_token="abc", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[], + next_page_token="def", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + ], + next_page_token="ghi", + ), + spanner_instance_admin.ListInstancePartitionOperationsResponse( + operations=[ + operations_pb2.Operation(), + operations_pb2.Operation(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple( + spanner_instance_admin.ListInstancePartitionOperationsResponse.to_json(x) + for x in response + ) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = {"parent": "projects/sample1/instances/sample2"} + + pager = client.list_instance_partition_operations(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, operations_pb2.Operation) for i in results) + + pages = list( + client.list_instance_partition_operations(request=sample_request).pages + ) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. @@ -8915,7 +16798,7 @@ def test_credentials_transport_error(): ) # It is an error to provide an api_key and a credential. - options = mock.Mock() + options = client_options.ClientOptions() options.api_key = "api_key" with pytest.raises(ValueError): client = InstanceAdminClient( @@ -9027,6 +16910,7 @@ def test_instance_admin_base_transport(): "delete_instance_config", "list_instance_config_operations", "list_instances", + "list_instance_partitions", "get_instance", "create_instance", "update_instance", @@ -9034,6 +16918,11 @@ def test_instance_admin_base_transport(): "set_iam_policy", "get_iam_policy", "test_iam_permissions", + "get_instance_partition", + "create_instance_partition", + "delete_instance_partition", + "update_instance_partition", + "list_instance_partition_operations", ) for method in methods: with pytest.raises(NotImplementedError): @@ -9347,6 +17236,9 @@ def test_instance_admin_client_transport_session_collision(transport_name): session1 = client1.transport.list_instances._session session2 = client2.transport.list_instances._session assert session1 != session2 + session1 = client1.transport.list_instance_partitions._session + session2 = client2.transport.list_instance_partitions._session + assert session1 != session2 session1 = client1.transport.get_instance._session session2 = client2.transport.get_instance._session assert session1 != session2 @@ -9368,6 +17260,21 @@ def test_instance_admin_client_transport_session_collision(transport_name): session1 = client1.transport.test_iam_permissions._session session2 = client2.transport.test_iam_permissions._session assert session1 != session2 + session1 = client1.transport.get_instance_partition._session + session2 = client2.transport.get_instance_partition._session + assert session1 != session2 + session1 = client1.transport.create_instance_partition._session + session2 = client2.transport.create_instance_partition._session + assert session1 != session2 + session1 = client1.transport.delete_instance_partition._session + session2 = client2.transport.delete_instance_partition._session + assert session1 != session2 + session1 = client1.transport.update_instance_partition._session + session2 = client2.transport.update_instance_partition._session + assert session1 != session2 + session1 = client1.transport.list_instance_partition_operations._session + session2 = client2.transport.list_instance_partition_operations._session + assert session1 != session2 def test_instance_admin_grpc_transport_channel(): @@ -9574,8 +17481,36 @@ def test_parse_instance_config_path(): assert expected == actual +def test_instance_partition_path(): + project = "winkle" + instance = "nautilus" + instance_partition = "scallop" + expected = "projects/{project}/instances/{instance}/instancePartitions/{instance_partition}".format( + project=project, + instance=instance, + instance_partition=instance_partition, + ) + actual = InstanceAdminClient.instance_partition_path( + project, instance, instance_partition + ) + assert expected == actual + + +def test_parse_instance_partition_path(): + expected = { + "project": "abalone", + "instance": "squid", + "instance_partition": "clam", + } + path = InstanceAdminClient.instance_partition_path(**expected) + + # Check that the path construction is reversible. + actual = InstanceAdminClient.parse_instance_partition_path(path) + assert expected == actual + + def test_common_billing_account_path(): - billing_account = "winkle" + billing_account = "whelk" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -9585,7 +17520,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "nautilus", + "billing_account": "octopus", } path = InstanceAdminClient.common_billing_account_path(**expected) @@ -9595,7 +17530,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "scallop" + folder = "oyster" expected = "folders/{folder}".format( folder=folder, ) @@ -9605,7 +17540,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "abalone", + "folder": "nudibranch", } path = InstanceAdminClient.common_folder_path(**expected) @@ -9615,7 +17550,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "squid" + organization = "cuttlefish" expected = "organizations/{organization}".format( organization=organization, ) @@ -9625,7 +17560,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "clam", + "organization": "mussel", } path = InstanceAdminClient.common_organization_path(**expected) @@ -9635,7 +17570,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "whelk" + project = "winkle" expected = "projects/{project}".format( project=project, ) @@ -9645,7 +17580,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "octopus", + "project": "nautilus", } path = InstanceAdminClient.common_project_path(**expected) @@ -9655,8 +17590,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "oyster" - location = "nudibranch" + project = "scallop" + location = "abalone" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -9667,8 +17602,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "cuttlefish", - "location": "mussel", + "project": "squid", + "location": "clam", } path = InstanceAdminClient.common_location_path(**expected) @@ -9770,7 +17705,9 @@ def test_api_key_credentials(client_class, transport_class): patched.assert_called_once_with( credentials=mock_cred, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, diff --git a/tests/unit/gapic/spanner_v1/__init__.py b/tests/unit/gapic/spanner_v1/__init__.py index 89a37dc92c..8f6cf06824 100644 --- a/tests/unit/gapic/spanner_v1/__init__.py +++ b/tests/unit/gapic/spanner_v1/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/unit/gapic/spanner_v1/test_spanner.py b/tests/unit/gapic/spanner_v1/test_spanner.py index d136ba902c..6474ed0606 100644 --- a/tests/unit/gapic/spanner_v1/test_spanner.py +++ b/tests/unit/gapic/spanner_v1/test_spanner.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ import json import math import pytest +from google.api_core import api_core_version from proto.marshal.rules.dates import DurationRule, TimestampRule from proto.marshal.rules import wrappers from requests import Response @@ -78,6 +79,17 @@ def modify_default_endpoint(client): ) +# If default endpoint template is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint template so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint_template(client): + return ( + "test.{UNIVERSE_DOMAIN}" + if ("localhost" in client._DEFAULT_ENDPOINT_TEMPLATE) + else client._DEFAULT_ENDPOINT_TEMPLATE + ) + + def test__get_default_mtls_endpoint(): api_endpoint = "example.googleapis.com" api_mtls_endpoint = "example.mtls.googleapis.com" @@ -101,6 +113,245 @@ def test__get_default_mtls_endpoint(): assert SpannerClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi +def test__read_environment_variables(): + assert SpannerClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert SpannerClient._read_environment_variables() == (True, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert SpannerClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + SpannerClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + assert SpannerClient._read_environment_variables() == (False, "never", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert SpannerClient._read_environment_variables() == (False, "always", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert SpannerClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + SpannerClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_CLOUD_UNIVERSE_DOMAIN": "foo.com"}): + assert SpannerClient._read_environment_variables() == (False, "auto", "foo.com") + + +def test__get_client_cert_source(): + mock_provided_cert_source = mock.Mock() + mock_default_cert_source = mock.Mock() + + assert SpannerClient._get_client_cert_source(None, False) is None + assert ( + SpannerClient._get_client_cert_source(mock_provided_cert_source, False) is None + ) + assert ( + SpannerClient._get_client_cert_source(mock_provided_cert_source, True) + == mock_provided_cert_source + ) + + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", return_value=True + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_default_cert_source, + ): + assert ( + SpannerClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + SpannerClient._get_client_cert_source(mock_provided_cert_source, "true") + is mock_provided_cert_source + ) + + +@mock.patch.object( + SpannerClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(SpannerClient), +) +@mock.patch.object( + SpannerAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(SpannerAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = SpannerClient._DEFAULT_UNIVERSE + default_endpoint = SpannerClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = SpannerClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + SpannerClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + SpannerClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == SpannerClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + SpannerClient._get_api_endpoint(None, None, default_universe, "auto") + == default_endpoint + ) + assert ( + SpannerClient._get_api_endpoint(None, None, default_universe, "always") + == SpannerClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + SpannerClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == SpannerClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + SpannerClient._get_api_endpoint(None, None, mock_universe, "never") + == mock_endpoint + ) + assert ( + SpannerClient._get_api_endpoint(None, None, default_universe, "never") + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + SpannerClient._get_api_endpoint( + None, mock_client_cert_source, mock_universe, "auto" + ) + assert ( + str(excinfo.value) + == "mTLS is not supported in any universe other than googleapis.com." + ) + + +def test__get_universe_domain(): + client_universe_domain = "foo.com" + universe_domain_env = "bar.com" + + assert ( + SpannerClient._get_universe_domain(client_universe_domain, universe_domain_env) + == client_universe_domain + ) + assert ( + SpannerClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + SpannerClient._get_universe_domain(None, None) + == SpannerClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + SpannerClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (SpannerClient, transports.SpannerGrpcTransport, "grpc"), + (SpannerClient, transports.SpannerRestTransport, "rest"), + ], +) +def test__validate_universe_domain(client_class, transport_class, transport_name): + client = client_class( + transport=transport_class(credentials=ga_credentials.AnonymousCredentials()) + ) + assert client._validate_universe_domain() == True + + # Test the case when universe is already validated. + assert client._validate_universe_domain() == True + + if transport_name == "grpc": + # Test the case where credentials are provided by the + # `local_channel_credentials`. The default universes in both match. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + client = client_class(transport=transport_class(channel=channel)) + assert client._validate_universe_domain() == True + + # Test the case where credentials do not exist: e.g. a transport is provided + # with no credentials. Validation should still succeed because there is no + # mismatch with non-existent credentials. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + transport = transport_class(channel=channel) + transport._credentials = None + client = client_class(transport=transport) + assert client._validate_universe_domain() == True + + # TODO: This is needed to cater for older versions of google-auth + # Make this test unconditional once the minimum supported version of + # google-auth becomes 2.23.0 or higher. + google_auth_major, google_auth_minor = [ + int(part) for part in google.auth.__version__.split(".")[0:2] + ] + if google_auth_major > 2 or (google_auth_major == 2 and google_auth_minor >= 23): + credentials = ga_credentials.AnonymousCredentials() + credentials._universe_domain = "foo.com" + # Test the case when there is a universe mismatch from the credentials. + client = client_class(transport=transport_class(credentials=credentials)) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (googleapis.com) does not match the universe domain found in the credentials (foo.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test the case when there is a universe mismatch from the client. + # + # TODO: Make this test unconditional once the minimum supported version of + # google-api-core becomes 2.15.0 or higher. + api_core_major, api_core_minor = [ + int(part) for part in api_core_version.__version__.split(".")[0:2] + ] + if api_core_major > 2 or (api_core_major == 2 and api_core_minor >= 15): + client = client_class( + client_options={"universe_domain": "bar.com"}, + transport=transport_class( + credentials=ga_credentials.AnonymousCredentials(), + ), + ) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (bar.com) does not match the universe domain found in the credentials (googleapis.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test that ValueError is raised if universe_domain is provided via client options and credentials is None + with pytest.raises(ValueError): + client._compare_universes("foo.bar", None) + + @pytest.mark.parametrize( "client_class,transport_name", [ @@ -205,10 +456,14 @@ def test_spanner_client_get_transport_class(): ], ) @mock.patch.object( - SpannerClient, "DEFAULT_ENDPOINT", modify_default_endpoint(SpannerClient) + SpannerClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(SpannerClient), ) @mock.patch.object( - SpannerAsyncClient, "DEFAULT_ENDPOINT", modify_default_endpoint(SpannerAsyncClient) + SpannerAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(SpannerAsyncClient), ) def test_spanner_client_client_options(client_class, transport_class, transport_name): # Check that if channel is provided we won't create a new one. @@ -248,7 +503,9 @@ def test_spanner_client_client_options(client_class, transport_class, transport_ patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -278,15 +535,23 @@ def test_spanner_client_client_options(client_class, transport_class, transport_ # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has # unsupported value. with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): + with pytest.raises(MutualTLSChannelError) as excinfo: client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. with mock.patch.dict( os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} ): - with pytest.raises(ValueError): + with pytest.raises(ValueError) as excinfo: client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) # Check the case quota_project_id is provided options = client_options.ClientOptions(quota_project_id="octopus") @@ -296,7 +561,9 @@ def test_spanner_client_client_options(client_class, transport_class, transport_ patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id="octopus", @@ -314,7 +581,9 @@ def test_spanner_client_client_options(client_class, transport_class, transport_ patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -346,10 +615,14 @@ def test_spanner_client_client_options(client_class, transport_class, transport_ ], ) @mock.patch.object( - SpannerClient, "DEFAULT_ENDPOINT", modify_default_endpoint(SpannerClient) + SpannerClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(SpannerClient), ) @mock.patch.object( - SpannerAsyncClient, "DEFAULT_ENDPOINT", modify_default_endpoint(SpannerAsyncClient) + SpannerAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(SpannerAsyncClient), ) @mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) def test_spanner_client_mtls_env_auto( @@ -372,7 +645,9 @@ def test_spanner_client_mtls_env_auto( if use_client_cert_env == "false": expected_client_cert_source = None - expected_host = client.DEFAULT_ENDPOINT + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) else: expected_client_cert_source = client_cert_source_callback expected_host = client.DEFAULT_MTLS_ENDPOINT @@ -404,7 +679,9 @@ def test_spanner_client_mtls_env_auto( return_value=client_cert_source_callback, ): if use_client_cert_env == "false": - expected_host = client.DEFAULT_ENDPOINT + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) expected_client_cert_source = None else: expected_host = client.DEFAULT_MTLS_ENDPOINT @@ -438,7 +715,9 @@ def test_spanner_client_mtls_env_auto( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -522,6 +801,113 @@ def test_spanner_client_get_mtls_endpoint_and_cert_source(client_class): assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT assert cert_source == mock_client_cert_source + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + +@pytest.mark.parametrize("client_class", [SpannerClient, SpannerAsyncClient]) +@mock.patch.object( + SpannerClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(SpannerClient), +) +@mock.patch.object( + SpannerAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(SpannerAsyncClient), +) +def test_spanner_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = SpannerClient._DEFAULT_UNIVERSE + default_endpoint = SpannerClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = SpannerClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + # If ClientOptions.api_endpoint is set and GOOGLE_API_USE_CLIENT_CERTIFICATE="true", + # use ClientOptions.api_endpoint as the api endpoint regardless. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ): + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=api_override + ) + client = client_class( + client_options=options, + credentials=ga_credentials.AnonymousCredentials(), + ) + assert client.api_endpoint == api_override + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == default_endpoint + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="always", + # use the DEFAULT_MTLS_ENDPOINT as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + + # If ClientOptions.api_endpoint is not set, GOOGLE_API_USE_MTLS_ENDPOINT="auto" (default), + # GOOGLE_API_USE_CLIENT_CERTIFICATE="false" (default), default cert source doesn't exist, + # and ClientOptions.universe_domain="bar.com", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with universe domain as the api endpoint. + options = client_options.ClientOptions() + universe_exists = hasattr(options, "universe_domain") + if universe_exists: + options = client_options.ClientOptions(universe_domain=mock_universe) + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + else: + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == ( + mock_endpoint if universe_exists else default_endpoint + ) + assert client.universe_domain == ( + mock_universe if universe_exists else default_universe + ) + + # If ClientOptions does not have a universe domain attribute and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + options = client_options.ClientOptions() + if hasattr(options, "universe_domain"): + delattr(options, "universe_domain") + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == default_endpoint + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -544,7 +930,9 @@ def test_spanner_client_client_options_scopes( patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=["1", "2"], client_cert_source_for_mtls=None, quota_project_id=None, @@ -579,7 +967,9 @@ def test_spanner_client_client_options_credentials_file( patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -632,7 +1022,9 @@ def test_spanner_client_create_channel_credentials_file( patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, @@ -696,18 +1088,21 @@ def test_create_session(request_type, transport: str = "grpc"): call.return_value = spanner.Session( name="name_value", creator_role="creator_role_value", + multiplexed=True, ) response = client.create_session(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.CreateSessionRequest() + request = spanner.CreateSessionRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.Session) assert response.name == "name_value" assert response.creator_role == "creator_role_value" + assert response.multiplexed is True def test_create_session_empty_call(): @@ -720,12 +1115,149 @@ def test_create_session_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.create_session), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.create_session() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.CreateSessionRequest() +def test_create_session_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.CreateSessionRequest( + database="database_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.create_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.CreateSessionRequest( + database="database_value", + ) + + +def test_create_session_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.create_session in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.create_session] = mock_rpc + request = {} + client.create_session(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.create_session(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_create_session_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner.Session( + name="name_value", + creator_role="creator_role_value", + multiplexed=True, + ) + ) + response = await client.create_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.CreateSessionRequest() + + +@pytest.mark.asyncio +async def test_create_session_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.create_session + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.create_session + ] = mock_object + + request = {} + await client.create_session(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.create_session(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_create_session_async( transport: str = "grpc_asyncio", request_type=spanner.CreateSessionRequest @@ -746,6 +1278,7 @@ async def test_create_session_async( spanner.Session( name="name_value", creator_role="creator_role_value", + multiplexed=True, ) ) response = await client.create_session(request) @@ -753,12 +1286,14 @@ async def test_create_session_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.CreateSessionRequest() + request = spanner.CreateSessionRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.Session) assert response.name == "name_value" assert response.creator_role == "creator_role_value" + assert response.multiplexed is True @pytest.mark.asyncio @@ -933,7 +1468,8 @@ def test_batch_create_sessions(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.BatchCreateSessionsRequest() + request = spanner.BatchCreateSessionsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.BatchCreateSessionsResponse) @@ -951,19 +1487,161 @@ def test_batch_create_sessions_empty_call(): with mock.patch.object( type(client.transport.batch_create_sessions), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.batch_create_sessions() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.BatchCreateSessionsRequest() -@pytest.mark.asyncio -async def test_batch_create_sessions_async( - transport: str = "grpc_asyncio", request_type=spanner.BatchCreateSessionsRequest -): - client = SpannerAsyncClient( +def test_batch_create_sessions_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.BatchCreateSessionsRequest( + database="database_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_create_sessions), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.batch_create_sessions(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.BatchCreateSessionsRequest( + database="database_value", + ) + + +def test_batch_create_sessions_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.batch_create_sessions + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.batch_create_sessions + ] = mock_rpc + request = {} + client.batch_create_sessions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.batch_create_sessions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_batch_create_sessions_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_create_sessions), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner.BatchCreateSessionsResponse() + ) + response = await client.batch_create_sessions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.BatchCreateSessionsRequest() + + +@pytest.mark.asyncio +async def test_batch_create_sessions_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.batch_create_sessions + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.batch_create_sessions + ] = mock_object + + request = {} + await client.batch_create_sessions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.batch_create_sessions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_batch_create_sessions_async( + transport: str = "grpc_asyncio", request_type=spanner.BatchCreateSessionsRequest +): + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, @@ -983,7 +1661,8 @@ async def test_batch_create_sessions_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.BatchCreateSessionsRequest() + request = spanner.BatchCreateSessionsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.BatchCreateSessionsResponse) @@ -1178,18 +1857,21 @@ def test_get_session(request_type, transport: str = "grpc"): call.return_value = spanner.Session( name="name_value", creator_role="creator_role_value", + multiplexed=True, ) response = client.get_session(request) # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.GetSessionRequest() + request = spanner.GetSessionRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.Session) assert response.name == "name_value" assert response.creator_role == "creator_role_value" + assert response.multiplexed is True def test_get_session_empty_call(): @@ -1202,12 +1884,149 @@ def test_get_session_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.get_session), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.get_session() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.GetSessionRequest() +def test_get_session_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.GetSessionRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.GetSessionRequest( + name="name_value", + ) + + +def test_get_session_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_session in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_session] = mock_rpc + request = {} + client.get_session(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_session(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_session_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner.Session( + name="name_value", + creator_role="creator_role_value", + multiplexed=True, + ) + ) + response = await client.get_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.GetSessionRequest() + + +@pytest.mark.asyncio +async def test_get_session_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_session + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.get_session + ] = mock_object + + request = {} + await client.get_session(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.get_session(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_get_session_async( transport: str = "grpc_asyncio", request_type=spanner.GetSessionRequest @@ -1228,6 +2047,7 @@ async def test_get_session_async( spanner.Session( name="name_value", creator_role="creator_role_value", + multiplexed=True, ) ) response = await client.get_session(request) @@ -1235,12 +2055,14 @@ async def test_get_session_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.GetSessionRequest() + request = spanner.GetSessionRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.Session) assert response.name == "name_value" assert response.creator_role == "creator_role_value" + assert response.multiplexed is True @pytest.mark.asyncio @@ -1415,7 +2237,8 @@ def test_list_sessions(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ListSessionsRequest() + request = spanner.ListSessionsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListSessionsPager) @@ -1432,12 +2255,151 @@ def test_list_sessions_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.list_sessions() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.ListSessionsRequest() +def test_list_sessions_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.ListSessionsRequest( + database="database_value", + page_token="page_token_value", + filter="filter_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_sessions(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ListSessionsRequest( + database="database_value", + page_token="page_token_value", + filter="filter_value", + ) + + +def test_list_sessions_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.list_sessions in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.list_sessions] = mock_rpc + request = {} + client.list_sessions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_sessions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_sessions_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner.ListSessionsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_sessions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ListSessionsRequest() + + +@pytest.mark.asyncio +async def test_list_sessions_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_sessions + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.list_sessions + ] = mock_object + + request = {} + await client.list_sessions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.list_sessions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_list_sessions_async( transport: str = "grpc_asyncio", request_type=spanner.ListSessionsRequest @@ -1464,7 +2426,8 @@ async def test_list_sessions_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ListSessionsRequest() + request = spanner.ListSessionsRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListSessionsAsyncPager) @@ -1621,7 +2584,7 @@ async def test_list_sessions_flattened_error_async(): def test_list_sessions_pager(transport_name: str = "grpc"): client = SpannerClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -1671,7 +2634,7 @@ def test_list_sessions_pager(transport_name: str = "grpc"): def test_list_sessions_pages(transport_name: str = "grpc"): client = SpannerClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), transport=transport_name, ) @@ -1713,7 +2676,7 @@ def test_list_sessions_pages(transport_name: str = "grpc"): @pytest.mark.asyncio async def test_list_sessions_async_pager(): client = SpannerAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1763,7 +2726,7 @@ async def test_list_sessions_async_pager(): @pytest.mark.asyncio async def test_list_sessions_async_pages(): client = SpannerAsyncClient( - credentials=ga_credentials.AnonymousCredentials, + credentials=ga_credentials.AnonymousCredentials(), ) # Mock the actual call within the gRPC stub, and fake the request. @@ -1835,7 +2798,8 @@ def test_delete_session(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.DeleteSessionRequest() + request = spanner.DeleteSessionRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert response is None @@ -1851,23 +2815,154 @@ def test_delete_session_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.delete_session() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.DeleteSessionRequest() -@pytest.mark.asyncio -async def test_delete_session_async( - transport: str = "grpc_asyncio", request_type=spanner.DeleteSessionRequest -): - client = SpannerAsyncClient( +def test_delete_session_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.DeleteSessionRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.DeleteSessionRequest( + name="name_value", + ) + + +def test_delete_session_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.delete_session in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.delete_session] = mock_rpc + request = {} + client.delete_session(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.delete_session(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_session_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.DeleteSessionRequest() + + +@pytest.mark.asyncio +async def test_delete_session_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.delete_session + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.delete_session + ] = mock_object + + request = {} + await client.delete_session(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.delete_session(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_session_async( + transport: str = "grpc_asyncio", request_type=spanner.DeleteSessionRequest +): + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. request = request_type() # Mock the actual call within the gRPC stub, and fake the request. @@ -1879,7 +2974,8 @@ async def test_delete_session_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.DeleteSessionRequest() + request = spanner.DeleteSessionRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert response is None @@ -2055,7 +3151,8 @@ def test_execute_sql(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ExecuteSqlRequest() + request = spanner.ExecuteSqlRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, result_set.ResultSet) @@ -2071,12 +3168,147 @@ def test_execute_sql_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.execute_sql), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.execute_sql() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.ExecuteSqlRequest() +def test_execute_sql_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.ExecuteSqlRequest( + session="session_value", + sql="sql_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.execute_sql), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.execute_sql(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ExecuteSqlRequest( + session="session_value", + sql="sql_value", + ) + + +def test_execute_sql_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.execute_sql in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.execute_sql] = mock_rpc + request = {} + client.execute_sql(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.execute_sql(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_execute_sql_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.execute_sql), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + result_set.ResultSet() + ) + response = await client.execute_sql() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ExecuteSqlRequest() + + +@pytest.mark.asyncio +async def test_execute_sql_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.execute_sql + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.execute_sql + ] = mock_object + + request = {} + await client.execute_sql(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.execute_sql(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_execute_sql_async( transport: str = "grpc_asyncio", request_type=spanner.ExecuteSqlRequest @@ -2101,7 +3333,8 @@ async def test_execute_sql_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ExecuteSqlRequest() + request = spanner.ExecuteSqlRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, result_set.ResultSet) @@ -2201,7 +3434,8 @@ def test_execute_streaming_sql(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ExecuteSqlRequest() + request = spanner.ExecuteSqlRequest() + assert args[0] == request # Establish that the response is the type that we expect. for message in response: @@ -2220,12 +3454,157 @@ def test_execute_streaming_sql_empty_call(): with mock.patch.object( type(client.transport.execute_streaming_sql), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.execute_streaming_sql() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.ExecuteSqlRequest() +def test_execute_streaming_sql_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.ExecuteSqlRequest( + session="session_value", + sql="sql_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.execute_streaming_sql), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.execute_streaming_sql(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ExecuteSqlRequest( + session="session_value", + sql="sql_value", + ) + + +def test_execute_streaming_sql_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.execute_streaming_sql + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.execute_streaming_sql + ] = mock_rpc + request = {} + client.execute_streaming_sql(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.execute_streaming_sql(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_execute_streaming_sql_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.execute_streaming_sql), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = mock.Mock(aio.UnaryStreamCall, autospec=True) + call.return_value.read = mock.AsyncMock( + side_effect=[result_set.PartialResultSet()] + ) + response = await client.execute_streaming_sql() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ExecuteSqlRequest() + + +@pytest.mark.asyncio +async def test_execute_streaming_sql_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.execute_streaming_sql + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.execute_streaming_sql + ] = mock_object + + request = {} + await client.execute_streaming_sql(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.execute_streaming_sql(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_execute_streaming_sql_async( transport: str = "grpc_asyncio", request_type=spanner.ExecuteSqlRequest @@ -2253,7 +3632,8 @@ async def test_execute_streaming_sql_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ExecuteSqlRequest() + request = spanner.ExecuteSqlRequest() + assert args[0] == request # Establish that the response is the type that we expect. message = await response.read() @@ -2359,7 +3739,8 @@ def test_execute_batch_dml(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ExecuteBatchDmlRequest() + request = spanner.ExecuteBatchDmlRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.ExecuteBatchDmlResponse) @@ -2377,40 +3758,180 @@ def test_execute_batch_dml_empty_call(): with mock.patch.object( type(client.transport.execute_batch_dml), "__call__" ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.execute_batch_dml() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.ExecuteBatchDmlRequest() -@pytest.mark.asyncio -async def test_execute_batch_dml_async( - transport: str = "grpc_asyncio", request_type=spanner.ExecuteBatchDmlRequest -): - client = SpannerAsyncClient( +def test_execute_batch_dml_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="grpc", ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.ExecuteBatchDmlRequest( + session="session_value", + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( type(client.transport.execute_batch_dml), "__call__" ) as call: - # Designate an appropriate return value for the call. - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - spanner.ExecuteBatchDmlResponse() + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. ) - response = await client.execute_batch_dml(request) - - # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) + client.execute_batch_dml(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ExecuteBatchDmlRequest( + session="session_value", + ) + + +def test_execute_batch_dml_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.execute_batch_dml in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.execute_batch_dml + ] = mock_rpc + request = {} + client.execute_batch_dml(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.execute_batch_dml(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_execute_batch_dml_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.execute_batch_dml), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner.ExecuteBatchDmlResponse() + ) + response = await client.execute_batch_dml() + call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.ExecuteBatchDmlRequest() + +@pytest.mark.asyncio +async def test_execute_batch_dml_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.execute_batch_dml + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.execute_batch_dml + ] = mock_object + + request = {} + await client.execute_batch_dml(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.execute_batch_dml(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + +@pytest.mark.asyncio +async def test_execute_batch_dml_async( + transport: str = "grpc_asyncio", request_type=spanner.ExecuteBatchDmlRequest +): + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.execute_batch_dml), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner.ExecuteBatchDmlResponse() + ) + response = await client.execute_batch_dml(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = spanner.ExecuteBatchDmlRequest() + assert args[0] == request + # Establish that the response is the type that we expect. assert isinstance(response, spanner.ExecuteBatchDmlResponse) @@ -2511,7 +4032,8 @@ def test_read(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ReadRequest() + request = spanner.ReadRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, result_set.ResultSet) @@ -2527,12 +4049,146 @@ def test_read_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.read), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.read() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.ReadRequest() +def test_read_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.ReadRequest( + session="session_value", + table="table_value", + index="index_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.read), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.read(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ReadRequest( + session="session_value", + table="table_value", + index="index_value", + ) + + +def test_read_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.read in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.read] = mock_rpc + request = {} + client.read(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.read(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_read_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.read), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + result_set.ResultSet() + ) + response = await client.read() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ReadRequest() + + +@pytest.mark.asyncio +async def test_read_async_use_cached_wrapped_rpc(transport: str = "grpc_asyncio"): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.read in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.read + ] = mock_object + + request = {} + await client.read(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.read(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_read_async( transport: str = "grpc_asyncio", request_type=spanner.ReadRequest @@ -2557,7 +4213,8 @@ async def test_read_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ReadRequest() + request = spanner.ReadRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, result_set.ResultSet) @@ -2655,7 +4312,8 @@ def test_streaming_read(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ReadRequest() + request = spanner.ReadRequest() + assert args[0] == request # Establish that the response is the type that we expect. for message in response: @@ -2672,12 +4330,150 @@ def test_streaming_read_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.streaming_read), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.streaming_read() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.ReadRequest() +def test_streaming_read_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.ReadRequest( + session="session_value", + table="table_value", + index="index_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.streaming_read), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.streaming_read(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ReadRequest( + session="session_value", + table="table_value", + index="index_value", + ) + + +def test_streaming_read_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.streaming_read in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.streaming_read] = mock_rpc + request = {} + client.streaming_read(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.streaming_read(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_streaming_read_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.streaming_read), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = mock.Mock(aio.UnaryStreamCall, autospec=True) + call.return_value.read = mock.AsyncMock( + side_effect=[result_set.PartialResultSet()] + ) + response = await client.streaming_read() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.ReadRequest() + + +@pytest.mark.asyncio +async def test_streaming_read_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.streaming_read + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.streaming_read + ] = mock_object + + request = {} + await client.streaming_read(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.streaming_read(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_streaming_read_async( transport: str = "grpc_asyncio", request_type=spanner.ReadRequest @@ -2703,7 +4499,8 @@ async def test_streaming_read_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.ReadRequest() + request = spanner.ReadRequest() + assert args[0] == request # Establish that the response is the type that we expect. message = await response.read() @@ -2790,48 +4587,190 @@ def test_begin_transaction(request_type, transport: str = "grpc"): transport=transport, ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.begin_transaction), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = transaction.Transaction( + id=b"id_blob", + ) + response = client.begin_transaction(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = spanner.BeginTransactionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, transaction.Transaction) + assert response.id == b"id_blob" + + +def test_begin_transaction_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.begin_transaction), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.begin_transaction() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.BeginTransactionRequest() + + +def test_begin_transaction_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.BeginTransactionRequest( + session="session_value", + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( type(client.transport.begin_transaction), "__call__" ) as call: - # Designate an appropriate return value for the call. - call.return_value = transaction.Transaction( - id=b"id_blob", + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. ) - response = client.begin_transaction(request) + client.begin_transaction(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.BeginTransactionRequest( + session="session_value", + ) + + +def test_begin_transaction_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.begin_transaction in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.begin_transaction + ] = mock_rpc + request = {} + client.begin_transaction(request) # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) == 1 - _, args, _ = call.mock_calls[0] - assert args[0] == spanner.BeginTransactionRequest() + assert mock_rpc.call_count == 1 - # Establish that the response is the type that we expect. - assert isinstance(response, transaction.Transaction) - assert response.id == b"id_blob" + client.begin_transaction(request) + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 -def test_begin_transaction_empty_call(): + +@pytest.mark.asyncio +async def test_begin_transaction_empty_call_async(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. - client = SpannerClient( + client = SpannerAsyncClient( credentials=ga_credentials.AnonymousCredentials(), - transport="grpc", + transport="grpc_asyncio", ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( type(client.transport.begin_transaction), "__call__" ) as call: - client.begin_transaction() + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + transaction.Transaction( + id=b"id_blob", + ) + ) + response = await client.begin_transaction() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.BeginTransactionRequest() +@pytest.mark.asyncio +async def test_begin_transaction_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.begin_transaction + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.begin_transaction + ] = mock_object + + request = {} + await client.begin_transaction(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.begin_transaction(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_begin_transaction_async( transport: str = "grpc_asyncio", request_type=spanner.BeginTransactionRequest @@ -2860,7 +4799,8 @@ async def test_begin_transaction_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.BeginTransactionRequest() + request = spanner.BeginTransactionRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, transaction.Transaction) @@ -3083,7 +5023,8 @@ def test_commit(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.CommitRequest() + request = spanner.CommitRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, commit_response.CommitResponse) @@ -3099,12 +5040,143 @@ def test_commit_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.commit), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.commit() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.CommitRequest() +def test_commit_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.CommitRequest( + session="session_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.commit), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.commit(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.CommitRequest( + session="session_value", + ) + + +def test_commit_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.commit in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.commit] = mock_rpc + request = {} + client.commit(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.commit(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_commit_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.commit), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + commit_response.CommitResponse() + ) + response = await client.commit() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.CommitRequest() + + +@pytest.mark.asyncio +async def test_commit_async_use_cached_wrapped_rpc(transport: str = "grpc_asyncio"): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.commit + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.commit + ] = mock_object + + request = {} + await client.commit(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.commit(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_commit_async( transport: str = "grpc_asyncio", request_type=spanner.CommitRequest @@ -3129,7 +5201,8 @@ async def test_commit_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.CommitRequest() + request = spanner.CommitRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, commit_response.CommitResponse) @@ -3365,7 +5438,8 @@ def test_rollback(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.RollbackRequest() + request = spanner.RollbackRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert response is None @@ -3381,12 +5455,141 @@ def test_rollback_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.rollback), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.rollback() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.RollbackRequest() +def test_rollback_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.RollbackRequest( + session="session_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.rollback), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.rollback(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.RollbackRequest( + session="session_value", + ) + + +def test_rollback_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.rollback in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.rollback] = mock_rpc + request = {} + client.rollback(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.rollback(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_rollback_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.rollback), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.rollback() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.RollbackRequest() + + +@pytest.mark.asyncio +async def test_rollback_async_use_cached_wrapped_rpc(transport: str = "grpc_asyncio"): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.rollback + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.rollback + ] = mock_object + + request = {} + await client.rollback(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.rollback(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_rollback_async( transport: str = "grpc_asyncio", request_type=spanner.RollbackRequest @@ -3409,7 +5612,8 @@ async def test_rollback_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.RollbackRequest() + request = spanner.RollbackRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert response is None @@ -3582,41 +5786,177 @@ def test_partition_query(request_type, transport: str = "grpc"): transport=transport, ) - # Everything is optional in proto3 as far as the runtime is concerned, - # and we are mocking out the actual API, so just send an empty request. - request = request_type() + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.partition_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = spanner.PartitionResponse() + response = client.partition_query(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = spanner.PartitionQueryRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, spanner.PartitionResponse) + + +def test_partition_query_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.partition_query), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.partition_query() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.PartitionQueryRequest() + + +def test_partition_query_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.PartitionQueryRequest( + session="session_value", + sql="sql_value", + ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.partition_query), "__call__") as call: - # Designate an appropriate return value for the call. - call.return_value = spanner.PartitionResponse() - response = client.partition_query(request) + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.partition_query(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.PartitionQueryRequest( + session="session_value", + sql="sql_value", + ) + + +def test_partition_query_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.partition_query in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.partition_query] = mock_rpc + request = {} + client.partition_query(request) # Establish that the underlying gRPC stub method was called. - assert len(call.mock_calls) == 1 - _, args, _ = call.mock_calls[0] - assert args[0] == spanner.PartitionQueryRequest() + assert mock_rpc.call_count == 1 - # Establish that the response is the type that we expect. - assert isinstance(response, spanner.PartitionResponse) + client.partition_query(request) + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 -def test_partition_query_empty_call(): + +@pytest.mark.asyncio +async def test_partition_query_empty_call_async(): # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. - client = SpannerClient( + client = SpannerAsyncClient( credentials=ga_credentials.AnonymousCredentials(), - transport="grpc", + transport="grpc_asyncio", ) # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.partition_query), "__call__") as call: - client.partition_query() + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner.PartitionResponse() + ) + response = await client.partition_query() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.PartitionQueryRequest() +@pytest.mark.asyncio +async def test_partition_query_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.partition_query + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.partition_query + ] = mock_object + + request = {} + await client.partition_query(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.partition_query(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_partition_query_async( transport: str = "grpc_asyncio", request_type=spanner.PartitionQueryRequest @@ -3641,7 +5981,8 @@ async def test_partition_query_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.PartitionQueryRequest() + request = spanner.PartitionQueryRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.PartitionResponse) @@ -3739,7 +6080,8 @@ def test_partition_read(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.PartitionReadRequest() + request = spanner.PartitionReadRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.PartitionResponse) @@ -3755,12 +6097,149 @@ def test_partition_read_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.partition_read), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.partition_read() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.PartitionReadRequest() +def test_partition_read_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.PartitionReadRequest( + session="session_value", + table="table_value", + index="index_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.partition_read), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.partition_read(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.PartitionReadRequest( + session="session_value", + table="table_value", + index="index_value", + ) + + +def test_partition_read_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.partition_read in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.partition_read] = mock_rpc + request = {} + client.partition_read(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.partition_read(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_partition_read_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.partition_read), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + spanner.PartitionResponse() + ) + response = await client.partition_read() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.PartitionReadRequest() + + +@pytest.mark.asyncio +async def test_partition_read_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.partition_read + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.partition_read + ] = mock_object + + request = {} + await client.partition_read(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.partition_read(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_partition_read_async( transport: str = "grpc_asyncio", request_type=spanner.PartitionReadRequest @@ -3785,7 +6264,8 @@ async def test_partition_read_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.PartitionReadRequest() + request = spanner.PartitionReadRequest() + assert args[0] == request # Establish that the response is the type that we expect. assert isinstance(response, spanner.PartitionResponse) @@ -3883,7 +6363,8 @@ def test_batch_write(request_type, transport: str = "grpc"): # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0] == spanner.BatchWriteRequest() + request = spanner.BatchWriteRequest() + assert args[0] == request # Establish that the response is the type that we expect. for message in response: @@ -3900,12 +6381,146 @@ def test_batch_write_empty_call(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.batch_write), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) client.batch_write() call.assert_called() _, args, _ = call.mock_calls[0] assert args[0] == spanner.BatchWriteRequest() +def test_batch_write_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = spanner.BatchWriteRequest( + session="session_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.batch_write), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.batch_write(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.BatchWriteRequest( + session="session_value", + ) + + +def test_batch_write_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.batch_write in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.batch_write] = mock_rpc + request = {} + client.batch_write(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.batch_write(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_batch_write_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.batch_write), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = mock.Mock(aio.UnaryStreamCall, autospec=True) + call.return_value.read = mock.AsyncMock( + side_effect=[spanner.BatchWriteResponse()] + ) + response = await client.batch_write() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == spanner.BatchWriteRequest() + + +@pytest.mark.asyncio +async def test_batch_write_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = SpannerAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.batch_write + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + class AwaitableMock(mock.AsyncMock): + def __await__(self): + self.await_count += 1 + return iter([]) + + mock_object = AwaitableMock() + client._client._transport._wrapped_methods[ + client._client._transport.batch_write + ] = mock_object + + request = {} + await client.batch_write(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_object.call_count == 1 + + await client.batch_write(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_object.call_count == 2 + + @pytest.mark.asyncio async def test_batch_write_async( transport: str = "grpc_asyncio", request_type=spanner.BatchWriteRequest @@ -3931,7 +6546,8 @@ async def test_batch_write_async( # Establish that the underlying gRPC stub method was called. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == spanner.BatchWriteRequest() + request = spanner.BatchWriteRequest() + assert args[0] == request # Establish that the response is the type that we expect. message = await response.read() @@ -4166,6 +6782,7 @@ def test_create_session_rest(request_type): return_value = spanner.Session( name="name_value", creator_role="creator_role_value", + multiplexed=True, ) # Wrap the value into a proper Response obj @@ -4183,6 +6800,43 @@ def test_create_session_rest(request_type): assert isinstance(response, spanner.Session) assert response.name == "name_value" assert response.creator_role == "creator_role_value" + assert response.multiplexed is True + + +def test_create_session_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.create_session in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.create_session] = mock_rpc + + request = {} + client.create_session(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.create_session(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 def test_create_session_rest_required_fields(request_type=spanner.CreateSessionRequest): @@ -4193,11 +6847,7 @@ def test_create_session_rest_required_fields(request_type=spanner.CreateSessionR request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -4441,19 +7091,60 @@ def test_batch_create_sessions_rest(request_type): # Designate an appropriate value for the returned response. return_value = spanner.BatchCreateSessionsResponse() - # Wrap the value into a proper Response obj - response_value = Response() - response_value.status_code = 200 - # Convert return value to protobuf type - return_value = spanner.BatchCreateSessionsResponse.pb(return_value) - json_return_value = json_format.MessageToJson(return_value) + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = spanner.BatchCreateSessionsResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.batch_create_sessions(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, spanner.BatchCreateSessionsResponse) + + +def test_batch_create_sessions_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.batch_create_sessions + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.batch_create_sessions + ] = mock_rpc + + request = {} + client.batch_create_sessions(request) - response_value._content = json_return_value.encode("UTF-8") - req.return_value = response_value - response = client.batch_create_sessions(request) + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 - # Establish that the response is the type that we expect. - assert isinstance(response, spanner.BatchCreateSessionsResponse) + client.batch_create_sessions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 def test_batch_create_sessions_rest_required_fields( @@ -4467,11 +7158,7 @@ def test_batch_create_sessions_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -4727,6 +7414,7 @@ def test_get_session_rest(request_type): return_value = spanner.Session( name="name_value", creator_role="creator_role_value", + multiplexed=True, ) # Wrap the value into a proper Response obj @@ -4744,6 +7432,43 @@ def test_get_session_rest(request_type): assert isinstance(response, spanner.Session) assert response.name == "name_value" assert response.creator_role == "creator_role_value" + assert response.multiplexed is True + + +def test_get_session_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_session in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.get_session] = mock_rpc + + request = {} + client.get_session(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_session(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 def test_get_session_rest_required_fields(request_type=spanner.GetSessionRequest): @@ -4754,11 +7479,7 @@ def test_get_session_rest_required_fields(request_type=spanner.GetSessionRequest request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -5013,6 +7734,42 @@ def test_list_sessions_rest(request_type): assert response.next_page_token == "next_page_token_value" +def test_list_sessions_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.list_sessions in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.list_sessions] = mock_rpc + + request = {} + client.list_sessions(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_sessions(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_list_sessions_rest_required_fields(request_type=spanner.ListSessionsRequest): transport_class = transports.SpannerRestTransport @@ -5021,11 +7778,7 @@ def test_list_sessions_rest_required_fields(request_type=spanner.ListSessionsReq request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -5351,6 +8104,42 @@ def test_delete_session_rest(request_type): assert response is None +def test_delete_session_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.delete_session in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.delete_session] = mock_rpc + + request = {} + client.delete_session(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.delete_session(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_delete_session_rest_required_fields(request_type=spanner.DeleteSessionRequest): transport_class = transports.SpannerRestTransport @@ -5359,11 +8148,7 @@ def test_delete_session_rest_required_fields(request_type=spanner.DeleteSessionR request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -5606,6 +8391,42 @@ def test_execute_sql_rest(request_type): assert isinstance(response, result_set.ResultSet) +def test_execute_sql_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.execute_sql in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.execute_sql] = mock_rpc + + request = {} + client.execute_sql(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.execute_sql(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_execute_sql_rest_required_fields(request_type=spanner.ExecuteSqlRequest): transport_class = transports.SpannerRestTransport @@ -5615,11 +8436,7 @@ def test_execute_sql_rest_required_fields(request_type=spanner.ExecuteSqlRequest request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -5838,6 +8655,47 @@ def test_execute_streaming_sql_rest(request_type): assert response.resume_token == b"resume_token_blob" +def test_execute_streaming_sql_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.execute_streaming_sql + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.execute_streaming_sql + ] = mock_rpc + + request = {} + client.execute_streaming_sql(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.execute_streaming_sql(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_execute_streaming_sql_rest_required_fields( request_type=spanner.ExecuteSqlRequest, ): @@ -5849,11 +8707,7 @@ def test_execute_streaming_sql_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -6066,6 +8920,44 @@ def test_execute_batch_dml_rest(request_type): assert isinstance(response, spanner.ExecuteBatchDmlResponse) +def test_execute_batch_dml_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.execute_batch_dml in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.execute_batch_dml + ] = mock_rpc + + request = {} + client.execute_batch_dml(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.execute_batch_dml(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_execute_batch_dml_rest_required_fields( request_type=spanner.ExecuteBatchDmlRequest, ): @@ -6077,11 +8969,7 @@ def test_execute_batch_dml_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -6292,6 +9180,42 @@ def test_read_rest(request_type): assert isinstance(response, result_set.ResultSet) +def test_read_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.read in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.read] = mock_rpc + + request = {} + client.read(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.read(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_read_rest_required_fields(request_type=spanner.ReadRequest): transport_class = transports.SpannerRestTransport @@ -6302,11 +9226,7 @@ def test_read_rest_required_fields(request_type=spanner.ReadRequest): request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -6530,6 +9450,42 @@ def test_streaming_read_rest(request_type): assert response.resume_token == b"resume_token_blob" +def test_streaming_read_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.streaming_read in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.streaming_read] = mock_rpc + + request = {} + client.streaming_read(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.streaming_read(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_streaming_read_rest_required_fields(request_type=spanner.ReadRequest): transport_class = transports.SpannerRestTransport @@ -6540,11 +9496,7 @@ def test_streaming_read_rest_required_fields(request_type=spanner.ReadRequest): request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -6765,6 +9717,44 @@ def test_begin_transaction_rest(request_type): assert response.id == b"id_blob" +def test_begin_transaction_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.begin_transaction in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.begin_transaction + ] = mock_rpc + + request = {} + client.begin_transaction(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.begin_transaction(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_begin_transaction_rest_required_fields( request_type=spanner.BeginTransactionRequest, ): @@ -6775,11 +9765,7 @@ def test_begin_transaction_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -7056,6 +10042,42 @@ def test_commit_rest(request_type): assert isinstance(response, commit_response.CommitResponse) +def test_commit_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.commit in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.commit] = mock_rpc + + request = {} + client.commit(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.commit(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_commit_rest_required_fields(request_type=spanner.CommitRequest): transport_class = transports.SpannerRestTransport @@ -7064,11 +10086,7 @@ def test_commit_rest_required_fields(request_type=spanner.CommitRequest): request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -7335,6 +10353,42 @@ def test_rollback_rest(request_type): assert response is None +def test_rollback_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.rollback in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.rollback] = mock_rpc + + request = {} + client.rollback(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.rollback(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_rollback_rest_required_fields(request_type=spanner.RollbackRequest): transport_class = transports.SpannerRestTransport @@ -7344,11 +10398,7 @@ def test_rollback_rest_required_fields(request_type=spanner.RollbackRequest): request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -7605,6 +10655,42 @@ def test_partition_query_rest(request_type): assert isinstance(response, spanner.PartitionResponse) +def test_partition_query_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.partition_query in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.partition_query] = mock_rpc + + request = {} + client.partition_query(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.partition_query(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_partition_query_rest_required_fields( request_type=spanner.PartitionQueryRequest, ): @@ -7616,11 +10702,7 @@ def test_partition_query_rest_required_fields( request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -7829,6 +10911,42 @@ def test_partition_read_rest(request_type): assert isinstance(response, spanner.PartitionResponse) +def test_partition_read_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.partition_read in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.partition_read] = mock_rpc + + request = {} + client.partition_read(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.partition_read(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_partition_read_rest_required_fields(request_type=spanner.PartitionReadRequest): transport_class = transports.SpannerRestTransport @@ -7838,11 +10956,7 @@ def test_partition_read_rest_required_fields(request_type=spanner.PartitionReadR request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -8062,6 +11176,42 @@ def test_batch_write_rest(request_type): assert response.indexes == [752] +def test_batch_write_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = SpannerClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.batch_write in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.batch_write] = mock_rpc + + request = {} + client.batch_write(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.batch_write(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + def test_batch_write_rest_required_fields(request_type=spanner.BatchWriteRequest): transport_class = transports.SpannerRestTransport @@ -8070,11 +11220,7 @@ def test_batch_write_rest_required_fields(request_type=spanner.BatchWriteRequest request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( - json_format.MessageToJson( - pb_request, - including_default_value_fields=False, - use_integers_for_enums=False, - ) + json_format.MessageToJson(pb_request, use_integers_for_enums=False) ) # verify fields with default values are dropped @@ -8359,7 +11505,7 @@ def test_credentials_transport_error(): ) # It is an error to provide an api_key and a credential. - options = mock.Mock() + options = client_options.ClientOptions() options.api_key = "api_key" with pytest.raises(ValueError): client = SpannerClient( @@ -9166,7 +12312,9 @@ def test_api_key_credentials(client_class, transport_class): patched.assert_called_once_with( credentials=mock_cred, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), scopes=None, client_cert_source_for_mtls=None, quota_project_id=None, diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index 8fb5b13a9a..174e5116c2 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -490,7 +490,7 @@ def test_list_instance_configs(self): from google.cloud.spanner_admin_instance_v1 import ListInstanceConfigsRequest from google.cloud.spanner_admin_instance_v1 import ListInstanceConfigsResponse - api = InstanceAdminClient(credentials=mock.Mock()) + api = InstanceAdminClient() credentials = _make_credentials() client = self._make_one(project=self.PROJECT, credentials=credentials) client._instance_admin_api = api @@ -537,7 +537,7 @@ def test_list_instance_configs_w_options(self): from google.cloud.spanner_admin_instance_v1 import ListInstanceConfigsRequest from google.cloud.spanner_admin_instance_v1 import ListInstanceConfigsResponse - api = InstanceAdminClient(credentials=mock.Mock()) + api = InstanceAdminClient() credentials = _make_credentials() client = self._make_one(project=self.PROJECT, credentials=credentials) client._instance_admin_api = api @@ -613,7 +613,7 @@ def test_list_instances(self): from google.cloud.spanner_admin_instance_v1 import ListInstancesRequest from google.cloud.spanner_admin_instance_v1 import ListInstancesResponse - api = InstanceAdminClient(credentials=mock.Mock()) + api = InstanceAdminClient() credentials = _make_credentials() client = self._make_one(project=self.PROJECT, credentials=credentials) client._instance_admin_api = api @@ -661,7 +661,7 @@ def test_list_instances_w_options(self): from google.cloud.spanner_admin_instance_v1 import ListInstancesRequest from google.cloud.spanner_admin_instance_v1 import ListInstancesResponse - api = InstanceAdminClient(credentials=mock.Mock()) + api = InstanceAdminClient() credentials = _make_credentials() client = self._make_one(project=self.PROJECT, credentials=credentials) client._instance_admin_api = api diff --git a/tests/unit/test_instance.py b/tests/unit/test_instance.py index 2313ee3131..f42bbe1db9 100644 --- a/tests/unit/test_instance.py +++ b/tests/unit/test_instance.py @@ -582,7 +582,7 @@ def test_list_databases(self): from google.cloud.spanner_admin_database_v1 import ListDatabasesRequest from google.cloud.spanner_admin_database_v1 import ListDatabasesResponse - api = DatabaseAdminClient(credentials=mock.Mock()) + api = DatabaseAdminClient() client = _Client(self.PROJECT) client.database_admin_api = api instance = self._make_one(self.INSTANCE_ID, client) @@ -621,7 +621,7 @@ def test_list_databases_w_options(self): from google.cloud.spanner_admin_database_v1 import ListDatabasesRequest from google.cloud.spanner_admin_database_v1 import ListDatabasesResponse - api = DatabaseAdminClient(credentials=mock.Mock()) + api = DatabaseAdminClient() client = _Client(self.PROJECT) client.database_admin_api = api instance = self._make_one(self.INSTANCE_ID, client) @@ -700,7 +700,7 @@ def test_list_backups_defaults(self): from google.cloud.spanner_admin_database_v1 import ListBackupsRequest from google.cloud.spanner_admin_database_v1 import ListBackupsResponse - api = DatabaseAdminClient(credentials=mock.Mock()) + api = DatabaseAdminClient() client = _Client(self.PROJECT) client.database_admin_api = api instance = self._make_one(self.INSTANCE_ID, client) @@ -739,7 +739,7 @@ def test_list_backups_w_options(self): from google.cloud.spanner_admin_database_v1 import ListBackupsRequest from google.cloud.spanner_admin_database_v1 import ListBackupsResponse - api = DatabaseAdminClient(credentials=mock.Mock()) + api = DatabaseAdminClient() client = _Client(self.PROJECT) client.database_admin_api = api instance = self._make_one(self.INSTANCE_ID, client) @@ -783,7 +783,7 @@ def test_list_backup_operations_defaults(self): from google.longrunning import operations_pb2 from google.protobuf.any_pb2 import Any - api = DatabaseAdminClient(credentials=mock.Mock()) + api = DatabaseAdminClient() client = _Client(self.PROJECT) client.database_admin_api = api instance = self._make_one(self.INSTANCE_ID, client) @@ -828,7 +828,7 @@ def test_list_backup_operations_w_options(self): from google.longrunning import operations_pb2 from google.protobuf.any_pb2 import Any - api = DatabaseAdminClient(credentials=mock.Mock()) + api = DatabaseAdminClient() client = _Client(self.PROJECT) client.database_admin_api = api instance = self._make_one(self.INSTANCE_ID, client) @@ -880,7 +880,7 @@ def test_list_database_operations_defaults(self): from google.longrunning import operations_pb2 from google.protobuf.any_pb2 import Any - api = DatabaseAdminClient(credentials=mock.Mock()) + api = DatabaseAdminClient() client = _Client(self.PROJECT) client.database_admin_api = api instance = self._make_one(self.INSTANCE_ID, client) @@ -937,7 +937,7 @@ def test_list_database_operations_w_options(self): from google.longrunning import operations_pb2 from google.protobuf.any_pb2 import Any - api = DatabaseAdminClient(credentials=mock.Mock()) + api = DatabaseAdminClient() client = _Client(self.PROJECT) client.database_admin_api = api instance = self._make_one(self.INSTANCE_ID, client) From 116474318d42a6f1ea0f9c2f82707e5dde281159 Mon Sep 17 00:00:00 2001 From: gesoges0 Date: Thu, 2 May 2024 16:23:26 +0900 Subject: [PATCH 2/3] docs: remove duplicate paramter description (#1052) Co-authored-by: Sri Harsha CH <57220027+harshachinta@users.noreply.github.com> From a9182a0be72b22a8ab1d6fc95f5f8a6c04af489e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 01:06:24 -0700 Subject: [PATCH 3/3] chore(main): release 3.46.0 (#1135) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 12 ++++++++++++ .../cloud/spanner_admin_database_v1/gapic_version.py | 2 +- .../cloud/spanner_admin_instance_v1/gapic_version.py | 2 +- google/cloud/spanner_v1/gapic_version.py | 2 +- ...et_metadata_google.spanner.admin.database.v1.json | 2 +- ...et_metadata_google.spanner.admin.instance.v1.json | 2 +- .../snippet_metadata_google.spanner.v1.json | 2 +- 8 files changed, 19 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8dac71dc4a..77356c567b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.45.0" + ".": "3.46.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dceb4eaa6..358133ef1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ [1]: https://pypi.org/project/google-cloud-spanner/#history +## [3.46.0](https://github.com/googleapis/python-spanner/compare/v3.45.0...v3.46.0) (2024-05-02) + + +### Features + +* **spanner:** Adding EXPECTED_FULFILLMENT_PERIOD to the indicate instance creation times (with FULFILLMENT_PERIOD_NORMAL or FULFILLMENT_PERIOD_EXTENDED ENUM) with the extended instance creation time triggered by On-Demand Capacity Feature ([293ecda](https://github.com/googleapis/python-spanner/commit/293ecdad78b51f248f8d5c023bdba3bac998ea5c)) + + +### Documentation + +* Remove duplicate paramter description ([#1052](https://github.com/googleapis/python-spanner/issues/1052)) ([1164743](https://github.com/googleapis/python-spanner/commit/116474318d42a6f1ea0f9c2f82707e5dde281159)) + ## [3.45.0](https://github.com/googleapis/python-spanner/compare/v3.44.0...v3.45.0) (2024-04-17) diff --git a/google/cloud/spanner_admin_database_v1/gapic_version.py b/google/cloud/spanner_admin_database_v1/gapic_version.py index 2e808494c6..4d1f04f803 100644 --- a/google/cloud/spanner_admin_database_v1/gapic_version.py +++ b/google/cloud/spanner_admin_database_v1/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "3.45.0" # {x-release-please-version} +__version__ = "3.46.0" # {x-release-please-version} diff --git a/google/cloud/spanner_admin_instance_v1/gapic_version.py b/google/cloud/spanner_admin_instance_v1/gapic_version.py index 2e808494c6..4d1f04f803 100644 --- a/google/cloud/spanner_admin_instance_v1/gapic_version.py +++ b/google/cloud/spanner_admin_instance_v1/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "3.45.0" # {x-release-please-version} +__version__ = "3.46.0" # {x-release-please-version} diff --git a/google/cloud/spanner_v1/gapic_version.py b/google/cloud/spanner_v1/gapic_version.py index 2e808494c6..4d1f04f803 100644 --- a/google/cloud/spanner_v1/gapic_version.py +++ b/google/cloud/spanner_v1/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "3.45.0" # {x-release-please-version} +__version__ = "3.46.0" # {x-release-please-version} diff --git a/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json b/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json index 11932ae5e8..f0df60123f 100644 --- a/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json +++ b/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-spanner-admin-database", - "version": "0.1.0" + "version": "3.46.0" }, "snippets": [ { diff --git a/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json b/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json index 0811b451cb..89fcfef090 100644 --- a/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json +++ b/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-spanner-admin-instance", - "version": "0.1.0" + "version": "3.46.0" }, "snippets": [ { diff --git a/samples/generated_samples/snippet_metadata_google.spanner.v1.json b/samples/generated_samples/snippet_metadata_google.spanner.v1.json index 4384d19e2a..b6e649ec8a 100644 --- a/samples/generated_samples/snippet_metadata_google.spanner.v1.json +++ b/samples/generated_samples/snippet_metadata_google.spanner.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-spanner", - "version": "0.1.0" + "version": "3.46.0" }, "snippets": [ {