From 817b3149fa12b3c4f77eb7405a698faed7fd3e91 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Jan 2023 16:36:39 +0000 Subject: [PATCH 1/9] chore(deps): update dependency google-cloud-bigquery-migration to v0.9.1 (#163) --- samples/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt index 3dae9dd..9816067 100644 --- a/samples/snippets/requirements.txt +++ b/samples/snippets/requirements.txt @@ -1 +1 @@ -google-cloud-bigquery-migration==0.9.0 +google-cloud-bigquery-migration==0.9.1 From 0216d5df9e042b5f023bba5e140615e3bc3006bf Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 25 Jan 2023 10:53:39 -0500 Subject: [PATCH 2/9] chore: Update gapic-generator-python to v1.8.2 (#164) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: Update gapic-generator-python to v1.8.2 PiperOrigin-RevId: 504289125 Source-Link: https://github.com/googleapis/googleapis/commit/38a48a44a44279e9cf9f2f864b588958a2d87491 Source-Link: https://github.com/googleapis/googleapis-gen/commit/b2dc22663dbe47a972c8d8c2f8a4df013dafdcbc Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiYjJkYzIyNjYzZGJlNDdhOTcyYzhkOGMyZjhhNGRmMDEzZGFmZGNiYyJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot --- .coveragerc | 1 + google/cloud/bigquery_migration_v2/__init__.py | 2 +- google/cloud/bigquery_migration_v2alpha/__init__.py | 2 +- .../snippet_metadata_google.cloud.bigquery.migration.v2.json | 2 +- ...nippet_metadata_google.cloud.bigquery.migration.v2alpha.json | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.coveragerc b/.coveragerc index 41f143a..c16fcf7 100644 --- a/.coveragerc +++ b/.coveragerc @@ -5,6 +5,7 @@ branch = True show_missing = True omit = google/cloud/bigquery_migration/__init__.py + google/cloud/bigquery_migration/gapic_version.py exclude_lines = # Re-enable the standard pragma pragma: NO COVER diff --git a/google/cloud/bigquery_migration_v2/__init__.py b/google/cloud/bigquery_migration_v2/__init__.py index e9496c7..3fcc7b4 100644 --- a/google/cloud/bigquery_migration_v2/__init__.py +++ b/google/cloud/bigquery_migration_v2/__init__.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from google.cloud.bigquery_migration import gapic_version as package_version +from google.cloud.bigquery_migration_v2 import gapic_version as package_version __version__ = package_version.__version__ diff --git a/google/cloud/bigquery_migration_v2alpha/__init__.py b/google/cloud/bigquery_migration_v2alpha/__init__.py index 46a41b2..6ac3802 100644 --- a/google/cloud/bigquery_migration_v2alpha/__init__.py +++ b/google/cloud/bigquery_migration_v2alpha/__init__.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from google.cloud.bigquery_migration import gapic_version as package_version +from google.cloud.bigquery_migration_v2alpha import gapic_version as package_version __version__ = package_version.__version__ diff --git a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2.json b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2.json index db3a813..eb49516 100644 --- a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2.json +++ b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-bigquery-migration", - "version": "0.9.1" + "version": "0.1.0" }, "snippets": [ { diff --git a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json index aaeb61e..b95cbec 100644 --- a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json +++ b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-bigquery-migration", - "version": "0.9.1" + "version": "0.1.0" }, "snippets": [ { From add7b8faf2e80fc512087e8ff5baf875514496b3 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 16:48:24 +0000 Subject: [PATCH 3/9] chore: fix prerelease_deps nox session [autoapprove] (#165) Source-Link: https://togithub.com/googleapis/synthtool/commit/26c7505b2f76981ec1707b851e1595c8c06e90fc Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:f946c75373c2b0040e8e318c5e85d0cf46bc6e61d0a01f3ef94d8de974ac6790 --- .github/.OwlBot.lock.yaml | 2 +- noxfile.py | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 889f77d..f0f3b24 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest - digest: sha256:c43f1d918bcf817d337aa29ff833439494a158a0831508fda4ec75dc4c0d0320 + digest: sha256:f946c75373c2b0040e8e318c5e85d0cf46bc6e61d0a01f3ef94d8de974ac6790 diff --git a/noxfile.py b/noxfile.py index e716318..95e58c5 100644 --- a/noxfile.py +++ b/noxfile.py @@ -189,9 +189,9 @@ def unit(session): def install_systemtest_dependencies(session, *constraints): # Use pre-release gRPC for system tests. - # Exclude version 1.49.0rc1 which has a known issue. - # See https://github.com/grpc/grpc/pull/30642 - session.install("--pre", "grpcio!=1.49.0rc1") + # Exclude version 1.52.0rc1 which has a known issue. + # See https://github.com/grpc/grpc/issues/32163 + session.install("--pre", "grpcio!=1.52.0rc1") session.install(*SYSTEM_TEST_STANDARD_DEPENDENCIES, *constraints) @@ -346,9 +346,7 @@ def prerelease_deps(session): unit_deps_all = UNIT_TEST_STANDARD_DEPENDENCIES + UNIT_TEST_EXTERNAL_DEPENDENCIES session.install(*unit_deps_all) system_deps_all = ( - SYSTEM_TEST_STANDARD_DEPENDENCIES - + SYSTEM_TEST_EXTERNAL_DEPENDENCIES - + SYSTEM_TEST_EXTRAS + SYSTEM_TEST_STANDARD_DEPENDENCIES + SYSTEM_TEST_EXTERNAL_DEPENDENCIES ) session.install(*system_deps_all) @@ -378,8 +376,8 @@ def prerelease_deps(session): # dependency of grpc "six", "googleapis-common-protos", - # Exclude version 1.49.0rc1 which has a known issue. See https://github.com/grpc/grpc/pull/30642 - "grpcio!=1.49.0rc1", + # Exclude version 1.52.0rc1 which has a known issue. See https://github.com/grpc/grpc/issues/32163 + "grpcio!=1.52.0rc1", "grpcio-status", "google-api-core", "proto-plus", From 29d8752b65c3b78a4ce69b3b7f12752793d32986 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 06:39:01 -0500 Subject: [PATCH 4/9] chore: Update gapic-generator-python to v1.8.4 (#166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: Update gapic-generator-python to v1.8.4 PiperOrigin-RevId: 507808936 Source-Link: https://github.com/googleapis/googleapis/commit/64cf8492b21778ce62c66ecee81b468a293bfd4c Source-Link: https://github.com/googleapis/googleapis-gen/commit/53c48cac153d3b37f3d2c2dec4830cfd91ec4153 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiNTNjNDhjYWMxNTNkM2IzN2YzZDJjMmRlYzQ4MzBjZmQ5MWVjNDE1MyJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- setup.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 380a9c3..37c47de 100644 --- a/setup.py +++ b/setup.py @@ -57,9 +57,7 @@ if package.startswith("google") ] -namespaces = ["google"] -if "google.cloud" in packages: - namespaces.append("google.cloud") +namespaces = ["google", "google.cloud"] setuptools.setup( name=name, From c311185b90e55685506ce7d53f8a37f5cb8ceff5 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:20:41 +0000 Subject: [PATCH 5/9] build(deps): bump cryptography from 38.0.3 to 39.0.1 in /synthtool/gcp/templates/python_library/.kokoro (#167) Source-Link: https://togithub.com/googleapis/synthtool/commit/bb171351c3946d3c3c32e60f5f18cee8c464ec51 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:f62c53736eccb0c4934a3ea9316e0d57696bb49c1a7c86c726e9bb8a2f87dadf --- .github/.OwlBot.lock.yaml | 2 +- .kokoro/requirements.txt | 49 ++++++++++++++++++--------------------- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index f0f3b24..894fb6b 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest - digest: sha256:f946c75373c2b0040e8e318c5e85d0cf46bc6e61d0a01f3ef94d8de974ac6790 + digest: sha256:f62c53736eccb0c4934a3ea9316e0d57696bb49c1a7c86c726e9bb8a2f87dadf diff --git a/.kokoro/requirements.txt b/.kokoro/requirements.txt index 05dc467..096e480 100644 --- a/.kokoro/requirements.txt +++ b/.kokoro/requirements.txt @@ -113,33 +113,28 @@ commonmark==0.9.1 \ --hash=sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60 \ --hash=sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9 # via rich -cryptography==38.0.3 \ - --hash=sha256:068147f32fa662c81aebab95c74679b401b12b57494872886eb5c1139250ec5d \ - --hash=sha256:06fc3cc7b6f6cca87bd56ec80a580c88f1da5306f505876a71c8cfa7050257dd \ - --hash=sha256:25c1d1f19729fb09d42e06b4bf9895212292cb27bb50229f5aa64d039ab29146 \ - --hash=sha256:402852a0aea73833d982cabb6d0c3bb582c15483d29fb7085ef2c42bfa7e38d7 \ - --hash=sha256:4e269dcd9b102c5a3d72be3c45d8ce20377b8076a43cbed6f660a1afe365e436 \ - --hash=sha256:5419a127426084933076132d317911e3c6eb77568a1ce23c3ac1e12d111e61e0 \ - --hash=sha256:554bec92ee7d1e9d10ded2f7e92a5d70c1f74ba9524947c0ba0c850c7b011828 \ - --hash=sha256:5e89468fbd2fcd733b5899333bc54d0d06c80e04cd23d8c6f3e0542358c6060b \ - --hash=sha256:65535bc550b70bd6271984d9863a37741352b4aad6fb1b3344a54e6950249b55 \ - --hash=sha256:6ab9516b85bebe7aa83f309bacc5f44a61eeb90d0b4ec125d2d003ce41932d36 \ - --hash=sha256:6addc3b6d593cd980989261dc1cce38263c76954d758c3c94de51f1e010c9a50 \ - --hash=sha256:728f2694fa743a996d7784a6194da430f197d5c58e2f4e278612b359f455e4a2 \ - --hash=sha256:785e4056b5a8b28f05a533fab69febf5004458e20dad7e2e13a3120d8ecec75a \ - --hash=sha256:78cf5eefac2b52c10398a42765bfa981ce2372cbc0457e6bf9658f41ec3c41d8 \ - --hash=sha256:7f836217000342d448e1c9a342e9163149e45d5b5eca76a30e84503a5a96cab0 \ - --hash=sha256:8d41a46251bf0634e21fac50ffd643216ccecfaf3701a063257fe0b2be1b6548 \ - --hash=sha256:984fe150f350a3c91e84de405fe49e688aa6092b3525f407a18b9646f6612320 \ - --hash=sha256:9b24bcff7853ed18a63cfb0c2b008936a9554af24af2fb146e16d8e1aed75748 \ - --hash=sha256:b1b35d9d3a65542ed2e9d90115dfd16bbc027b3f07ee3304fc83580f26e43249 \ - --hash=sha256:b1b52c9e5f8aa2b802d48bd693190341fae201ea51c7a167d69fc48b60e8a959 \ - --hash=sha256:bbf203f1a814007ce24bd4d51362991d5cb90ba0c177a9c08825f2cc304d871f \ - --hash=sha256:be243c7e2bfcf6cc4cb350c0d5cdf15ca6383bbcb2a8ef51d3c9411a9d4386f0 \ - --hash=sha256:bfbe6ee19615b07a98b1d2287d6a6073f734735b49ee45b11324d85efc4d5cbd \ - --hash=sha256:c46837ea467ed1efea562bbeb543994c2d1f6e800785bd5a2c98bc096f5cb220 \ - --hash=sha256:dfb4f4dd568de1b6af9f4cda334adf7d72cf5bc052516e1b2608b683375dd95c \ - --hash=sha256:ed7b00096790213e09eb11c97cc6e2b757f15f3d2f85833cd2d3ec3fe37c1722 +cryptography==39.0.1 \ + --hash=sha256:0f8da300b5c8af9f98111ffd512910bc792b4c77392a9523624680f7956a99d4 \ + --hash=sha256:35f7c7d015d474f4011e859e93e789c87d21f6f4880ebdc29896a60403328f1f \ + --hash=sha256:5aa67414fcdfa22cf052e640cb5ddc461924a045cacf325cd164e65312d99502 \ + --hash=sha256:5d2d8b87a490bfcd407ed9d49093793d0f75198a35e6eb1a923ce1ee86c62b41 \ + --hash=sha256:6687ef6d0a6497e2b58e7c5b852b53f62142cfa7cd1555795758934da363a965 \ + --hash=sha256:6f8ba7f0328b79f08bdacc3e4e66fb4d7aab0c3584e0bd41328dce5262e26b2e \ + --hash=sha256:706843b48f9a3f9b9911979761c91541e3d90db1ca905fd63fee540a217698bc \ + --hash=sha256:807ce09d4434881ca3a7594733669bd834f5b2c6d5c7e36f8c00f691887042ad \ + --hash=sha256:83e17b26de248c33f3acffb922748151d71827d6021d98c70e6c1a25ddd78505 \ + --hash=sha256:96f1157a7c08b5b189b16b47bc9db2332269d6680a196341bf30046330d15388 \ + --hash=sha256:aec5a6c9864be7df2240c382740fcf3b96928c46604eaa7f3091f58b878c0bb6 \ + --hash=sha256:b0afd054cd42f3d213bf82c629efb1ee5f22eba35bf0eec88ea9ea7304f511a2 \ + --hash=sha256:ced4e447ae29ca194449a3f1ce132ded8fcab06971ef5f618605aacaa612beac \ + --hash=sha256:d1f6198ee6d9148405e49887803907fe8962a23e6c6f83ea7d98f1c0de375695 \ + --hash=sha256:e124352fd3db36a9d4a21c1aa27fd5d051e621845cb87fb851c08f4f75ce8be6 \ + --hash=sha256:e422abdec8b5fa8462aa016786680720d78bdce7a30c652b7fadf83a4ba35336 \ + --hash=sha256:ef8b72fa70b348724ff1218267e7f7375b8de4e8194d1636ee60510aae104cd0 \ + --hash=sha256:f0c64d1bd842ca2633e74a1a28033d139368ad959872533b1bab8c80e8240a0c \ + --hash=sha256:f24077a3b5298a5a06a8e0536e3ea9ec60e4c7ac486755e5fb6e6ea9b3500106 \ + --hash=sha256:fdd188c8a6ef8769f148f88f859884507b954cc64db6b52f66ef199bb9ad660a \ + --hash=sha256:fe913f20024eb2cb2f323e42a64bdf2911bb9738a15dba7d3cce48151034e3a8 # via # gcp-releasetool # secretstorage From 30bfffd50a25795c08efb91f213547bf63ebde1a Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:10:30 +0000 Subject: [PATCH 6/9] chore(python): upgrade gcp-releasetool in .kokoro [autoapprove] (#169) Source-Link: https://togithub.com/googleapis/synthtool/commit/5f2a6089f73abf06238fe4310f6a14d6f6d1eed3 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:8555f0e37e6261408f792bfd6635102d2da5ad73f8f09bcb24f25e6afb5fac97 --- .github/.OwlBot.lock.yaml | 2 +- .kokoro/requirements.in | 2 +- .kokoro/requirements.txt | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 894fb6b..5fc5daa 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest - digest: sha256:f62c53736eccb0c4934a3ea9316e0d57696bb49c1a7c86c726e9bb8a2f87dadf + digest: sha256:8555f0e37e6261408f792bfd6635102d2da5ad73f8f09bcb24f25e6afb5fac97 diff --git a/.kokoro/requirements.in b/.kokoro/requirements.in index cbd7e77..882178c 100644 --- a/.kokoro/requirements.in +++ b/.kokoro/requirements.in @@ -1,5 +1,5 @@ gcp-docuploader -gcp-releasetool +gcp-releasetool>=1.10.5 # required for compatibility with cryptography>=39.x importlib-metadata typing-extensions twine diff --git a/.kokoro/requirements.txt b/.kokoro/requirements.txt index 096e480..fa99c12 100644 --- a/.kokoro/requirements.txt +++ b/.kokoro/requirements.txt @@ -154,9 +154,9 @@ gcp-docuploader==0.6.4 \ --hash=sha256:01486419e24633af78fd0167db74a2763974765ee8078ca6eb6964d0ebd388af \ --hash=sha256:70861190c123d907b3b067da896265ead2eeb9263969d6955c9e0bb091b5ccbf # via -r requirements.in -gcp-releasetool==1.10.0 \ - --hash=sha256:72a38ca91b59c24f7e699e9227c90cbe4dd71b789383cb0164b088abae294c83 \ - --hash=sha256:8c7c99320208383d4bb2b808c6880eb7a81424afe7cdba3c8d84b25f4f0e097d +gcp-releasetool==1.10.5 \ + --hash=sha256:174b7b102d704b254f2a26a3eda2c684fd3543320ec239baf771542a2e58e109 \ + --hash=sha256:e29d29927fe2ca493105a82958c6873bb2b90d503acac56be2c229e74de0eec9 # via -r requirements.in google-api-core==2.10.2 \ --hash=sha256:10c06f7739fe57781f87523375e8e1a3a4674bf6392cd6131a3222182b971320 \ From 5a133879e363b0a31659f428269c526237c4c1cd Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 11:38:15 -0500 Subject: [PATCH 7/9] chore: Update gapic-generator-python to v1.8.5 (#168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: Update gapic-generator-python to v1.8.5 PiperOrigin-RevId: 511892190 Source-Link: https://github.com/googleapis/googleapis/commit/a45d9c09c1287ffdf938f4e8083e791046c0b23b Source-Link: https://github.com/googleapis/googleapis-gen/commit/1907294b1d8365ea24f8c5f2e059a64124c4ed3b Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiMTkwNzI5NGIxZDgzNjVlYTI0ZjhjNWYyZTA1OWE2NDEyNGM0ZWQzYiJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot Co-authored-by: Anthonios Partheniou --- google/cloud/bigquery_migration_v2/types/migration_entities.py | 2 ++ .../bigquery_migration_v2/types/migration_error_details.py | 2 ++ google/cloud/bigquery_migration_v2/types/migration_metrics.py | 2 ++ google/cloud/bigquery_migration_v2/types/migration_service.py | 2 ++ google/cloud/bigquery_migration_v2/types/translation_config.py | 2 ++ .../cloud/bigquery_migration_v2alpha/types/assessment_task.py | 2 ++ .../bigquery_migration_v2alpha/types/migration_entities.py | 2 ++ .../bigquery_migration_v2alpha/types/migration_error_details.py | 2 ++ .../cloud/bigquery_migration_v2alpha/types/migration_metrics.py | 2 ++ .../cloud/bigquery_migration_v2alpha/types/migration_service.py | 2 ++ .../cloud/bigquery_migration_v2alpha/types/translation_task.py | 2 ++ 11 files changed, 22 insertions(+) diff --git a/google/cloud/bigquery_migration_v2/types/migration_entities.py b/google/cloud/bigquery_migration_v2/types/migration_entities.py index 18e87f5..ae0baa4 100644 --- a/google/cloud/bigquery_migration_v2/types/migration_entities.py +++ b/google/cloud/bigquery_migration_v2/types/migration_entities.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence from google.protobuf import timestamp_pb2 # type: ignore diff --git a/google/cloud/bigquery_migration_v2/types/migration_error_details.py b/google/cloud/bigquery_migration_v2/types/migration_error_details.py index fab6bd4..ea6e3bf 100644 --- a/google/cloud/bigquery_migration_v2/types/migration_error_details.py +++ b/google/cloud/bigquery_migration_v2/types/migration_error_details.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence from google.rpc import error_details_pb2 # type: ignore diff --git a/google/cloud/bigquery_migration_v2/types/migration_metrics.py b/google/cloud/bigquery_migration_v2/types/migration_metrics.py index f0ad71e..04325a9 100644 --- a/google/cloud/bigquery_migration_v2/types/migration_metrics.py +++ b/google/cloud/bigquery_migration_v2/types/migration_metrics.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence from google.api import distribution_pb2 # type: ignore diff --git a/google/cloud/bigquery_migration_v2/types/migration_service.py b/google/cloud/bigquery_migration_v2/types/migration_service.py index 0b38c79..65d5699 100644 --- a/google/cloud/bigquery_migration_v2/types/migration_service.py +++ b/google/cloud/bigquery_migration_v2/types/migration_service.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence from google.protobuf import field_mask_pb2 # type: ignore diff --git a/google/cloud/bigquery_migration_v2/types/translation_config.py b/google/cloud/bigquery_migration_v2/types/translation_config.py index 6c495f1..741d9fe 100644 --- a/google/cloud/bigquery_migration_v2/types/translation_config.py +++ b/google/cloud/bigquery_migration_v2/types/translation_config.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence import proto # type: ignore diff --git a/google/cloud/bigquery_migration_v2alpha/types/assessment_task.py b/google/cloud/bigquery_migration_v2alpha/types/assessment_task.py index 62e96d4..8afeda4 100644 --- a/google/cloud/bigquery_migration_v2alpha/types/assessment_task.py +++ b/google/cloud/bigquery_migration_v2alpha/types/assessment_task.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence import proto # type: ignore diff --git a/google/cloud/bigquery_migration_v2alpha/types/migration_entities.py b/google/cloud/bigquery_migration_v2alpha/types/migration_entities.py index 14d6a20..909727f 100644 --- a/google/cloud/bigquery_migration_v2alpha/types/migration_entities.py +++ b/google/cloud/bigquery_migration_v2alpha/types/migration_entities.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence from google.protobuf import any_pb2 # type: ignore diff --git a/google/cloud/bigquery_migration_v2alpha/types/migration_error_details.py b/google/cloud/bigquery_migration_v2alpha/types/migration_error_details.py index b6b1b5b..eb52e15 100644 --- a/google/cloud/bigquery_migration_v2alpha/types/migration_error_details.py +++ b/google/cloud/bigquery_migration_v2alpha/types/migration_error_details.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence from google.rpc import error_details_pb2 # type: ignore diff --git a/google/cloud/bigquery_migration_v2alpha/types/migration_metrics.py b/google/cloud/bigquery_migration_v2alpha/types/migration_metrics.py index ba216c1..7702dbc 100644 --- a/google/cloud/bigquery_migration_v2alpha/types/migration_metrics.py +++ b/google/cloud/bigquery_migration_v2alpha/types/migration_metrics.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence from google.api import distribution_pb2 # type: ignore diff --git a/google/cloud/bigquery_migration_v2alpha/types/migration_service.py b/google/cloud/bigquery_migration_v2alpha/types/migration_service.py index d49c19a..2156b40 100644 --- a/google/cloud/bigquery_migration_v2alpha/types/migration_service.py +++ b/google/cloud/bigquery_migration_v2alpha/types/migration_service.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence from google.protobuf import field_mask_pb2 # type: ignore diff --git a/google/cloud/bigquery_migration_v2alpha/types/translation_task.py b/google/cloud/bigquery_migration_v2alpha/types/translation_task.py index 2c658c7..7a80697 100644 --- a/google/cloud/bigquery_migration_v2alpha/types/translation_task.py +++ b/google/cloud/bigquery_migration_v2alpha/types/translation_task.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from __future__ import annotations + from typing import MutableMapping, MutableSequence import proto # type: ignore From 533d1d87e3bfb917488550a979b35994ebe293ed Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 1 Mar 2023 05:00:39 -0500 Subject: [PATCH 8/9] feat(v2alpha): Add SQL translation service (#170) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add SQL translation service to Bazel generation PiperOrigin-RevId: 512937316 Source-Link: https://github.com/googleapis/googleapis/commit/178674c69aa54ec78f23b6a1a2af72e22131277f Source-Link: https://github.com/googleapis/googleapis-gen/commit/131f3271256e0a7a2ab96d42540ef05c9cacec7d Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiMTMxZjMyNzEyNTZlMGE3YTJhYjk2ZDQyNTQwZWYwNWM5Y2FjZWM3ZCJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- docs/bigquery_migration_v2alpha/services.rst | 1 + .../sql_translation_service.rst | 6 + .../bigquery_migration_v2alpha/__init__.py | 18 + .../gapic_metadata.json | 24 + .../sql_translation_service/__init__.py | 22 + .../sql_translation_service/async_client.py | 357 ++++ .../sql_translation_service/client.py | 568 ++++++ .../transports/__init__.py | 34 + .../transports/base.py | 158 ++ .../transports/grpc.py | 270 +++ .../transports/grpc_asyncio.py | 269 +++ .../types/__init__.py | 12 + .../types/translation_service.py | 202 ++ ...anslation_service_translate_query_async.py | 54 + ...ranslation_service_translate_query_sync.py | 54 + ...ogle.cloud.bigquery.migration.v2alpha.json | 177 ++ ...xup_bigquery_migration_v2alpha_keywords.py | 1 + .../test_sql_translation_service.py | 1655 +++++++++++++++++ 18 files changed, 3882 insertions(+) create mode 100644 docs/bigquery_migration_v2alpha/sql_translation_service.rst create mode 100644 google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/__init__.py create mode 100644 google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/async_client.py create mode 100644 google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/client.py create mode 100644 google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/__init__.py create mode 100644 google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/base.py create mode 100644 google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/grpc.py create mode 100644 google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/grpc_asyncio.py create mode 100644 google/cloud/bigquery_migration_v2alpha/types/translation_service.py create mode 100644 samples/generated_samples/bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_async.py create mode 100644 samples/generated_samples/bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_sync.py create mode 100644 tests/unit/gapic/bigquery_migration_v2alpha/test_sql_translation_service.py diff --git a/docs/bigquery_migration_v2alpha/services.rst b/docs/bigquery_migration_v2alpha/services.rst index 64b04ab..717bf41 100644 --- a/docs/bigquery_migration_v2alpha/services.rst +++ b/docs/bigquery_migration_v2alpha/services.rst @@ -4,3 +4,4 @@ Services for Google Cloud Bigquery Migration v2alpha API :maxdepth: 2 migration_service + sql_translation_service diff --git a/docs/bigquery_migration_v2alpha/sql_translation_service.rst b/docs/bigquery_migration_v2alpha/sql_translation_service.rst new file mode 100644 index 0000000..4d89dd2 --- /dev/null +++ b/docs/bigquery_migration_v2alpha/sql_translation_service.rst @@ -0,0 +1,6 @@ +SqlTranslationService +--------------------------------------- + +.. automodule:: google.cloud.bigquery_migration_v2alpha.services.sql_translation_service + :members: + :inherited-members: diff --git a/google/cloud/bigquery_migration_v2alpha/__init__.py b/google/cloud/bigquery_migration_v2alpha/__init__.py index 6ac3802..59bc57a 100644 --- a/google/cloud/bigquery_migration_v2alpha/__init__.py +++ b/google/cloud/bigquery_migration_v2alpha/__init__.py @@ -22,6 +22,10 @@ MigrationServiceAsyncClient, MigrationServiceClient, ) +from .services.sql_translation_service import ( + SqlTranslationServiceAsyncClient, + SqlTranslationServiceClient, +) from .types.assessment_task import ( AssessmentOrchestrationResultDetails, AssessmentTaskDetails, @@ -49,6 +53,13 @@ ListMigrationWorkflowsResponse, StartMigrationWorkflowRequest, ) +from .types.translation_service import ( + SqlTranslationError, + SqlTranslationErrorDetail, + SqlTranslationWarning, + TranslateQueryRequest, + TranslateQueryResponse, +) from .types.translation_task import ( BteqOptions, DatasetReference, @@ -61,6 +72,7 @@ __all__ = ( "MigrationServiceAsyncClient", + "SqlTranslationServiceAsyncClient", "AssessmentOrchestrationResultDetails", "AssessmentTaskDetails", "BteqOptions", @@ -84,10 +96,16 @@ "MigrationWorkflow", "Point", "ResourceErrorDetail", + "SqlTranslationError", + "SqlTranslationErrorDetail", + "SqlTranslationServiceClient", + "SqlTranslationWarning", "StartMigrationWorkflowRequest", "TeradataOptions", "TimeInterval", "TimeSeries", + "TranslateQueryRequest", + "TranslateQueryResponse", "TranslationFileMapping", "TranslationTaskDetails", "TypedValue", diff --git a/google/cloud/bigquery_migration_v2alpha/gapic_metadata.json b/google/cloud/bigquery_migration_v2alpha/gapic_metadata.json index 2cdac01..9eb915e 100644 --- a/google/cloud/bigquery_migration_v2alpha/gapic_metadata.json +++ b/google/cloud/bigquery_migration_v2alpha/gapic_metadata.json @@ -88,6 +88,30 @@ } } } + }, + "SqlTranslationService": { + "clients": { + "grpc": { + "libraryClient": "SqlTranslationServiceClient", + "rpcs": { + "TranslateQuery": { + "methods": [ + "translate_query" + ] + } + } + }, + "grpc-async": { + "libraryClient": "SqlTranslationServiceAsyncClient", + "rpcs": { + "TranslateQuery": { + "methods": [ + "translate_query" + ] + } + } + } + } } } } diff --git a/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/__init__.py b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/__init__.py new file mode 100644 index 0000000..84d4f60 --- /dev/null +++ b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# +from .async_client import SqlTranslationServiceAsyncClient +from .client import SqlTranslationServiceClient + +__all__ = ( + "SqlTranslationServiceClient", + "SqlTranslationServiceAsyncClient", +) diff --git a/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/async_client.py b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/async_client.py new file mode 100644 index 0000000..dee8faf --- /dev/null +++ b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/async_client.py @@ -0,0 +1,357 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# +from collections import OrderedDict +import functools +import re +from typing import ( + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core.client_options import ClientOptions +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.bigquery_migration_v2alpha import gapic_version as package_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.cloud.bigquery_migration_v2alpha.types import translation_service + +from .client import SqlTranslationServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, SqlTranslationServiceTransport +from .transports.grpc_asyncio import SqlTranslationServiceGrpcAsyncIOTransport + + +class SqlTranslationServiceAsyncClient: + """Provides other SQL dialects to GoogleSQL translation + operations. + """ + + _client: SqlTranslationServiceClient + + DEFAULT_ENDPOINT = SqlTranslationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = SqlTranslationServiceClient.DEFAULT_MTLS_ENDPOINT + + common_billing_account_path = staticmethod( + SqlTranslationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + SqlTranslationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(SqlTranslationServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + SqlTranslationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + SqlTranslationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + SqlTranslationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(SqlTranslationServiceClient.common_project_path) + parse_common_project_path = staticmethod( + SqlTranslationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + SqlTranslationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + SqlTranslationServiceClient.parse_common_location_path + ) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + SqlTranslationServiceAsyncClient: The constructed client. + """ + return SqlTranslationServiceClient.from_service_account_info.__func__(SqlTranslationServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + SqlTranslationServiceAsyncClient: The constructed client. + """ + return SqlTranslationServiceClient.from_service_account_file.__func__(SqlTranslationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """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 + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return SqlTranslationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> SqlTranslationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SqlTranslationServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + get_transport_class = functools.partial( + type(SqlTranslationServiceClient).get_transport_class, + type(SqlTranslationServiceClient), + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Union[str, SqlTranslationServiceTransport] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the sql translation service client. + + Args: + 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. + transport (Union[str, ~.SqlTranslationServiceTransport]): 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: + "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 + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client = SqlTranslationServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def translate_query( + self, + request: Optional[ + Union[translation_service.TranslateQueryRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + source_dialect: Optional[ + translation_service.TranslateQueryRequest.SqlTranslationSourceDialect + ] = None, + query: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> translation_service.TranslateQueryResponse: + r"""Translates input queries from source dialects to + GoogleSQL. + + .. 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 bigquery_migration_v2alpha + + async def sample_translate_query(): + # Create a client + client = bigquery_migration_v2alpha.SqlTranslationServiceAsyncClient() + + # Initialize request argument(s) + request = bigquery_migration_v2alpha.TranslateQueryRequest( + parent="parent_value", + source_dialect="TERADATA", + query="query_value", + ) + + # Make the request + response = await client.translate_query(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.bigquery_migration_v2alpha.types.TranslateQueryRequest, dict]]): + The request object. The request of translating a SQL + query to Standard SQL. + parent (:class:`str`): + Required. The name of the project to which this + translation request belongs. Example: + ``projects/foo/locations/bar`` + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + source_dialect (:class:`google.cloud.bigquery_migration_v2alpha.types.TranslateQueryRequest.SqlTranslationSourceDialect`): + Required. The source SQL dialect of ``queries``. + This corresponds to the ``source_dialect`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query (:class:`str`): + Required. The query to be translated. + This corresponds to the ``query`` 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.bigquery_migration_v2alpha.types.TranslateQueryResponse: + The response of translating a SQL + query to Standard SQL. + + """ + # 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, source_dialect, query]) + 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." + ) + + request = translation_service.TranslateQueryRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if source_dialect is not None: + request.source_dialect = source_dialect + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.translate_query, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # 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),)), + ) + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("SqlTranslationServiceAsyncClient",) diff --git a/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/client.py b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/client.py new file mode 100644 index 0000000..bbb37b6 --- /dev/null +++ b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/client.py @@ -0,0 +1,568 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.bigquery_migration_v2alpha import gapic_version as package_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.cloud.bigquery_migration_v2alpha.types import translation_service + +from .transports.base import DEFAULT_CLIENT_INFO, SqlTranslationServiceTransport +from .transports.grpc import SqlTranslationServiceGrpcTransport +from .transports.grpc_asyncio import SqlTranslationServiceGrpcAsyncIOTransport + + +class SqlTranslationServiceClientMeta(type): + """Metaclass for the SqlTranslationService client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = ( + OrderedDict() + ) # type: Dict[str, Type[SqlTranslationServiceTransport]] + _transport_registry["grpc"] = SqlTranslationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = SqlTranslationServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[SqlTranslationServiceTransport]: + """Returns an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class SqlTranslationServiceClient(metaclass=SqlTranslationServiceClientMeta): + """Provides other SQL dialects to GoogleSQL translation + operations. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + DEFAULT_ENDPOINT = "bigquerymigration.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + SqlTranslationServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + SqlTranslationServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> SqlTranslationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SqlTranslationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def common_billing_account_path( + billing_account: str, + ) -> str: + """Returns a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path( + folder: str, + ) -> str: + """Returns a fully-qualified folder string.""" + return "folders/{folder}".format( + folder=folder, + ) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path( + organization: str, + ) -> str: + """Returns a fully-qualified organization string.""" + return "organizations/{organization}".format( + organization=organization, + ) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path( + project: str, + ) -> str: + """Returns a fully-qualified project string.""" + return "projects/{project}".format( + project=project, + ) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path( + project: str, + location: str, + ) -> str: + """Returns a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @classmethod + 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. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + if client_options is None: + client_options = client_options_lib.ClientOptions() + use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + 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`" + ) + + # Figure out the client cert source to use. + client_cert_source = None + if use_client_cert == "true": + if client_options.client_cert_source: + client_cert_source = client_options.client_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + api_endpoint = cls.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = cls.DEFAULT_ENDPOINT + + return api_endpoint, client_cert_source + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, SqlTranslationServiceTransport]] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the sql translation service client. + + Args: + 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. + transport (Union[str, SqlTranslationServiceTransport]): 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: + "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 + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + 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. + """ + 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) + + api_endpoint, client_cert_source_func = self.get_mtls_endpoint_and_cert_source( + client_options + ) + + api_key_value = getattr(client_options, "api_key", None) + if api_key_value and credentials: + raise ValueError( + "client_options.api_key and credentials are mutually exclusive" + ) + + # 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, SqlTranslationServiceTransport): + # transport is a SqlTranslationServiceTransport instance. + if credentials or client_options.credentials_file or api_key_value: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + 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, + client_info=client_info, + always_use_jwt_access=True, + api_audience=client_options.api_audience, + ) + + def translate_query( + self, + request: Optional[ + Union[translation_service.TranslateQueryRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + source_dialect: Optional[ + translation_service.TranslateQueryRequest.SqlTranslationSourceDialect + ] = None, + query: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> translation_service.TranslateQueryResponse: + r"""Translates input queries from source dialects to + GoogleSQL. + + .. 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 bigquery_migration_v2alpha + + def sample_translate_query(): + # Create a client + client = bigquery_migration_v2alpha.SqlTranslationServiceClient() + + # Initialize request argument(s) + request = bigquery_migration_v2alpha.TranslateQueryRequest( + parent="parent_value", + source_dialect="TERADATA", + query="query_value", + ) + + # Make the request + response = client.translate_query(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.bigquery_migration_v2alpha.types.TranslateQueryRequest, dict]): + The request object. The request of translating a SQL + query to Standard SQL. + parent (str): + Required. The name of the project to which this + translation request belongs. Example: + ``projects/foo/locations/bar`` + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + source_dialect (google.cloud.bigquery_migration_v2alpha.types.TranslateQueryRequest.SqlTranslationSourceDialect): + Required. The source SQL dialect of ``queries``. + This corresponds to the ``source_dialect`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query (str): + Required. The query to be translated. + This corresponds to the ``query`` 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.bigquery_migration_v2alpha.types.TranslateQueryResponse: + The response of translating a SQL + query to Standard SQL. + + """ + # 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, source_dialect, query]) + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a translation_service.TranslateQueryRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, translation_service.TranslateQueryRequest): + request = translation_service.TranslateQueryRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if source_dialect is not None: + request.source_dialect = source_dialect + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.translate_query] + + # 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),)), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "SqlTranslationServiceClient": + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("SqlTranslationServiceClient",) diff --git a/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/__init__.py b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/__init__.py new file mode 100644 index 0000000..1467e7d --- /dev/null +++ b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# +from collections import OrderedDict +from typing import Dict, Type + +from .base import SqlTranslationServiceTransport +from .grpc import SqlTranslationServiceGrpcTransport +from .grpc_asyncio import SqlTranslationServiceGrpcAsyncIOTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[SqlTranslationServiceTransport]] +_transport_registry["grpc"] = SqlTranslationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = SqlTranslationServiceGrpcAsyncIOTransport + +__all__ = ( + "SqlTranslationServiceTransport", + "SqlTranslationServiceGrpcTransport", + "SqlTranslationServiceGrpcAsyncIOTransport", +) diff --git a/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/base.py b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/base.py new file mode 100644 index 0000000..63b8b68 --- /dev/null +++ b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# +import abc +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union + +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.bigquery_migration_v2alpha import gapic_version as package_version +from google.cloud.bigquery_migration_v2alpha.types import translation_service + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class SqlTranslationServiceTransport(abc.ABC): + """Abstract transport class for SqlTranslationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "bigquerymigration.googleapis.com" + + def __init__( + self, + *, + host: str = DEFAULT_HOST, + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + 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. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + 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. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.translate_query: gapic_v1.method.wrap_method( + self.translate_query, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def translate_query( + self, + ) -> Callable[ + [translation_service.TranslateQueryRequest], + Union[ + translation_service.TranslateQueryResponse, + Awaitable[translation_service.TranslateQueryResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("SqlTranslationServiceTransport",) diff --git a/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/grpc.py b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/grpc.py new file mode 100644 index 0000000..7b8890e --- /dev/null +++ b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/grpc.py @@ -0,0 +1,270 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# +from typing import Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, grpc_helpers +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +import grpc # type: ignore + +from google.cloud.bigquery_migration_v2alpha.types import translation_service + +from .base import DEFAULT_CLIENT_INFO, SqlTranslationServiceTransport + + +class SqlTranslationServiceGrpcTransport(SqlTranslationServiceTransport): + """gRPC backend transport for SqlTranslationService. + + Provides other SQL dialects to GoogleSQL translation + operations. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "bigquerymigration.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + 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. + 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 list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + 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 + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + 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. + 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. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + 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. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "bigquerymigration.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + 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 mutually exclusive with credentials. + 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`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def translate_query( + self, + ) -> Callable[ + [translation_service.TranslateQueryRequest], + translation_service.TranslateQueryResponse, + ]: + r"""Return a callable for the translate query method over gRPC. + + Translates input queries from source dialects to + GoogleSQL. + + Returns: + Callable[[~.TranslateQueryRequest], + ~.TranslateQueryResponse]: + 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 "translate_query" not in self._stubs: + self._stubs["translate_query"] = self.grpc_channel.unary_unary( + "/google.cloud.bigquery.migration.v2alpha.SqlTranslationService/TranslateQuery", + request_serializer=translation_service.TranslateQueryRequest.serialize, + response_deserializer=translation_service.TranslateQueryResponse.deserialize, + ) + return self._stubs["translate_query"] + + def close(self): + self.grpc_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("SqlTranslationServiceGrpcTransport",) diff --git a/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/grpc_asyncio.py b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/grpc_asyncio.py new file mode 100644 index 0000000..954d672 --- /dev/null +++ b/google/cloud/bigquery_migration_v2alpha/services/sql_translation_service/transports/grpc_asyncio.py @@ -0,0 +1,269 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +import grpc # type: ignore +from grpc.experimental import aio # type: ignore + +from google.cloud.bigquery_migration_v2alpha.types import translation_service + +from .base import DEFAULT_CLIENT_INFO, SqlTranslationServiceTransport +from .grpc import SqlTranslationServiceGrpcTransport + + +class SqlTranslationServiceGrpcAsyncIOTransport(SqlTranslationServiceTransport): + """gRPC AsyncIO backend transport for SqlTranslationService. + + Provides other SQL dialects to GoogleSQL translation + operations. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "bigquerymigration.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> aio.Channel: + """Create and return a gRPC AsyncIO channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + 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`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + aio.Channel: A gRPC AsyncIO channel object. + """ + + return grpc_helpers_async.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + def __init__( + self, + *, + host: str = "bigquerymigration.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + 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. + 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`. + channel (Optional[aio.Channel]): A ``Channel`` instance through + which to make calls. + 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 + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + 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. + 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. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + 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. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @property + def grpc_channel(self) -> aio.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Return the channel from cache. + return self._grpc_channel + + @property + def translate_query( + self, + ) -> Callable[ + [translation_service.TranslateQueryRequest], + Awaitable[translation_service.TranslateQueryResponse], + ]: + r"""Return a callable for the translate query method over gRPC. + + Translates input queries from source dialects to + GoogleSQL. + + Returns: + Callable[[~.TranslateQueryRequest], + Awaitable[~.TranslateQueryResponse]]: + 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 "translate_query" not in self._stubs: + self._stubs["translate_query"] = self.grpc_channel.unary_unary( + "/google.cloud.bigquery.migration.v2alpha.SqlTranslationService/TranslateQuery", + request_serializer=translation_service.TranslateQueryRequest.serialize, + response_deserializer=translation_service.TranslateQueryResponse.deserialize, + ) + return self._stubs["translate_query"] + + def close(self): + return self.grpc_channel.close() + + +__all__ = ("SqlTranslationServiceGrpcAsyncIOTransport",) diff --git a/google/cloud/bigquery_migration_v2alpha/types/__init__.py b/google/cloud/bigquery_migration_v2alpha/types/__init__.py index 8d18db5..7266742 100644 --- a/google/cloud/bigquery_migration_v2alpha/types/__init__.py +++ b/google/cloud/bigquery_migration_v2alpha/types/__init__.py @@ -33,6 +33,13 @@ ListMigrationWorkflowsResponse, StartMigrationWorkflowRequest, ) +from .translation_service import ( + SqlTranslationError, + SqlTranslationErrorDetail, + SqlTranslationWarning, + TranslateQueryRequest, + TranslateQueryResponse, +) from .translation_task import ( BteqOptions, DatasetReference, @@ -66,6 +73,11 @@ "ListMigrationWorkflowsRequest", "ListMigrationWorkflowsResponse", "StartMigrationWorkflowRequest", + "SqlTranslationError", + "SqlTranslationErrorDetail", + "SqlTranslationWarning", + "TranslateQueryRequest", + "TranslateQueryResponse", "BteqOptions", "DatasetReference", "Filter", diff --git a/google/cloud/bigquery_migration_v2alpha/types/translation_service.py b/google/cloud/bigquery_migration_v2alpha/types/translation_service.py new file mode 100644 index 0000000..bac9366 --- /dev/null +++ b/google/cloud/bigquery_migration_v2alpha/types/translation_service.py @@ -0,0 +1,202 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.bigquery.migration.v2alpha", + manifest={ + "TranslateQueryRequest", + "TranslateQueryResponse", + "SqlTranslationErrorDetail", + "SqlTranslationError", + "SqlTranslationWarning", + }, +) + + +class TranslateQueryRequest(proto.Message): + r"""The request of translating a SQL query to Standard SQL. + + Attributes: + parent (str): + Required. The name of the project to which this translation + request belongs. Example: ``projects/foo/locations/bar`` + source_dialect (google.cloud.bigquery_migration_v2alpha.types.TranslateQueryRequest.SqlTranslationSourceDialect): + Required. The source SQL dialect of ``queries``. + query (str): + Required. The query to be translated. + """ + + class SqlTranslationSourceDialect(proto.Enum): + r"""Supported SQL translation source dialects. + + Values: + SQL_TRANSLATION_SOURCE_DIALECT_UNSPECIFIED (0): + SqlTranslationSourceDialect not specified. + TERADATA (1): + Teradata SQL. + """ + SQL_TRANSLATION_SOURCE_DIALECT_UNSPECIFIED = 0 + TERADATA = 1 + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + source_dialect: SqlTranslationSourceDialect = proto.Field( + proto.ENUM, + number=2, + enum=SqlTranslationSourceDialect, + ) + query: str = proto.Field( + proto.STRING, + number=3, + ) + + +class TranslateQueryResponse(proto.Message): + r"""The response of translating a SQL query to Standard SQL. + + Attributes: + translation_job (str): + Output only. Immutable. The unique identifier for the SQL + translation job. Example: + ``projects/123/locations/us/translation/1234`` + translated_query (str): + The translated result. This will be empty if + the translation fails. + errors (MutableSequence[google.cloud.bigquery_migration_v2alpha.types.SqlTranslationError]): + The list of errors encountered during the + translation, if present. + warnings (MutableSequence[google.cloud.bigquery_migration_v2alpha.types.SqlTranslationWarning]): + The list of warnings encountered during the + translation, if present, indicates + non-semantically correct translation. + """ + + translation_job: str = proto.Field( + proto.STRING, + number=4, + ) + translated_query: str = proto.Field( + proto.STRING, + number=1, + ) + errors: MutableSequence["SqlTranslationError"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="SqlTranslationError", + ) + warnings: MutableSequence["SqlTranslationWarning"] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="SqlTranslationWarning", + ) + + +class SqlTranslationErrorDetail(proto.Message): + r"""Structured error object capturing the error message and the + location in the source text where the error occurs. + + Attributes: + row (int): + Specifies the row from the source text where + the error occurred. + column (int): + Specifie the column from the source texts + where the error occurred. + message (str): + A human-readable description of the error. + """ + + row: int = proto.Field( + proto.INT64, + number=1, + ) + column: int = proto.Field( + proto.INT64, + number=2, + ) + message: str = proto.Field( + proto.STRING, + number=3, + ) + + +class SqlTranslationError(proto.Message): + r"""The detailed error object if the SQL translation job fails. + + Attributes: + error_type (google.cloud.bigquery_migration_v2alpha.types.SqlTranslationError.SqlTranslationErrorType): + The type of SQL translation error. + error_detail (google.cloud.bigquery_migration_v2alpha.types.SqlTranslationErrorDetail): + Specifies the details of the error, including + the error message and location from the source + text. + """ + + class SqlTranslationErrorType(proto.Enum): + r"""The error type of the SQL translation job. + + Values: + SQL_TRANSLATION_ERROR_TYPE_UNSPECIFIED (0): + SqlTranslationErrorType not specified. + SQL_PARSE_ERROR (1): + Failed to parse the input text as a SQL + query. + UNSUPPORTED_SQL_FUNCTION (2): + Found unsupported functions in the input SQL + query that are not able to translate. + """ + SQL_TRANSLATION_ERROR_TYPE_UNSPECIFIED = 0 + SQL_PARSE_ERROR = 1 + UNSUPPORTED_SQL_FUNCTION = 2 + + error_type: SqlTranslationErrorType = proto.Field( + proto.ENUM, + number=1, + enum=SqlTranslationErrorType, + ) + error_detail: "SqlTranslationErrorDetail" = proto.Field( + proto.MESSAGE, + number=2, + message="SqlTranslationErrorDetail", + ) + + +class SqlTranslationWarning(proto.Message): + r"""The detailed warning object if the SQL translation job is + completed but not semantically correct. + + Attributes: + warning_detail (google.cloud.bigquery_migration_v2alpha.types.SqlTranslationErrorDetail): + Specifies the details of the warning, + including the warning message and location from + the source text. + """ + + warning_detail: "SqlTranslationErrorDetail" = proto.Field( + proto.MESSAGE, + number=1, + message="SqlTranslationErrorDetail", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/samples/generated_samples/bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_async.py b/samples/generated_samples/bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_async.py new file mode 100644 index 0000000..1ebd697 --- /dev/null +++ b/samples/generated_samples/bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_async.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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 TranslateQuery +# 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-bigquery-migration + + +# [START bigquerymigration_v2alpha_generated_SqlTranslationService_TranslateQuery_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 bigquery_migration_v2alpha + + +async def sample_translate_query(): + # Create a client + client = bigquery_migration_v2alpha.SqlTranslationServiceAsyncClient() + + # Initialize request argument(s) + request = bigquery_migration_v2alpha.TranslateQueryRequest( + parent="parent_value", + source_dialect="TERADATA", + query="query_value", + ) + + # Make the request + response = await client.translate_query(request=request) + + # Handle the response + print(response) + +# [END bigquerymigration_v2alpha_generated_SqlTranslationService_TranslateQuery_async] diff --git a/samples/generated_samples/bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_sync.py b/samples/generated_samples/bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_sync.py new file mode 100644 index 0000000..25700a9 --- /dev/null +++ b/samples/generated_samples/bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_sync.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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 TranslateQuery +# 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-bigquery-migration + + +# [START bigquerymigration_v2alpha_generated_SqlTranslationService_TranslateQuery_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 bigquery_migration_v2alpha + + +def sample_translate_query(): + # Create a client + client = bigquery_migration_v2alpha.SqlTranslationServiceClient() + + # Initialize request argument(s) + request = bigquery_migration_v2alpha.TranslateQueryRequest( + parent="parent_value", + source_dialect="TERADATA", + query="query_value", + ) + + # Make the request + response = client.translate_query(request=request) + + # Handle the response + print(response) + +# [END bigquerymigration_v2alpha_generated_SqlTranslationService_TranslateQuery_sync] diff --git a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json index b95cbec..1457555 100644 --- a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json +++ b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json @@ -1133,6 +1133,183 @@ } ], "title": "bigquerymigration_v2alpha_generated_migration_service_start_migration_workflow_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.bigquery_migration_v2alpha.SqlTranslationServiceAsyncClient", + "shortName": "SqlTranslationServiceAsyncClient" + }, + "fullName": "google.cloud.bigquery_migration_v2alpha.SqlTranslationServiceAsyncClient.translate_query", + "method": { + "fullName": "google.cloud.bigquery.migration.v2alpha.SqlTranslationService.TranslateQuery", + "service": { + "fullName": "google.cloud.bigquery.migration.v2alpha.SqlTranslationService", + "shortName": "SqlTranslationService" + }, + "shortName": "TranslateQuery" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.bigquery_migration_v2alpha.types.TranslateQueryRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "source_dialect", + "type": "google.cloud.bigquery_migration_v2alpha.types.TranslateQueryRequest.SqlTranslationSourceDialect" + }, + { + "name": "query", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.bigquery_migration_v2alpha.types.TranslateQueryResponse", + "shortName": "translate_query" + }, + "description": "Sample for TranslateQuery", + "file": "bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "bigquerymigration_v2alpha_generated_SqlTranslationService_TranslateQuery_async", + "segments": [ + { + "end": 53, + "start": 27, + "type": "FULL" + }, + { + "end": 53, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 47, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 50, + "start": 48, + "type": "REQUEST_EXECUTION" + }, + { + "end": 54, + "start": 51, + "type": "RESPONSE_HANDLING" + } + ], + "title": "bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.bigquery_migration_v2alpha.SqlTranslationServiceClient", + "shortName": "SqlTranslationServiceClient" + }, + "fullName": "google.cloud.bigquery_migration_v2alpha.SqlTranslationServiceClient.translate_query", + "method": { + "fullName": "google.cloud.bigquery.migration.v2alpha.SqlTranslationService.TranslateQuery", + "service": { + "fullName": "google.cloud.bigquery.migration.v2alpha.SqlTranslationService", + "shortName": "SqlTranslationService" + }, + "shortName": "TranslateQuery" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.bigquery_migration_v2alpha.types.TranslateQueryRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "source_dialect", + "type": "google.cloud.bigquery_migration_v2alpha.types.TranslateQueryRequest.SqlTranslationSourceDialect" + }, + { + "name": "query", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.bigquery_migration_v2alpha.types.TranslateQueryResponse", + "shortName": "translate_query" + }, + "description": "Sample for TranslateQuery", + "file": "bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "bigquerymigration_v2alpha_generated_SqlTranslationService_TranslateQuery_sync", + "segments": [ + { + "end": 53, + "start": 27, + "type": "FULL" + }, + { + "end": 53, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 47, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 50, + "start": 48, + "type": "REQUEST_EXECUTION" + }, + { + "end": 54, + "start": 51, + "type": "RESPONSE_HANDLING" + } + ], + "title": "bigquerymigration_v2alpha_generated_sql_translation_service_translate_query_sync.py" } ] } diff --git a/scripts/fixup_bigquery_migration_v2alpha_keywords.py b/scripts/fixup_bigquery_migration_v2alpha_keywords.py index 18f588a..24a0351 100644 --- a/scripts/fixup_bigquery_migration_v2alpha_keywords.py +++ b/scripts/fixup_bigquery_migration_v2alpha_keywords.py @@ -46,6 +46,7 @@ class bigquery_migrationCallTransformer(cst.CSTTransformer): 'list_migration_subtasks': ('parent', 'read_mask', 'page_size', 'page_token', 'filter', ), 'list_migration_workflows': ('parent', 'read_mask', 'page_size', 'page_token', ), 'start_migration_workflow': ('name', ), + 'translate_query': ('parent', 'source_dialect', 'query', ), } def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: diff --git a/tests/unit/gapic/bigquery_migration_v2alpha/test_sql_translation_service.py b/tests/unit/gapic/bigquery_migration_v2alpha/test_sql_translation_service.py new file mode 100644 index 0000000..ef973c4 --- /dev/null +++ b/tests/unit/gapic/bigquery_migration_v2alpha/test_sql_translation_service.py @@ -0,0 +1,1655 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. +# +import os + +# try/except added for compatibility with python < 3.8 +try: + from unittest import mock + from unittest.mock import AsyncMock # pragma: NO COVER +except ImportError: # pragma: NO COVER + import mock + +import math + +from google.api_core import gapic_v1, grpc_helpers, grpc_helpers_async, path_template +from google.api_core import client_options +from google.api_core import exceptions as core_exceptions +import google.auth +from google.auth import credentials as ga_credentials +from google.auth.exceptions import MutualTLSChannelError +from google.oauth2 import service_account +import grpc +from grpc.experimental import aio +from proto.marshal.rules import wrappers +from proto.marshal.rules.dates import DurationRule, TimestampRule +import pytest + +from google.cloud.bigquery_migration_v2alpha.services.sql_translation_service import ( + SqlTranslationServiceAsyncClient, + SqlTranslationServiceClient, + transports, +) +from google.cloud.bigquery_migration_v2alpha.types import translation_service + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +# If default endpoint is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint(client): + return ( + "foo.googleapis.com" + if ("localhost" in client.DEFAULT_ENDPOINT) + else client.DEFAULT_ENDPOINT + ) + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert SqlTranslationServiceClient._get_default_mtls_endpoint(None) is None + assert ( + SqlTranslationServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + SqlTranslationServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + SqlTranslationServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + SqlTranslationServiceClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + SqlTranslationServiceClient._get_default_mtls_endpoint(non_googleapi) + == non_googleapi + ) + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (SqlTranslationServiceClient, "grpc"), + (SqlTranslationServiceAsyncClient, "grpc_asyncio"), + ], +) +def test_sql_translation_service_client_from_service_account_info( + client_class, transport_name +): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info, transport=transport_name) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ("bigquerymigration.googleapis.com:443") + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.SqlTranslationServiceGrpcTransport, "grpc"), + (transports.SqlTranslationServiceGrpcAsyncIOTransport, "grpc_asyncio"), + ], +) +def test_sql_translation_service_client_service_account_always_use_jwt( + transport_class, transport_name +): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=True) + use_jwt.assert_called_once_with(True) + + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=False) + use_jwt.assert_not_called() + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (SqlTranslationServiceClient, "grpc"), + (SqlTranslationServiceAsyncClient, "grpc_asyncio"), + ], +) +def test_sql_translation_service_client_from_service_account_file( + client_class, transport_name +): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + factory.return_value = creds + client = client_class.from_service_account_file( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + client = client_class.from_service_account_json( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ("bigquerymigration.googleapis.com:443") + + +def test_sql_translation_service_client_get_transport_class(): + transport = SqlTranslationServiceClient.get_transport_class() + available_transports = [ + transports.SqlTranslationServiceGrpcTransport, + ] + assert transport in available_transports + + transport = SqlTranslationServiceClient.get_transport_class("grpc") + assert transport == transports.SqlTranslationServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + SqlTranslationServiceClient, + transports.SqlTranslationServiceGrpcTransport, + "grpc", + ), + ( + SqlTranslationServiceAsyncClient, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ], +) +@mock.patch.object( + SqlTranslationServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(SqlTranslationServiceClient), +) +@mock.patch.object( + SqlTranslationServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(SqlTranslationServiceAsyncClient), +) +def test_sql_translation_service_client_client_options( + client_class, transport_class, transport_name +): + # Check that if channel is provided we won't create a new one. + with mock.patch.object(SqlTranslationServiceClient, "get_transport_class") as gtc: + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) + client = client_class(transport=transport) + gtc.assert_not_called() + + # Check that if channel is provided via str we will create a new one. + with mock.patch.object(SqlTranslationServiceClient, "get_transport_class") as gtc: + client = client_class(transport=transport_name) + gtc.assert_called() + + # Check the case api_endpoint is provided. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name, client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # 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): + client = client_class(transport=transport_name) + + # 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): + client = client_class(transport=transport_name) + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + # Check the case api_endpoint is provided + options = client_options.ClientOptions( + api_audience="https://language.googleapis.com" + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience="https://language.googleapis.com", + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + SqlTranslationServiceClient, + transports.SqlTranslationServiceGrpcTransport, + "grpc", + "true", + ), + ( + SqlTranslationServiceAsyncClient, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + SqlTranslationServiceClient, + transports.SqlTranslationServiceGrpcTransport, + "grpc", + "false", + ), + ( + SqlTranslationServiceAsyncClient, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + SqlTranslationServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(SqlTranslationServiceClient), +) +@mock.patch.object( + SqlTranslationServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(SqlTranslationServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_sql_translation_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client.DEFAULT_ENDPOINT + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT + + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + 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=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client.DEFAULT_ENDPOINT + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback + + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class", [SqlTranslationServiceClient, SqlTranslationServiceAsyncClient] +) +@mock.patch.object( + SqlTranslationServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(SqlTranslationServiceClient), +) +@mock.patch.object( + SqlTranslationServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(SqlTranslationServiceAsyncClient), +) +def test_sql_translation_service_client_get_mtls_endpoint_and_cert_source(client_class): + mock_client_cert_source = mock.Mock() + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "true". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source == mock_client_cert_source + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "false". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + mock_client_cert_source = mock.Mock() + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert doesn't exist. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert exists. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + 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_client_cert_source, + ): + ( + api_endpoint, + cert_source, + ) = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source == mock_client_cert_source + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + SqlTranslationServiceClient, + transports.SqlTranslationServiceGrpcTransport, + "grpc", + ), + ( + SqlTranslationServiceAsyncClient, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ], +) +def test_sql_translation_service_client_client_options_scopes( + client_class, transport_class, transport_name +): + # Check the case scopes are provided. + options = client_options.ClientOptions( + scopes=["1", "2"], + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=["1", "2"], + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + SqlTranslationServiceClient, + transports.SqlTranslationServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + SqlTranslationServiceAsyncClient, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_sql_translation_service_client_client_options_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +def test_sql_translation_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.bigquery_migration_v2alpha.services.sql_translation_service.transports.SqlTranslationServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = SqlTranslationServiceClient( + client_options={"api_endpoint": "squid.clam.whelk"} + ) + grpc_transport.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + SqlTranslationServiceClient, + transports.SqlTranslationServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + SqlTranslationServiceAsyncClient, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_sql_translation_service_client_create_channel_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # test that the credentials from file are saved and used as the credentials. + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel" + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + file_creds = ga_credentials.AnonymousCredentials() + load_creds.return_value = (file_creds, None) + adc.return_value = (creds, None) + client = client_class(client_options=options, transport=transport_name) + create_channel.assert_called_with( + "bigquerymigration.googleapis.com:443", + credentials=file_creds, + credentials_file=None, + quota_project_id=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=None, + default_host="bigquerymigration.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + translation_service.TranslateQueryRequest, + dict, + ], +) +def test_translate_query(request_type, transport: str = "grpc"): + client = SqlTranslationServiceClient( + 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.translate_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = translation_service.TranslateQueryResponse( + translation_job="translation_job_value", + translated_query="translated_query_value", + ) + response = client.translate_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] == translation_service.TranslateQueryRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, translation_service.TranslateQueryResponse) + assert response.translation_job == "translation_job_value" + assert response.translated_query == "translated_query_value" + + +def test_translate_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 = SqlTranslationServiceClient( + 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.translate_query), "__call__") as call: + client.translate_query() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == translation_service.TranslateQueryRequest() + + +@pytest.mark.asyncio +async def test_translate_query_async( + transport: str = "grpc_asyncio", + request_type=translation_service.TranslateQueryRequest, +): + client = SqlTranslationServiceAsyncClient( + 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.translate_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + translation_service.TranslateQueryResponse( + translation_job="translation_job_value", + translated_query="translated_query_value", + ) + ) + response = await client.translate_query(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == translation_service.TranslateQueryRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, translation_service.TranslateQueryResponse) + assert response.translation_job == "translation_job_value" + assert response.translated_query == "translated_query_value" + + +@pytest.mark.asyncio +async def test_translate_query_async_from_dict(): + await test_translate_query_async(request_type=dict) + + +def test_translate_query_field_headers(): + client = SqlTranslationServiceClient( + 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 = translation_service.TranslateQueryRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.translate_query), "__call__") as call: + call.return_value = translation_service.TranslateQueryResponse() + client.translate_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] == 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_translate_query_field_headers_async(): + client = SqlTranslationServiceAsyncClient( + 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 = translation_service.TranslateQueryRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.translate_query), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + translation_service.TranslateQueryResponse() + ) + await client.translate_query(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_translate_query_flattened(): + client = SqlTranslationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.translate_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = translation_service.TranslateQueryResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.translate_query( + parent="parent_value", + source_dialect=translation_service.TranslateQueryRequest.SqlTranslationSourceDialect.TERADATA, + query="query_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].source_dialect + mock_val = ( + translation_service.TranslateQueryRequest.SqlTranslationSourceDialect.TERADATA + ) + assert arg == mock_val + arg = args[0].query + mock_val = "query_value" + assert arg == mock_val + + +def test_translate_query_flattened_error(): + client = SqlTranslationServiceClient( + 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.translate_query( + translation_service.TranslateQueryRequest(), + parent="parent_value", + source_dialect=translation_service.TranslateQueryRequest.SqlTranslationSourceDialect.TERADATA, + query="query_value", + ) + + +@pytest.mark.asyncio +async def test_translate_query_flattened_async(): + client = SqlTranslationServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.translate_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = translation_service.TranslateQueryResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + translation_service.TranslateQueryResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.translate_query( + parent="parent_value", + source_dialect=translation_service.TranslateQueryRequest.SqlTranslationSourceDialect.TERADATA, + query="query_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].source_dialect + mock_val = ( + translation_service.TranslateQueryRequest.SqlTranslationSourceDialect.TERADATA + ) + assert arg == mock_val + arg = args[0].query + mock_val = "query_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_translate_query_flattened_error_async(): + client = SqlTranslationServiceAsyncClient( + 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.translate_query( + translation_service.TranslateQueryRequest(), + parent="parent_value", + source_dialect=translation_service.TranslateQueryRequest.SqlTranslationSourceDialect.TERADATA, + query="query_value", + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.SqlTranslationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = SqlTranslationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.SqlTranslationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = SqlTranslationServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.SqlTranslationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = SqlTranslationServiceClient( + client_options=options, + transport=transport, + ) + + # It is an error to provide an api_key and a credential. + options = mock.Mock() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = SqlTranslationServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.SqlTranslationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = SqlTranslationServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.SqlTranslationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = SqlTranslationServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.SqlTranslationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.SqlTranslationServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.SqlTranslationServiceGrpcTransport, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + ], +) +def test_transport_kind(transport_name): + transport = SqlTranslationServiceClient.get_transport_class(transport_name)( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert transport.kind == transport_name + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = SqlTranslationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.SqlTranslationServiceGrpcTransport, + ) + + +def test_sql_translation_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.SqlTranslationServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_sql_translation_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.bigquery_migration_v2alpha.services.sql_translation_service.transports.SqlTranslationServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.SqlTranslationServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ("translate_query",) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + with pytest.raises(NotImplementedError): + transport.close() + + # Catch all for all remaining methods and properties + remainder = [ + "kind", + ] + for r in remainder: + with pytest.raises(NotImplementedError): + getattr(transport, r)() + + +def test_sql_translation_service_base_transport_with_credentials_file(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.bigquery_migration_v2alpha.services.sql_translation_service.transports.SqlTranslationServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.SqlTranslationServiceTransport( + credentials_file="credentials.json", + quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +def test_sql_translation_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( + "google.cloud.bigquery_migration_v2alpha.services.sql_translation_service.transports.SqlTranslationServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.SqlTranslationServiceTransport() + adc.assert_called_once() + + +def test_sql_translation_service_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + SqlTranslationServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id=None, + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.SqlTranslationServiceGrpcTransport, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + ], +) +def test_sql_translation_service_transport_auth_adc(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.SqlTranslationServiceGrpcTransport, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + ], +) +def test_sql_translation_service_transport_auth_gdch_credentials(transport_class): + host = "https://language.com" + api_audience_tests = [None, "https://language2.com"] + api_audience_expect = [host, "https://language2.com"] + for t, e in zip(api_audience_tests, api_audience_expect): + with mock.patch.object(google.auth, "default", autospec=True) as adc: + gdch_mock = mock.MagicMock() + type(gdch_mock).with_gdch_audience = mock.PropertyMock( + return_value=gdch_mock + ) + adc.return_value = (gdch_mock, None) + transport_class(host=host, api_audience=t) + gdch_mock.with_gdch_audience.assert_called_once_with(e) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.SqlTranslationServiceGrpcTransport, grpc_helpers), + (transports.SqlTranslationServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_sql_translation_service_transport_create_channel( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "bigquerymigration.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=["1", "2"], + default_host="bigquerymigration.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.SqlTranslationServiceGrpcTransport, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + ], +) +def test_sql_translation_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = ga_credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + ], +) +def test_sql_translation_service_host_no_port(transport_name): + client = SqlTranslationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="bigquerymigration.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ("bigquerymigration.googleapis.com:443") + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + ], +) +def test_sql_translation_service_host_with_port(transport_name): + client = SqlTranslationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="bigquerymigration.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ("bigquerymigration.googleapis.com:8000") + + +def test_sql_translation_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.SqlTranslationServiceGrpcTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +def test_sql_translation_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.SqlTranslationServiceGrpcAsyncIOTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.SqlTranslationServiceGrpcTransport, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + ], +) +def test_sql_translation_service_transport_channel_mtls_with_client_cert_source( + transport_class, +): + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = ga_credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.SqlTranslationServiceGrpcTransport, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + ], +) +def test_sql_translation_service_transport_channel_mtls_with_adc(transport_class): + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + + +def test_common_billing_account_path(): + billing_account = "squid" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = SqlTranslationServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "clam", + } + path = SqlTranslationServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = SqlTranslationServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "whelk" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = SqlTranslationServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "octopus", + } + path = SqlTranslationServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = SqlTranslationServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "oyster" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = SqlTranslationServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "nudibranch", + } + path = SqlTranslationServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = SqlTranslationServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "cuttlefish" + expected = "projects/{project}".format( + project=project, + ) + actual = SqlTranslationServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "mussel", + } + path = SqlTranslationServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = SqlTranslationServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "winkle" + location = "nautilus" + expected = "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + actual = SqlTranslationServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "scallop", + "location": "abalone", + } + path = SqlTranslationServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = SqlTranslationServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_with_default_client_info(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.SqlTranslationServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = SqlTranslationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.SqlTranslationServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = SqlTranslationServiceClient.get_transport_class() + transport = transport_class( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = SqlTranslationServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = SqlTranslationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = SqlTranslationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() + + +@pytest.mark.parametrize( + "client_class,transport_class", + [ + (SqlTranslationServiceClient, transports.SqlTranslationServiceGrpcTransport), + ( + SqlTranslationServiceAsyncClient, + transports.SqlTranslationServiceGrpcAsyncIOTransport, + ), + ], +) +def test_api_key_credentials(client_class, transport_class): + with mock.patch.object( + google.auth._default, "get_api_key_credentials", create=True + ) as get_api_key_credentials: + mock_cred = mock.Mock() + get_api_key_credentials.return_value = mock_cred + options = client_options.ClientOptions() + options.api_key = "api_key" + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=mock_cred, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) From fd94f47b36b2051a752b074700329539fd8b3f31 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 1 Mar 2023 13:24:40 -0500 Subject: [PATCH 9/9] chore(main): release 0.10.0 (#171) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 7 +++++++ google/cloud/bigquery_migration/gapic_version.py | 2 +- google/cloud/bigquery_migration_v2/gapic_version.py | 2 +- google/cloud/bigquery_migration_v2alpha/gapic_version.py | 2 +- ...nippet_metadata_google.cloud.bigquery.migration.v2.json | 2 +- ...t_metadata_google.cloud.bigquery.migration.v2alpha.json | 2 +- 7 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b28fea9..7d9b009 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.9.1" + ".": "0.10.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 03f75a3..25965b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.10.0](https://github.com/googleapis/python-bigquery-migration/compare/v0.9.1...v0.10.0) (2023-03-01) + + +### Features + +* **v2alpha:** Add SQL translation service ([#170](https://github.com/googleapis/python-bigquery-migration/issues/170)) ([533d1d8](https://github.com/googleapis/python-bigquery-migration/commit/533d1d87e3bfb917488550a979b35994ebe293ed)) + ## [0.9.1](https://github.com/googleapis/python-bigquery-migration/compare/v0.9.0...v0.9.1) (2023-01-20) diff --git a/google/cloud/bigquery_migration/gapic_version.py b/google/cloud/bigquery_migration/gapic_version.py index f7e843c..267ed2e 100644 --- a/google/cloud/bigquery_migration/gapic_version.py +++ b/google/cloud/bigquery_migration/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "0.9.1" # {x-release-please-version} +__version__ = "0.10.0" # {x-release-please-version} diff --git a/google/cloud/bigquery_migration_v2/gapic_version.py b/google/cloud/bigquery_migration_v2/gapic_version.py index f7e843c..267ed2e 100644 --- a/google/cloud/bigquery_migration_v2/gapic_version.py +++ b/google/cloud/bigquery_migration_v2/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "0.9.1" # {x-release-please-version} +__version__ = "0.10.0" # {x-release-please-version} diff --git a/google/cloud/bigquery_migration_v2alpha/gapic_version.py b/google/cloud/bigquery_migration_v2alpha/gapic_version.py index f7e843c..267ed2e 100644 --- a/google/cloud/bigquery_migration_v2alpha/gapic_version.py +++ b/google/cloud/bigquery_migration_v2alpha/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "0.9.1" # {x-release-please-version} +__version__ = "0.10.0" # {x-release-please-version} diff --git a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2.json b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2.json index eb49516..24663c5 100644 --- a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2.json +++ b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-bigquery-migration", - "version": "0.1.0" + "version": "0.10.0" }, "snippets": [ { diff --git a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json index 1457555..0169709 100644 --- a/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json +++ b/samples/generated_samples/snippet_metadata_google.cloud.bigquery.migration.v2alpha.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-bigquery-migration", - "version": "0.1.0" + "version": "0.10.0" }, "snippets": [ { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy