From a397effb87f74f579605bcf261bf2b00d5e9fa5b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 23 Mar 2021 17:00:08 -0700 Subject: [PATCH] feat(v3beta1): add online and batch document translation (#121) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat(v3beta1): add online and batch document translation  feat: add `from_service_account_info` fix: use correct retry deadlines --- .coveragerc | 32 +- .github/header-checker-lint.yml | 15 + .gitignore | 4 +- .kokoro/build.sh | 26 +- .kokoro/docs/docs-presubmit.cfg | 11 + .kokoro/samples/python3.6/periodic-head.cfg | 11 + .kokoro/samples/python3.7/periodic-head.cfg | 11 + .kokoro/samples/python3.8/periodic-head.cfg | 11 + .../test-samples-against-head.sh | 21 +- .kokoro/test-samples-impl.sh | 102 +++ .kokoro/test-samples.sh | 96 +-- .pre-commit-config.yaml | 2 +- .trampolinerc | 1 + CONTRIBUTING.rst | 22 +- MANIFEST.in | 4 +- UPGRADING.md | 4 +- docs/translate_v3/services.rst | 6 +- docs/translate_v3/translation_service.rst | 11 + docs/translate_v3/types.rst | 1 + docs/translate_v3beta1/services.rst | 6 +- .../translate_v3beta1/translation_service.rst | 11 + docs/translate_v3beta1/types.rst | 1 + .../translation_service/async_client.py | 107 ++- .../services/translation_service/client.py | 151 ++-- .../services/translation_service/pagers.py | 27 +- .../translation_service/transports/base.py | 22 +- .../translation_service/transports/grpc.py | 114 ++- .../transports/grpc_asyncio.py | 122 ++- google/cloud/translate_v3/types/__init__.py | 84 +- .../translate_v3/types/translation_service.py | 66 +- google/cloud/translate_v3beta1/__init__.py | 20 + .../translation_service/async_client.py | 283 +++++-- .../services/translation_service/client.py | 312 +++++-- .../services/translation_service/pagers.py | 27 +- .../translation_service/transports/base.py | 51 +- .../translation_service/transports/grpc.py | 179 ++-- .../transports/grpc_asyncio.py | 188 +++-- .../cloud/translate_v3beta1/types/__init__.py | 104 ++- .../types/translation_service.py | 786 ++++++++++++++++-- noxfile.py | 57 +- renovate.json | 3 +- samples/snippets/hybrid_glossaries/noxfile.py | 2 +- samples/snippets/noxfile.py | 2 +- scripts/fixup_translate_v3beta1_keywords.py | 2 + setup.py | 5 +- synth.metadata | 121 +-- synth.py | 7 + testing/constraints-3.10.txt | 0 testing/constraints-3.11.txt | 0 testing/constraints-3.6.txt | 10 + testing/constraints-3.7.txt | 0 testing/constraints-3.8.txt | 0 testing/constraints-3.9.txt | 0 tests/unit/gapic/translate_v3/__init__.py | 15 + .../translate_v3/test_translation_service.py | 353 ++++++-- .../unit/gapic/translate_v3beta1/__init__.py | 15 + .../test_translation_service.py | 659 +++++++++++++-- 57 files changed, 3151 insertions(+), 1152 deletions(-) create mode 100644 .github/header-checker-lint.yml create mode 100644 .kokoro/samples/python3.6/periodic-head.cfg create mode 100644 .kokoro/samples/python3.7/periodic-head.cfg create mode 100644 .kokoro/samples/python3.8/periodic-head.cfg rename google/cloud/translate.py => .kokoro/test-samples-against-head.sh (57%) mode change 100644 => 100755 create mode 100755 .kokoro/test-samples-impl.sh create mode 100644 docs/translate_v3/translation_service.rst create mode 100644 docs/translate_v3beta1/translation_service.rst create mode 100644 testing/constraints-3.10.txt create mode 100644 testing/constraints-3.11.txt create mode 100644 testing/constraints-3.6.txt create mode 100644 testing/constraints-3.7.txt create mode 100644 testing/constraints-3.8.txt create mode 100644 testing/constraints-3.9.txt diff --git a/.coveragerc b/.coveragerc index d9205f04..711d95bf 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,44 +1,20 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 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 -# -# https://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 by synthtool. DO NOT EDIT! [run] branch = True [report] fail_under = 100 show_missing = True +omit = + google/cloud/translate/__init__.py + google/cloud/translate_v2/__init__.py + google/cloud/__init__.py exclude_lines = # Re-enable the standard pragma pragma: NO COVER # Ignore debug-only repr def __repr__ - # Ignore abstract methods - raise NotImplementedError # Ignore pkg_resources exceptions. # This is added at the module level as a safeguard for if someone # generates the code and tries to run it without pip installing. This # makes it virtually impossible to test properly. except pkg_resources.DistributionNotFound -omit = - */gapic/*.py - */proto/*.py - */core/*.py - */site-packages/*.py - google/cloud/__init__.py - google/cloud/translate.py - google/cloud/translate/__init__.py - google/cloud/translation*/*.py \ No newline at end of file diff --git a/.github/header-checker-lint.yml b/.github/header-checker-lint.yml new file mode 100644 index 00000000..fc281c05 --- /dev/null +++ b/.github/header-checker-lint.yml @@ -0,0 +1,15 @@ +{"allowedCopyrightHolders": ["Google LLC"], + "allowedLicenses": ["Apache-2.0", "MIT", "BSD-3"], + "ignoreFiles": ["**/requirements.txt", "**/requirements-test.txt"], + "sourceFileExtensions": [ + "ts", + "js", + "java", + "sh", + "Dockerfile", + "yaml", + "py", + "html", + "txt" + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index b9daa52f..b4243ced 100644 --- a/.gitignore +++ b/.gitignore @@ -50,8 +50,10 @@ docs.metadata # Virtual environment env/ + +# Test logs coverage.xml -sponge_log.xml +*sponge_log.xml # System test environment variables. system_tests/local_test_setup diff --git a/.kokoro/build.sh b/.kokoro/build.sh index e4e84c42..862a763d 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -15,7 +15,11 @@ set -eo pipefail -cd github/python-translate +if [[ -z "${PROJECT_ROOT:-}" ]]; then + PROJECT_ROOT="github/python-translate" +fi + +cd "${PROJECT_ROOT}" # Disable buffering, so that the logs stream through. export PYTHONUNBUFFERED=1 @@ -30,16 +34,26 @@ export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json export PROJECT_ID=$(cat "${KOKORO_GFILE_DIR}/project-id.json") # Remove old nox -python3.6 -m pip uninstall --yes --quiet nox-automation +python3 -m pip uninstall --yes --quiet nox-automation # Install nox -python3.6 -m pip install --upgrade --quiet nox -python3.6 -m nox --version +python3 -m pip install --upgrade --quiet nox +python3 -m nox --version + +# If this is a continuous build, send the test log to the FlakyBot. +# See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. +if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then + cleanup() { + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot + } + trap cleanup EXIT HUP +fi # If NOX_SESSION is set, it only runs the specified session, # otherwise run all the sessions. if [[ -n "${NOX_SESSION:-}" ]]; then - python3.6 -m nox -s "${NOX_SESSION:-}" + python3 -m nox -s ${NOX_SESSION:-} else - python3.6 -m nox + python3 -m nox fi diff --git a/.kokoro/docs/docs-presubmit.cfg b/.kokoro/docs/docs-presubmit.cfg index 11181078..a7a40a92 100644 --- a/.kokoro/docs/docs-presubmit.cfg +++ b/.kokoro/docs/docs-presubmit.cfg @@ -15,3 +15,14 @@ env_vars: { key: "TRAMPOLINE_IMAGE_UPLOAD" value: "false" } + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-translate/.kokoro/build.sh" +} + +# Only run this nox session. +env_vars: { + key: "NOX_SESSION" + value: "docs docfx" +} diff --git a/.kokoro/samples/python3.6/periodic-head.cfg b/.kokoro/samples/python3.6/periodic-head.cfg new file mode 100644 index 00000000..f9cfcd33 --- /dev/null +++ b/.kokoro/samples/python3.6/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.7/periodic-head.cfg b/.kokoro/samples/python3.7/periodic-head.cfg new file mode 100644 index 00000000..f9cfcd33 --- /dev/null +++ b/.kokoro/samples/python3.7/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.8/periodic-head.cfg b/.kokoro/samples/python3.8/periodic-head.cfg new file mode 100644 index 00000000..f9cfcd33 --- /dev/null +++ b/.kokoro/samples/python3.8/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/google/cloud/translate.py b/.kokoro/test-samples-against-head.sh old mode 100644 new mode 100755 similarity index 57% rename from google/cloud/translate.py rename to .kokoro/test-samples-against-head.sh index 7b5ea626..e1137ce0 --- a/google/cloud/translate.py +++ b/.kokoro/test-samples-against-head.sh @@ -1,5 +1,4 @@ -# -*- coding: utf-8 -*- -# +#!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,14 +13,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +# A customized test runner for samples. +# +# For periodic builds, you can specify this file for testing against head. -from __future__ import absolute_import - -from google.cloud.translate_v3 import TranslationServiceClient -from google.cloud.translate_v3 import types +# `-e` enables the script to automatically fail when a command fails +# `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero +set -eo pipefail +# Enables `**` to include files nested inside sub-folders +shopt -s globstar +cd github/python-translate -__all__ = ( - "types", - "TranslationServiceClient", -) +exec .kokoro/test-samples-impl.sh diff --git a/.kokoro/test-samples-impl.sh b/.kokoro/test-samples-impl.sh new file mode 100755 index 00000000..cf5de74c --- /dev/null +++ b/.kokoro/test-samples-impl.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# Copyright 2021 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 +# +# https://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. + + +# `-e` enables the script to automatically fail when a command fails +# `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero +set -eo pipefail +# Enables `**` to include files nested inside sub-folders +shopt -s globstar + +# Exit early if samples directory doesn't exist +if [ ! -d "./samples" ]; then + echo "No tests run. `./samples` not found" + exit 0 +fi + +# Disable buffering, so that the logs stream through. +export PYTHONUNBUFFERED=1 + +# Debug: show build environment +env | grep KOKORO + +# Install nox +python3.6 -m pip install --upgrade --quiet nox + +# Use secrets acessor service account to get secrets +if [[ -f "${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" ]]; then + gcloud auth activate-service-account \ + --key-file="${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" \ + --project="cloud-devrel-kokoro-resources" +fi + +# This script will create 3 files: +# - testing/test-env.sh +# - testing/service-account.json +# - testing/client-secrets.json +./scripts/decrypt-secrets.sh + +source ./testing/test-env.sh +export GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/testing/service-account.json + +# For cloud-run session, we activate the service account for gcloud sdk. +gcloud auth activate-service-account \ + --key-file "${GOOGLE_APPLICATION_CREDENTIALS}" + +export GOOGLE_CLIENT_SECRETS=$(pwd)/testing/client-secrets.json + +echo -e "\n******************** TESTING PROJECTS ********************" + +# Switch to 'fail at end' to allow all tests to complete before exiting. +set +e +# Use RTN to return a non-zero value if the test fails. +RTN=0 +ROOT=$(pwd) +# Find all requirements.txt in the samples directory (may break on whitespace). +for file in samples/**/requirements.txt; do + cd "$ROOT" + # Navigate to the project folder. + file=$(dirname "$file") + cd "$file" + + echo "------------------------------------------------------------" + echo "- testing $file" + echo "------------------------------------------------------------" + + # Use nox to execute the tests for the project. + python3.6 -m nox -s "$RUN_TESTS_SESSION" + EXIT=$? + + # If this is a periodic build, send the test log to the FlakyBot. + # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. + if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot + fi + + if [[ $EXIT -ne 0 ]]; then + RTN=1 + echo -e "\n Testing failed: Nox returned a non-zero exit code. \n" + else + echo -e "\n Testing completed.\n" + fi + +done +cd "$ROOT" + +# Workaround for Kokoro permissions issue: delete secrets +rm testing/{test-env.sh,client-secrets.json,service-account.json} + +exit "$RTN" diff --git a/.kokoro/test-samples.sh b/.kokoro/test-samples.sh index 82e6dc4e..71a494e3 100755 --- a/.kokoro/test-samples.sh +++ b/.kokoro/test-samples.sh @@ -13,6 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# The default test runner for samples. +# +# For periodic builds, we rewinds the repo to the latest release, and +# run test-samples-impl.sh. # `-e` enables the script to automatically fail when a command fails # `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero @@ -24,87 +28,19 @@ cd github/python-translate # Run periodic samples tests at latest release if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then + # preserving the test runner implementation. + cp .kokoro/test-samples-impl.sh "${TMPDIR}/test-samples-impl.sh" + echo "--- IMPORTANT IMPORTANT IMPORTANT ---" + echo "Now we rewind the repo back to the latest release..." LATEST_RELEASE=$(git describe --abbrev=0 --tags) git checkout $LATEST_RELEASE -fi - -# Exit early if samples directory doesn't exist -if [ ! -d "./samples" ]; then - echo "No tests run. `./samples` not found" - exit 0 -fi - -# Disable buffering, so that the logs stream through. -export PYTHONUNBUFFERED=1 - -# Debug: show build environment -env | grep KOKORO - -# Install nox -python3.6 -m pip install --upgrade --quiet nox - -# Use secrets acessor service account to get secrets -if [[ -f "${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" ]]; then - gcloud auth activate-service-account \ - --key-file="${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" \ - --project="cloud-devrel-kokoro-resources" -fi - -# This script will create 3 files: -# - testing/test-env.sh -# - testing/service-account.json -# - testing/client-secrets.json -./scripts/decrypt-secrets.sh - -source ./testing/test-env.sh -export GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/testing/service-account.json - -# For cloud-run session, we activate the service account for gcloud sdk. -gcloud auth activate-service-account \ - --key-file "${GOOGLE_APPLICATION_CREDENTIALS}" - -export GOOGLE_CLIENT_SECRETS=$(pwd)/testing/client-secrets.json - -echo -e "\n******************** TESTING PROJECTS ********************" - -# Switch to 'fail at end' to allow all tests to complete before exiting. -set +e -# Use RTN to return a non-zero value if the test fails. -RTN=0 -ROOT=$(pwd) -# Find all requirements.txt in the samples directory (may break on whitespace). -for file in samples/**/requirements.txt; do - cd "$ROOT" - # Navigate to the project folder. - file=$(dirname "$file") - cd "$file" - - echo "------------------------------------------------------------" - echo "- testing $file" - echo "------------------------------------------------------------" - - # Use nox to execute the tests for the project. - python3.6 -m nox -s "$RUN_TESTS_SESSION" - EXIT=$? - - # If this is a periodic build, send the test log to the FlakyBot. - # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. - if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then - chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot - $KOKORO_GFILE_DIR/linux_amd64/flakybot + echo "The current head is: " + echo $(git rev-parse --verify HEAD) + echo "--- IMPORTANT IMPORTANT IMPORTANT ---" + # move back the test runner implementation if there's no file. + if [ ! -f .kokoro/test-samples-impl.sh ]; then + cp "${TMPDIR}/test-samples-impl.sh" .kokoro/test-samples-impl.sh fi +fi - if [[ $EXIT -ne 0 ]]; then - RTN=1 - echo -e "\n Testing failed: Nox returned a non-zero exit code. \n" - else - echo -e "\n Testing completed.\n" - fi - -done -cd "$ROOT" - -# Workaround for Kokoro permissions issue: delete secrets -rm testing/{test-env.sh,client-secrets.json,service-account.json} - -exit "$RTN" +exec .kokoro/test-samples-impl.sh diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a9024b15..32302e48 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,6 +12,6 @@ repos: hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.4 + rev: 3.9.0 hooks: - id: flake8 diff --git a/.trampolinerc b/.trampolinerc index 995ee291..383b6ec8 100644 --- a/.trampolinerc +++ b/.trampolinerc @@ -24,6 +24,7 @@ required_envvars+=( pass_down_envvars+=( "STAGING_BUCKET" "V2_STAGING_BUCKET" + "NOX_SESSION" ) # Prevent unintentional override on the default image. diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 201242c4..86915e5b 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -70,9 +70,14 @@ We use `nox `__ to instrument our tests. - To test your changes, run unit tests with ``nox``:: $ nox -s unit-2.7 - $ nox -s unit-3.7 + $ nox -s unit-3.8 $ ... +- Args to pytest can be passed through the nox command separated by a `--`. For + example, to run a single test:: + + $ nox -s unit-3.8 -- -k + .. note:: The unit tests and system tests are described in the @@ -93,8 +98,12 @@ On Debian/Ubuntu:: ************ Coding Style ************ +- We use the automatic code formatter ``black``. You can run it using + the nox session ``blacken``. This will eliminate many lint errors. Run via:: + + $ nox -s blacken -- PEP8 compliance, with exceptions defined in the linter configuration. +- PEP8 compliance is required, with exceptions defined in the linter configuration. If you have ``nox`` installed, you can test that you have not introduced any non-compliant code via:: @@ -133,13 +142,18 @@ Running System Tests - To run system tests, you can execute:: - $ nox -s system-3.7 + # Run all system tests + $ nox -s system-3.8 $ nox -s system-2.7 + # Run a single system test + $ nox -s system-3.8 -- -k + + .. note:: System tests are only configured to run under Python 2.7 and - Python 3.7. For expediency, we do not run them in older versions + Python 3.8. For expediency, we do not run them in older versions of Python 3. This alone will not run the tests. You'll need to change some local diff --git a/MANIFEST.in b/MANIFEST.in index e9e29d12..e783f4c6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -16,10 +16,10 @@ # Generated by synthtool. DO NOT EDIT! include README.rst LICENSE -recursive-include google *.json *.proto +recursive-include google *.json *.proto py.typed recursive-include tests * global-exclude *.py[co] global-exclude __pycache__ # Exclude scripts for samples readmegen -prune scripts/readme-gen \ No newline at end of file +prune scripts/readme-gen diff --git a/UPGRADING.md b/UPGRADING.md index 7c564789..48fd3f7c 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -17,10 +17,10 @@ The 3.0.0 release requires Python 3.6+. Methods expect request objects. We provide a script that will convert most common use cases. -* Install the library +* Install the library and `libcst`. ```py -python3 -m pip install google-cloud-translate +python3 -m pip install google-cloud-translate libcst ``` * The script `fixup_translation_{version}_keywords.py` is shipped with the library. It expects diff --git a/docs/translate_v3/services.rst b/docs/translate_v3/services.rst index ce46a05d..f457bf2c 100644 --- a/docs/translate_v3/services.rst +++ b/docs/translate_v3/services.rst @@ -1,6 +1,6 @@ Services for Google Cloud Translate v3 API ========================================== +.. toctree:: + :maxdepth: 2 -.. automodule:: google.cloud.translate_v3.services.translation_service - :members: - :inherited-members: + translation_service diff --git a/docs/translate_v3/translation_service.rst b/docs/translate_v3/translation_service.rst new file mode 100644 index 00000000..0a3597fd --- /dev/null +++ b/docs/translate_v3/translation_service.rst @@ -0,0 +1,11 @@ +TranslationService +------------------------------------ + +.. automodule:: google.cloud.translate_v3.services.translation_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.translate_v3.services.translation_service.pagers + :members: + :inherited-members: diff --git a/docs/translate_v3/types.rst b/docs/translate_v3/types.rst index b919f55c..35bd3cbf 100644 --- a/docs/translate_v3/types.rst +++ b/docs/translate_v3/types.rst @@ -3,4 +3,5 @@ Types for Google Cloud Translate v3 API .. automodule:: google.cloud.translate_v3.types :members: + :undoc-members: :show-inheritance: diff --git a/docs/translate_v3beta1/services.rst b/docs/translate_v3beta1/services.rst index 4fc95083..2e364924 100644 --- a/docs/translate_v3beta1/services.rst +++ b/docs/translate_v3beta1/services.rst @@ -1,6 +1,6 @@ Services for Google Cloud Translate v3beta1 API =============================================== +.. toctree:: + :maxdepth: 2 -.. automodule:: google.cloud.translate_v3beta1.services.translation_service - :members: - :inherited-members: + translation_service diff --git a/docs/translate_v3beta1/translation_service.rst b/docs/translate_v3beta1/translation_service.rst new file mode 100644 index 00000000..cfe3524b --- /dev/null +++ b/docs/translate_v3beta1/translation_service.rst @@ -0,0 +1,11 @@ +TranslationService +------------------------------------ + +.. automodule:: google.cloud.translate_v3beta1.services.translation_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.translate_v3beta1.services.translation_service.pagers + :members: + :inherited-members: diff --git a/docs/translate_v3beta1/types.rst b/docs/translate_v3beta1/types.rst index b5640f8f..f5d6b49a 100644 --- a/docs/translate_v3beta1/types.rst +++ b/docs/translate_v3beta1/types.rst @@ -3,4 +3,5 @@ Types for Google Cloud Translate v3beta1 API .. automodule:: google.cloud.translate_v3beta1.types :members: + :undoc-members: :show-inheritance: diff --git a/google/cloud/translate_v3/services/translation_service/async_client.py b/google/cloud/translate_v3/services/translation_service/async_client.py index 85656a02..d293e203 100644 --- a/google/cloud/translate_v3/services/translation_service/async_client.py +++ b/google/cloud/translate_v3/services/translation_service/async_client.py @@ -79,7 +79,36 @@ class TranslationServiceAsyncClient: TranslationServiceClient.parse_common_location_path ) - from_service_account_file = TranslationServiceClient.from_service_account_file + @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: + TranslationServiceAsyncClient: The constructed client. + """ + return TranslationServiceClient.from_service_account_info.__func__(TranslationServiceAsyncClient, 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: + TranslationServiceAsyncClient: The constructed client. + """ + return TranslationServiceClient.from_service_account_file.__func__(TranslationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -161,7 +190,7 @@ async def translate_text( r"""Translates input text and returns translated text. Args: - request (:class:`~.translation_service.TranslateTextRequest`): + request (:class:`google.cloud.translate_v3.types.TranslateTextRequest`): The request object. The request message for synchronous translation. parent (:class:`str`): @@ -181,6 +210,7 @@ async def translate_text( Models and glossaries must be within the same region (have same location-id), otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -189,6 +219,7 @@ async def translate_text( use for translation of the input text, set to one of the language codes listed in Language Support. + This corresponds to the ``target_language_code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -197,6 +228,7 @@ async def translate_text( string format. We recommend the total content be less than 30k codepoints. Use BatchTranslateText for larger text. + This corresponds to the ``contents`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -219,6 +251,7 @@ async def translate_text( If missing, the system decides which google base model to use. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -227,6 +260,7 @@ async def translate_text( text, for example, "text/html", "text/plain". If left blank, the MIME type defaults to "text/html". + This corresponds to the ``mime_type`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -239,6 +273,7 @@ async def translate_text( API attempts to identify the source language automatically and returns the source language within the response. + This corresponds to the ``source_language_code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -250,7 +285,7 @@ async def translate_text( sent along with the request as metadata. Returns: - ~.translation_service.TranslateTextResponse: + google.cloud.translate_v3.types.TranslateTextResponse: """ # Create or coerce a protobuf request object. @@ -326,7 +361,7 @@ async def detect_language( r"""Detects the language of text within a request. Args: - request (:class:`~.translation_service.DetectLanguageRequest`): + request (:class:`google.cloud.translate_v3.types.DetectLanguageRequest`): The request object. The request message for language detection. parent (:class:`str`): @@ -344,6 +379,7 @@ async def detect_language( Only models within the same region (has same location-id) can be used. Otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -358,6 +394,7 @@ async def detect_language( ``projects/{project-number-or-id}/locations/{location-id}/models/language-detection/default``. If not specified, the default model is used. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -366,12 +403,14 @@ async def detect_language( text, for example, "text/html", "text/plain". If left blank, the MIME type defaults to "text/html". + This corresponds to the ``mime_type`` field on the ``request`` instance; if ``request`` is provided, this should not be set. content (:class:`str`): The content of the input stored as a string. + This corresponds to the ``content`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -383,7 +422,7 @@ async def detect_language( sent along with the request as metadata. Returns: - ~.translation_service.DetectLanguageResponse: + google.cloud.translate_v3.types.DetectLanguageResponse: The response message for language detection. @@ -447,7 +486,7 @@ async def get_supported_languages( translation. Args: - request (:class:`~.translation_service.GetSupportedLanguagesRequest`): + request (:class:`google.cloud.translate_v3.types.GetSupportedLanguagesRequest`): The request object. The request message for discovering supported languages. parent (:class:`str`): @@ -466,6 +505,7 @@ async def get_supported_languages( Only models within the same region (have same location-id) can be used, otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -484,6 +524,7 @@ async def get_supported_languages( Returns languages supported by the specified model. If missing, we get supported languages of Google general base (PBMT) model. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -493,6 +534,7 @@ async def get_supported_languages( of supported languages. If missing, then display names are not returned in a response. + This corresponds to the ``display_language_code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -504,7 +546,7 @@ async def get_supported_languages( sent along with the request as metadata. Returns: - ~.translation_service.SupportedLanguages: + google.cloud.translate_v3.types.SupportedLanguages: The response message for discovering supported languages. @@ -542,6 +584,7 @@ async def get_supported_languages( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -578,7 +621,7 @@ async def batch_translate_text( of the call. Args: - request (:class:`~.translation_service.BatchTranslateTextRequest`): + request (:class:`google.cloud.translate_v3.types.BatchTranslateTextRequest`): The request object. The batch translation request. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -588,15 +631,13 @@ async def batch_translate_text( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.translation_service.BatchTranslateResponse``: - Stored in the - [google.longrunning.Operation.response][google.longrunning.Operation.response] - field returned by BatchTranslateText if at least one - sentence is translated successfully. + The result type for the operation will be :class:`google.cloud.translate_v3.types.BatchTranslateResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by BatchTranslateText if at least one + sentence is translated successfully. """ # Create or coerce a protobuf request object. @@ -645,14 +686,14 @@ async def create_glossary( Returns NOT_FOUND, if the project doesn't exist. Args: - request (:class:`~.translation_service.CreateGlossaryRequest`): + request (:class:`google.cloud.translate_v3.types.CreateGlossaryRequest`): The request object. Request message for CreateGlossary. parent (:class:`str`): Required. The project name. This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - glossary (:class:`~.translation_service.Glossary`): + glossary (:class:`google.cloud.translate_v3.types.Glossary`): Required. The glossary to create. This corresponds to the ``glossary`` field on the ``request`` instance; if ``request`` is provided, this @@ -665,12 +706,12 @@ async def create_glossary( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.translation_service.Glossary``: Represents a - glossary built from user provided data. + :class:`google.cloud.translate_v3.types.Glossary` + Represents a glossary built from user provided data. """ # Create or coerce a protobuf request object. @@ -734,12 +775,13 @@ async def list_glossaries( doesn't exist. Args: - request (:class:`~.translation_service.ListGlossariesRequest`): + request (:class:`google.cloud.translate_v3.types.ListGlossariesRequest`): The request object. Request message for ListGlossaries. parent (:class:`str`): Required. The name of the project from which to list all of the glossaries. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -751,7 +793,7 @@ async def list_glossaries( sent along with the request as metadata. Returns: - ~.pagers.ListGlossariesAsyncPager: + google.cloud.translate_v3.services.translation_service.pagers.ListGlossariesAsyncPager: Response message for ListGlossaries. Iterating over this object will yield results and resolve additional pages @@ -787,6 +829,7 @@ async def list_glossaries( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -823,11 +866,12 @@ async def get_glossary( exist. Args: - request (:class:`~.translation_service.GetGlossaryRequest`): + request (:class:`google.cloud.translate_v3.types.GetGlossaryRequest`): The request object. Request message for GetGlossary. name (:class:`str`): Required. The name of the glossary to retrieve. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -839,7 +883,7 @@ async def get_glossary( sent along with the request as metadata. Returns: - ~.translation_service.Glossary: + google.cloud.translate_v3.types.Glossary: Represents a glossary built from user provided data. @@ -873,6 +917,7 @@ async def get_glossary( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -904,11 +949,12 @@ async def delete_glossary( doesn't exist. Args: - request (:class:`~.translation_service.DeleteGlossaryRequest`): + request (:class:`google.cloud.translate_v3.types.DeleteGlossaryRequest`): The request object. Request message for DeleteGlossary. name (:class:`str`): Required. The name of the glossary to delete. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -920,14 +966,12 @@ async def delete_glossary( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.translation_service.DeleteGlossaryResponse``: - Stored in the - [google.longrunning.Operation.response][google.longrunning.Operation.response] - field returned by DeleteGlossary. + The result type for the operation will be :class:`google.cloud.translate_v3.types.DeleteGlossaryResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by DeleteGlossary. """ # Create or coerce a protobuf request object. @@ -959,6 +1003,7 @@ async def delete_glossary( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/translate_v3/services/translation_service/client.py b/google/cloud/translate_v3/services/translation_service/client.py index 4c4aa1a6..c4637e75 100644 --- a/google/cloud/translate_v3/services/translation_service/client.py +++ b/google/cloud/translate_v3/services/translation_service/client.py @@ -115,6 +115,22 @@ def _get_default_mtls_endpoint(api_endpoint): 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: + TranslationServiceClient: 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 @@ -127,7 +143,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): kwargs: Additional arguments to pass to the constructor. Returns: - {@api.name}: The constructed client. + TranslationServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -235,10 +251,10 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.TranslationServiceTransport]): The + transport (Union[str, TranslationServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (client_options_lib.ClientOptions): Custom options for the + client_options (google.api_core.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 @@ -274,21 +290,17 @@ def __init__( util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) ) - ssl_credentials = None + client_cert_source_func = None is_mtls = False if use_client_cert: if client_options.client_cert_source: - import grpc # type: ignore - - cert, key = client_options.client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) is_mtls = True + client_cert_source_func = client_options.client_cert_source else: - creds = SslCredentials() - is_mtls = creds.is_mtls - ssl_credentials = creds.ssl_credentials if is_mtls else None + is_mtls = mtls.has_default_client_cert_source() + client_cert_source_func = ( + mtls.default_client_cert_source() if is_mtls else None + ) # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -331,7 +343,7 @@ def __init__( credentials_file=client_options.credentials_file, host=api_endpoint, scopes=client_options.scopes, - ssl_channel_credentials=ssl_credentials, + client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, ) @@ -353,10 +365,10 @@ def translate_text( r"""Translates input text and returns translated text. Args: - request (:class:`~.translation_service.TranslateTextRequest`): + request (google.cloud.translate_v3.types.TranslateTextRequest): The request object. The request message for synchronous translation. - parent (:class:`str`): + parent (str): Required. Project or location to make a call. Must refer to a caller's project. @@ -373,26 +385,29 @@ def translate_text( Models and glossaries must be within the same region (have same location-id), otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - target_language_code (:class:`str`): + target_language_code (str): Required. The BCP-47 language code to use for translation of the input text, set to one of the language codes listed in Language Support. + This corresponds to the ``target_language_code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - contents (:class:`Sequence[str]`): + contents (Sequence[str]): Required. The content of the input in string format. We recommend the total content be less than 30k codepoints. Use BatchTranslateText for larger text. + This corresponds to the ``contents`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - model (:class:`str`): + model (str): Optional. The ``model`` type requested for this translation. @@ -411,18 +426,20 @@ def translate_text( If missing, the system decides which google base model to use. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - mime_type (:class:`str`): + mime_type (str): Optional. The format of the source text, for example, "text/html", "text/plain". If left blank, the MIME type defaults to "text/html". + This corresponds to the ``mime_type`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - source_language_code (:class:`str`): + source_language_code (str): Optional. The BCP-47 language code of the input text if known, for example, "en-US" or "sr-Latn". Supported language @@ -431,6 +448,7 @@ def translate_text( API attempts to identify the source language automatically and returns the source language within the response. + This corresponds to the ``source_language_code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -442,7 +460,7 @@ def translate_text( sent along with the request as metadata. Returns: - ~.translation_service.TranslateTextResponse: + google.cloud.translate_v3.types.TranslateTextResponse: """ # Create or coerce a protobuf request object. @@ -478,6 +496,8 @@ def translate_text( request.parent = parent if target_language_code is not None: request.target_language_code = target_language_code + if contents is not None: + request.contents = contents if model is not None: request.model = model if mime_type is not None: @@ -485,9 +505,6 @@ def translate_text( if source_language_code is not None: request.source_language_code = source_language_code - if contents: - request.contents.extend(contents) - # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. rpc = self._transport._wrapped_methods[self._transport.translate_text] @@ -519,10 +536,10 @@ def detect_language( r"""Detects the language of text within a request. Args: - request (:class:`~.translation_service.DetectLanguageRequest`): + request (google.cloud.translate_v3.types.DetectLanguageRequest): The request object. The request message for language detection. - parent (:class:`str`): + parent (str): Required. Project or location to make a call. Must refer to a caller's project. @@ -537,10 +554,11 @@ def detect_language( Only models within the same region (has same location-id) can be used. Otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - model (:class:`str`): + model (str): Optional. The language detection model to be used. Format: @@ -551,20 +569,23 @@ def detect_language( ``projects/{project-number-or-id}/locations/{location-id}/models/language-detection/default``. If not specified, the default model is used. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - mime_type (:class:`str`): + mime_type (str): Optional. The format of the source text, for example, "text/html", "text/plain". If left blank, the MIME type defaults to "text/html". + This corresponds to the ``mime_type`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - content (:class:`str`): + content (str): The content of the input stored as a string. + This corresponds to the ``content`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -576,7 +597,7 @@ def detect_language( sent along with the request as metadata. Returns: - ~.translation_service.DetectLanguageResponse: + google.cloud.translate_v3.types.DetectLanguageResponse: The response message for language detection. @@ -641,10 +662,10 @@ def get_supported_languages( translation. Args: - request (:class:`~.translation_service.GetSupportedLanguagesRequest`): + request (google.cloud.translate_v3.types.GetSupportedLanguagesRequest): The request object. The request message for discovering supported languages. - parent (:class:`str`): + parent (str): Required. Project or location to make a call. Must refer to a caller's project. @@ -660,10 +681,11 @@ def get_supported_languages( Only models within the same region (have same location-id) can be used, otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - model (:class:`str`): + model (str): Optional. Get supported languages of this model. The format depends on model type: @@ -678,15 +700,17 @@ def get_supported_languages( Returns languages supported by the specified model. If missing, we get supported languages of Google general base (PBMT) model. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - display_language_code (:class:`str`): + display_language_code (str): Optional. The language to use to return localized, human readable names of supported languages. If missing, then display names are not returned in a response. + This corresponds to the ``display_language_code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -698,7 +722,7 @@ def get_supported_languages( sent along with the request as metadata. Returns: - ~.translation_service.SupportedLanguages: + google.cloud.translate_v3.types.SupportedLanguages: The response message for discovering supported languages. @@ -765,7 +789,7 @@ def batch_translate_text( of the call. Args: - request (:class:`~.translation_service.BatchTranslateTextRequest`): + request (google.cloud.translate_v3.types.BatchTranslateTextRequest): The request object. The batch translation request. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -775,15 +799,13 @@ def batch_translate_text( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.translation_service.BatchTranslateResponse``: - Stored in the - [google.longrunning.Operation.response][google.longrunning.Operation.response] - field returned by BatchTranslateText if at least one - sentence is translated successfully. + The result type for the operation will be :class:`google.cloud.translate_v3.types.BatchTranslateResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by BatchTranslateText if at least one + sentence is translated successfully. """ # Create or coerce a protobuf request object. @@ -833,14 +855,14 @@ def create_glossary( Returns NOT_FOUND, if the project doesn't exist. Args: - request (:class:`~.translation_service.CreateGlossaryRequest`): + request (google.cloud.translate_v3.types.CreateGlossaryRequest): The request object. Request message for CreateGlossary. - parent (:class:`str`): + parent (str): Required. The project name. This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - glossary (:class:`~.translation_service.Glossary`): + glossary (google.cloud.translate_v3.types.Glossary): Required. The glossary to create. This corresponds to the ``glossary`` field on the ``request`` instance; if ``request`` is provided, this @@ -853,12 +875,12 @@ def create_glossary( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.translation_service.Glossary``: Represents a - glossary built from user provided data. + :class:`google.cloud.translate_v3.types.Glossary` + Represents a glossary built from user provided data. """ # Create or coerce a protobuf request object. @@ -923,12 +945,13 @@ def list_glossaries( doesn't exist. Args: - request (:class:`~.translation_service.ListGlossariesRequest`): + request (google.cloud.translate_v3.types.ListGlossariesRequest): The request object. Request message for ListGlossaries. - parent (:class:`str`): + parent (str): Required. The name of the project from which to list all of the glossaries. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -940,7 +963,7 @@ def list_glossaries( sent along with the request as metadata. Returns: - ~.pagers.ListGlossariesPager: + google.cloud.translate_v3.services.translation_service.pagers.ListGlossariesPager: Response message for ListGlossaries. Iterating over this object will yield results and resolve additional pages @@ -1005,11 +1028,12 @@ def get_glossary( exist. Args: - request (:class:`~.translation_service.GetGlossaryRequest`): + request (google.cloud.translate_v3.types.GetGlossaryRequest): The request object. Request message for GetGlossary. - name (:class:`str`): + name (str): Required. The name of the glossary to retrieve. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1021,7 +1045,7 @@ def get_glossary( sent along with the request as metadata. Returns: - ~.translation_service.Glossary: + google.cloud.translate_v3.types.Glossary: Represents a glossary built from user provided data. @@ -1079,11 +1103,12 @@ def delete_glossary( doesn't exist. Args: - request (:class:`~.translation_service.DeleteGlossaryRequest`): + request (google.cloud.translate_v3.types.DeleteGlossaryRequest): The request object. Request message for DeleteGlossary. - name (:class:`str`): + name (str): Required. The name of the glossary to delete. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1095,14 +1120,12 @@ def delete_glossary( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.translation_service.DeleteGlossaryResponse``: - Stored in the - [google.longrunning.Operation.response][google.longrunning.Operation.response] - field returned by DeleteGlossary. + The result type for the operation will be :class:`google.cloud.translate_v3.types.DeleteGlossaryResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by DeleteGlossary. """ # Create or coerce a protobuf request object. diff --git a/google/cloud/translate_v3/services/translation_service/pagers.py b/google/cloud/translate_v3/services/translation_service/pagers.py index 51347139..d6d24694 100644 --- a/google/cloud/translate_v3/services/translation_service/pagers.py +++ b/google/cloud/translate_v3/services/translation_service/pagers.py @@ -15,7 +15,16 @@ # limitations under the License. # -from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple +from typing import ( + Any, + AsyncIterable, + Awaitable, + Callable, + Iterable, + Sequence, + Tuple, + Optional, +) from google.cloud.translate_v3.types import translation_service @@ -24,7 +33,7 @@ class ListGlossariesPager: """A pager for iterating through ``list_glossaries`` requests. This class thinly wraps an initial - :class:`~.translation_service.ListGlossariesResponse` object, and + :class:`google.cloud.translate_v3.types.ListGlossariesResponse` object, and provides an ``__iter__`` method to iterate through its ``glossaries`` field. @@ -33,7 +42,7 @@ class ListGlossariesPager: through the ``glossaries`` field on the corresponding responses. - All the usual :class:`~.translation_service.ListGlossariesResponse` + All the usual :class:`google.cloud.translate_v3.types.ListGlossariesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -51,9 +60,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.translation_service.ListGlossariesRequest`): + request (google.cloud.translate_v3.types.ListGlossariesRequest): The initial request object. - response (:class:`~.translation_service.ListGlossariesResponse`): + response (google.cloud.translate_v3.types.ListGlossariesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -86,7 +95,7 @@ class ListGlossariesAsyncPager: """A pager for iterating through ``list_glossaries`` requests. This class thinly wraps an initial - :class:`~.translation_service.ListGlossariesResponse` object, and + :class:`google.cloud.translate_v3.types.ListGlossariesResponse` object, and provides an ``__aiter__`` method to iterate through its ``glossaries`` field. @@ -95,7 +104,7 @@ class ListGlossariesAsyncPager: through the ``glossaries`` field on the corresponding responses. - All the usual :class:`~.translation_service.ListGlossariesResponse` + All the usual :class:`google.cloud.translate_v3.types.ListGlossariesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -113,9 +122,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.translation_service.ListGlossariesRequest`): + request (google.cloud.translate_v3.types.ListGlossariesRequest): The initial request object. - response (:class:`~.translation_service.ListGlossariesResponse`): + response (google.cloud.translate_v3.types.ListGlossariesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/translate_v3/services/translation_service/transports/base.py b/google/cloud/translate_v3/services/translation_service/transports/base.py index 204e32ec..1107abf8 100644 --- a/google/cloud/translate_v3/services/translation_service/transports/base.py +++ b/google/cloud/translate_v3/services/translation_service/transports/base.py @@ -72,10 +72,10 @@ def __init__( scope (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 + 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. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -83,6 +83,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -92,20 +95,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -124,6 +124,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -145,6 +146,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -158,6 +160,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -171,6 +174,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, diff --git a/google/cloud/translate_v3/services/translation_service/transports/grpc.py b/google/cloud/translate_v3/services/translation_service/transports/grpc.py index 7efc5785..2e0a86b0 100644 --- a/google/cloud/translate_v3/services/translation_service/transports/grpc.py +++ b/google/cloud/translate_v3/services/translation_service/transports/grpc.py @@ -59,6 +59,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -89,6 +90,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for 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 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): @@ -103,72 +108,61 @@ def __init__( 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] = {} + self._operations_client = None + + 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: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # 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 - elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) + 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 - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials + 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 + ) - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # 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, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -176,18 +170,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - self._operations_client = None - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -201,7 +185,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + 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 diff --git a/google/cloud/translate_v3/services/translation_service/transports/grpc_asyncio.py b/google/cloud/translate_v3/services/translation_service/transports/grpc_asyncio.py index d63d8c0b..442b84dc 100644 --- a/google/cloud/translate_v3/services/translation_service/transports/grpc_asyncio.py +++ b/google/cloud/translate_v3/services/translation_service/transports/grpc_asyncio.py @@ -63,7 +63,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + 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 @@ -103,6 +103,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -134,12 +135,16 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for 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 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 + 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: @@ -148,72 +153,61 @@ def __init__( 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] = {} + self._operations_client = None + + 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: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # 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 - elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) + 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 - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials + 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 + ) - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # 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, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -221,18 +215,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} - self._operations_client = None + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/translate_v3/types/__init__.py b/google/cloud/translate_v3/types/__init__.py index ac1da5b4..98fddfeb 100644 --- a/google/cloud/translate_v3/types/__init__.py +++ b/google/cloud/translate_v3/types/__init__.py @@ -16,61 +16,61 @@ # from .translation_service import ( - TranslateTextGlossaryConfig, - TranslateTextRequest, - TranslateTextResponse, - Translation, - DetectLanguageRequest, - DetectedLanguage, - DetectLanguageResponse, - GetSupportedLanguagesRequest, - SupportedLanguages, - SupportedLanguage, - GcsSource, - InputConfig, - GcsDestination, - OutputConfig, - BatchTranslateTextRequest, BatchTranslateMetadata, BatchTranslateResponse, - GlossaryInputConfig, - Glossary, + BatchTranslateTextRequest, + CreateGlossaryMetadata, CreateGlossaryRequest, - GetGlossaryRequest, + DeleteGlossaryMetadata, DeleteGlossaryRequest, + DeleteGlossaryResponse, + DetectedLanguage, + DetectLanguageRequest, + DetectLanguageResponse, + GcsDestination, + GcsSource, + GetGlossaryRequest, + GetSupportedLanguagesRequest, + Glossary, + GlossaryInputConfig, + InputConfig, ListGlossariesRequest, ListGlossariesResponse, - CreateGlossaryMetadata, - DeleteGlossaryMetadata, - DeleteGlossaryResponse, + OutputConfig, + SupportedLanguage, + SupportedLanguages, + TranslateTextGlossaryConfig, + TranslateTextRequest, + TranslateTextResponse, + Translation, ) __all__ = ( - "TranslateTextGlossaryConfig", - "TranslateTextRequest", - "TranslateTextResponse", - "Translation", - "DetectLanguageRequest", - "DetectedLanguage", - "DetectLanguageResponse", - "GetSupportedLanguagesRequest", - "SupportedLanguages", - "SupportedLanguage", - "GcsSource", - "InputConfig", - "GcsDestination", - "OutputConfig", - "BatchTranslateTextRequest", "BatchTranslateMetadata", "BatchTranslateResponse", - "GlossaryInputConfig", - "Glossary", + "BatchTranslateTextRequest", + "CreateGlossaryMetadata", "CreateGlossaryRequest", - "GetGlossaryRequest", + "DeleteGlossaryMetadata", "DeleteGlossaryRequest", + "DeleteGlossaryResponse", + "DetectedLanguage", + "DetectLanguageRequest", + "DetectLanguageResponse", + "GcsDestination", + "GcsSource", + "GetGlossaryRequest", + "GetSupportedLanguagesRequest", + "Glossary", + "GlossaryInputConfig", + "InputConfig", "ListGlossariesRequest", "ListGlossariesResponse", - "CreateGlossaryMetadata", - "DeleteGlossaryMetadata", - "DeleteGlossaryResponse", + "OutputConfig", + "SupportedLanguage", + "SupportedLanguages", + "TranslateTextGlossaryConfig", + "TranslateTextRequest", + "TranslateTextResponse", + "Translation", ) diff --git a/google/cloud/translate_v3/types/translation_service.py b/google/cloud/translate_v3/types/translation_service.py index 992223f4..3740856f 100644 --- a/google/cloud/translate_v3/types/translation_service.py +++ b/google/cloud/translate_v3/types/translation_service.py @@ -133,12 +133,12 @@ class TranslateTextRequest(proto.Message): If missing, the system decides which google base model to use. - glossary_config (~.translation_service.TranslateTextGlossaryConfig): + glossary_config (google.cloud.translate_v3.types.TranslateTextGlossaryConfig): Optional. Glossary to be applied. The glossary must be within the same region (have the same location-id) as the model, otherwise an INVALID_ARGUMENT (400) error is returned. - labels (Sequence[~.translation_service.TranslateTextRequest.LabelsEntry]): + labels (Sequence[google.cloud.translate_v3.types.TranslateTextRequest.LabelsEntry]): Optional. The labels with user-defined metadata for the request. Label keys and values can be no longer than 63 @@ -175,11 +175,11 @@ class TranslateTextResponse(proto.Message): r""" Attributes: - translations (Sequence[~.translation_service.Translation]): + translations (Sequence[google.cloud.translate_v3.types.Translation]): Text translation responses with no glossary applied. This field has the same length as [``contents``][google.cloud.translation.v3.TranslateTextRequest.contents]. - glossary_translations (Sequence[~.translation_service.Translation]): + glossary_translations (Sequence[google.cloud.translate_v3.types.Translation]): Text translation responses if a glossary is provided in the request. This can be the same as [``translations``][google.cloud.translation.v3.TranslateTextResponse.translations] @@ -216,7 +216,7 @@ class Translation(proto.Message): request. If the source language was passed, auto-detection of the language does not occur and this field is empty. - glossary_config (~.translation_service.TranslateTextGlossaryConfig): + glossary_config (google.cloud.translate_v3.types.TranslateTextGlossaryConfig): The ``glossary_config`` used for this translation. """ @@ -266,7 +266,7 @@ class DetectLanguageRequest(proto.Message): Optional. The format of the source text, for example, "text/html", "text/plain". If left blank, the MIME type defaults to "text/html". - labels (Sequence[~.translation_service.DetectLanguageRequest.LabelsEntry]): + labels (Sequence[google.cloud.translate_v3.types.DetectLanguageRequest.LabelsEntry]): Optional. The labels with user-defined metadata for the request. Label keys and values can be no longer than 63 @@ -312,7 +312,7 @@ class DetectLanguageResponse(proto.Message): r"""The response message for language detection. Attributes: - languages (Sequence[~.translation_service.DetectedLanguage]): + languages (Sequence[google.cloud.translate_v3.types.DetectedLanguage]): A list of detected languages sorted by detection confidence in descending order. The most probable language first. @@ -376,7 +376,7 @@ class SupportedLanguages(proto.Message): r"""The response message for discovering supported languages. Attributes: - languages (Sequence[~.translation_service.SupportedLanguage]): + languages (Sequence[google.cloud.translate_v3.types.SupportedLanguage]): A list of supported language responses. This list contains an entry for each language the Translation API supports. @@ -438,7 +438,7 @@ class InputConfig(proto.Message): "text/html" is used if mime_type is missing. For ``.html``, this field must be "text/html" or empty. For ``.txt``, this field must be "text/plain" or empty. - gcs_source (~.translation_service.GcsSource): + gcs_source (google.cloud.translate_v3.types.GcsSource): Required. Google Cloud Storage location for the source input. This can be a single file (for example, ``gs://translation-test/input.tsv``) or a wildcard (for @@ -485,7 +485,7 @@ class OutputConfig(proto.Message): r"""Output configuration for BatchTranslateText request. Attributes: - gcs_destination (~.translation_service.GcsDestination): + gcs_destination (google.cloud.translate_v3.types.GcsDestination): Google Cloud Storage destination for output content. For every single input file (for example, gs://a/b/c.[extension]), we generate at most 2 \* n output @@ -586,7 +586,7 @@ class BatchTranslateTextRequest(proto.Message): target_language_codes (Sequence[str]): Required. Specify up to 10 language codes here. - models (Sequence[~.translation_service.BatchTranslateTextRequest.ModelsEntry]): + models (Sequence[google.cloud.translate_v3.types.BatchTranslateTextRequest.ModelsEntry]): Optional. The models to use for translation. Map's key is target language code. Map's value is model name. Value can be a built-in general model, or an AutoML Translation model. @@ -602,21 +602,21 @@ class BatchTranslateTextRequest(proto.Message): If the map is empty or a specific model is not requested for a language pair, then default google model (nmt) is used. - input_configs (Sequence[~.translation_service.InputConfig]): + input_configs (Sequence[google.cloud.translate_v3.types.InputConfig]): Required. Input configurations. The total number of files matched should be <= 1000. The total content size should be <= 100M Unicode codepoints. The files must use UTF-8 encoding. - output_config (~.translation_service.OutputConfig): + output_config (google.cloud.translate_v3.types.OutputConfig): Required. Output configuration. If 2 input configs match to the same file (that is, same input path), we don't generate output for duplicate inputs. - glossaries (Sequence[~.translation_service.BatchTranslateTextRequest.GlossariesEntry]): + glossaries (Sequence[google.cloud.translate_v3.types.BatchTranslateTextRequest.GlossariesEntry]): Optional. Glossaries to be applied for translation. It's keyed by target language code. - labels (Sequence[~.translation_service.BatchTranslateTextRequest.LabelsEntry]): + labels (Sequence[google.cloud.translate_v3.types.BatchTranslateTextRequest.LabelsEntry]): Optional. The labels with user-defined metadata for the request. Label keys and values can be no longer than 63 @@ -653,7 +653,7 @@ class BatchTranslateMetadata(proto.Message): r"""State metadata for the batch translation operation. Attributes: - state (~.translation_service.BatchTranslateMetadata.State): + state (google.cloud.translate_v3.types.BatchTranslateMetadata.State): The state of the operation. translated_characters (int): Number of successfully translated characters @@ -667,7 +667,7 @@ class BatchTranslateMetadata(proto.Message): codepoints from input files times the number of target languages and appears here shortly after the call is submitted. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): Time when the operation was submitted. """ @@ -707,9 +707,9 @@ class BatchTranslateResponse(proto.Message): failed_characters (int): Number of characters that have failed to process (Unicode codepoints). - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): Time when the operation was submitted. - end_time (~.timestamp.Timestamp): + end_time (google.protobuf.timestamp_pb2.Timestamp): The time when the operation is finished and [google.longrunning.Operation.done][google.longrunning.Operation.done] is set to true. @@ -730,7 +730,7 @@ class GlossaryInputConfig(proto.Message): r"""Input configuration for glossaries. Attributes: - gcs_source (~.translation_service.GcsSource): + gcs_source (google.cloud.translate_v3.types.GcsSource): Required. Google Cloud Storage location of glossary data. File format is determined based on the filename extension. API returns [google.rpc.Code.INVALID_ARGUMENT] for @@ -771,20 +771,20 @@ class Glossary(proto.Message): Required. The resource name of the glossary. Glossary names have the form ``projects/{project-number-or-id}/locations/{location-id}/glossaries/{glossary-id}``. - language_pair (~.translation_service.Glossary.LanguageCodePair): + language_pair (google.cloud.translate_v3.types.Glossary.LanguageCodePair): Used with unidirectional glossaries. - language_codes_set (~.translation_service.Glossary.LanguageCodesSet): + language_codes_set (google.cloud.translate_v3.types.Glossary.LanguageCodesSet): Used with equivalent term set glossaries. - input_config (~.translation_service.GlossaryInputConfig): + input_config (google.cloud.translate_v3.types.GlossaryInputConfig): Required. Provides examples to build the glossary from. Total glossary must not exceed 10M Unicode codepoints. entry_count (int): Output only. The number of entries defined in the glossary. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): Output only. When CreateGlossary was called. - end_time (~.timestamp.Timestamp): + end_time (google.protobuf.timestamp_pb2.Timestamp): Output only. When the glossary creation was finished. """ @@ -845,7 +845,7 @@ class CreateGlossaryRequest(proto.Message): Attributes: parent (str): Required. The project name. - glossary (~.translation_service.Glossary): + glossary (google.cloud.translate_v3.types.Glossary): Required. The glossary to create. """ @@ -915,7 +915,7 @@ class ListGlossariesResponse(proto.Message): r"""Response message for ListGlossaries. Attributes: - glossaries (Sequence[~.translation_service.Glossary]): + glossaries (Sequence[google.cloud.translate_v3.types.Glossary]): The list of glossaries for a project. next_page_token (str): A token to retrieve a page of results. Pass this value in @@ -942,10 +942,10 @@ class CreateGlossaryMetadata(proto.Message): name (str): The name of the glossary that is being created. - state (~.translation_service.CreateGlossaryMetadata.State): + state (google.cloud.translate_v3.types.CreateGlossaryMetadata.State): The current state of the glossary creation operation. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): The time when the operation was submitted to the server. """ @@ -977,10 +977,10 @@ class DeleteGlossaryMetadata(proto.Message): name (str): The name of the glossary that is being deleted. - state (~.translation_service.DeleteGlossaryMetadata.State): + state (google.cloud.translate_v3.types.DeleteGlossaryMetadata.State): The current state of the glossary deletion operation. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): The time when the operation was submitted to the server. """ @@ -1011,10 +1011,10 @@ class DeleteGlossaryResponse(proto.Message): Attributes: name (str): The name of the deleted glossary. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): The time when the operation was submitted to the server. - end_time (~.timestamp.Timestamp): + end_time (google.protobuf.timestamp_pb2.Timestamp): The time when the glossary deletion is finished and [google.longrunning.Operation.done][google.longrunning.Operation.done] is set to true. diff --git a/google/cloud/translate_v3beta1/__init__.py b/google/cloud/translate_v3beta1/__init__.py index b7cd2fe0..80a31e78 100644 --- a/google/cloud/translate_v3beta1/__init__.py +++ b/google/cloud/translate_v3beta1/__init__.py @@ -16,6 +16,11 @@ # from .services.translation_service import TranslationServiceClient +from .types.translation_service import BatchDocumentInputConfig +from .types.translation_service import BatchDocumentOutputConfig +from .types.translation_service import BatchTranslateDocumentMetadata +from .types.translation_service import BatchTranslateDocumentRequest +from .types.translation_service import BatchTranslateDocumentResponse from .types.translation_service import BatchTranslateMetadata from .types.translation_service import BatchTranslateResponse from .types.translation_service import BatchTranslateTextRequest @@ -27,6 +32,9 @@ from .types.translation_service import DetectLanguageRequest from .types.translation_service import DetectLanguageResponse from .types.translation_service import DetectedLanguage +from .types.translation_service import DocumentInputConfig +from .types.translation_service import DocumentOutputConfig +from .types.translation_service import DocumentTranslation from .types.translation_service import GcsDestination from .types.translation_service import GcsSource from .types.translation_service import GetGlossaryRequest @@ -39,6 +47,8 @@ from .types.translation_service import OutputConfig from .types.translation_service import SupportedLanguage from .types.translation_service import SupportedLanguages +from .types.translation_service import TranslateDocumentRequest +from .types.translation_service import TranslateDocumentResponse from .types.translation_service import TranslateTextGlossaryConfig from .types.translation_service import TranslateTextRequest from .types.translation_service import TranslateTextResponse @@ -46,6 +56,11 @@ __all__ = ( + "BatchDocumentInputConfig", + "BatchDocumentOutputConfig", + "BatchTranslateDocumentMetadata", + "BatchTranslateDocumentRequest", + "BatchTranslateDocumentResponse", "BatchTranslateMetadata", "BatchTranslateResponse", "BatchTranslateTextRequest", @@ -57,6 +72,9 @@ "DetectLanguageRequest", "DetectLanguageResponse", "DetectedLanguage", + "DocumentInputConfig", + "DocumentOutputConfig", + "DocumentTranslation", "GcsDestination", "GcsSource", "GetGlossaryRequest", @@ -69,6 +87,8 @@ "OutputConfig", "SupportedLanguage", "SupportedLanguages", + "TranslateDocumentRequest", + "TranslateDocumentResponse", "TranslateTextGlossaryConfig", "TranslateTextRequest", "TranslateTextResponse", diff --git a/google/cloud/translate_v3beta1/services/translation_service/async_client.py b/google/cloud/translate_v3beta1/services/translation_service/async_client.py index 114f7ceb..f4b201cf 100644 --- a/google/cloud/translate_v3beta1/services/translation_service/async_client.py +++ b/google/cloud/translate_v3beta1/services/translation_service/async_client.py @@ -79,7 +79,36 @@ class TranslationServiceAsyncClient: TranslationServiceClient.parse_common_location_path ) - from_service_account_file = TranslationServiceClient.from_service_account_file + @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: + TranslationServiceAsyncClient: The constructed client. + """ + return TranslationServiceClient.from_service_account_info.__func__(TranslationServiceAsyncClient, 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: + TranslationServiceAsyncClient: The constructed client. + """ + return TranslationServiceClient.from_service_account_file.__func__(TranslationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -155,7 +184,7 @@ async def translate_text( r"""Translates input text and returns translated text. Args: - request (:class:`~.translation_service.TranslateTextRequest`): + request (:class:`google.cloud.translate_v3beta1.types.TranslateTextRequest`): The request object. The request message for synchronous translation. @@ -166,7 +195,7 @@ async def translate_text( sent along with the request as metadata. Returns: - ~.translation_service.TranslateTextResponse: + google.cloud.translate_v3beta1.types.TranslateTextResponse: """ # Create or coerce a protobuf request object. @@ -207,7 +236,7 @@ async def detect_language( r"""Detects the language of text within a request. Args: - request (:class:`~.translation_service.DetectLanguageRequest`): + request (:class:`google.cloud.translate_v3beta1.types.DetectLanguageRequest`): The request object. The request message for language detection. parent (:class:`str`): @@ -215,16 +244,17 @@ async def detect_language( to a caller's project. Format: - ``projects/{project-id}/locations/{location-id}`` or - ``projects/{project-id}``. + ``projects/{project-number-or-id}/locations/{location-id}`` + or ``projects/{project-number-or-id}``. For global calls, use - ``projects/{project-id}/locations/global`` or - ``projects/{project-id}``. + ``projects/{project-number-or-id}/locations/global`` or + ``projects/{project-number-or-id}``. - Only models within the same region (has same - location-id) can be used. Otherwise an INVALID_ARGUMENT + Only models within the same region, which have the same + location-id, can be used. Otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -232,13 +262,14 @@ async def detect_language( Optional. The language detection model to be used. Format: - ``projects/{project-id}/locations/{location-id}/models/language-detection/{model-id}`` + ``projects/{project-number-or-id}/locations/{location-id}/models/language-detection/{model-id}`` Only one language detection model is currently supported: - ``projects/{project-id}/locations/{location-id}/models/language-detection/default``. + ``projects/{project-number-or-id}/locations/{location-id}/models/language-detection/default``. If not specified, the default model is used. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -247,6 +278,7 @@ async def detect_language( text, for example, "text/html", "text/plain". If left blank, the MIME type defaults to "text/html". + This corresponds to the ``mime_type`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -258,7 +290,7 @@ async def detect_language( sent along with the request as metadata. Returns: - ~.translation_service.DetectLanguageResponse: + google.cloud.translate_v3beta1.types.DetectLanguageResponse: The response message for language detection. @@ -320,25 +352,26 @@ async def get_supported_languages( translation. Args: - request (:class:`~.translation_service.GetSupportedLanguagesRequest`): + request (:class:`google.cloud.translate_v3beta1.types.GetSupportedLanguagesRequest`): The request object. The request message for discovering supported languages. parent (:class:`str`): Required. Project or location to make a call. Must refer to a caller's project. - Format: ``projects/{project-id}`` or - ``projects/{project-id}/locations/{location-id}``. + Format: ``projects/{project-number-or-id}`` or + ``projects/{project-number-or-id}/locations/{location-id}``. For global calls, use - ``projects/{project-id}/locations/global`` or - ``projects/{project-id}``. + ``projects/{project-number-or-id}/locations/global`` or + ``projects/{project-number-or-id}``. Non-global location is required for AutoML models. Only models within the same region (have same location-id) can be used, otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -348,6 +381,7 @@ async def get_supported_languages( of supported languages. If missing, then display names are not returned in a response. + This corresponds to the ``display_language_code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -357,15 +391,16 @@ async def get_supported_languages( The format depends on model type: - AutoML Translation models: - ``projects/{project-id}/locations/{location-id}/models/{model-id}`` + ``projects/{project-number-or-id}/locations/{location-id}/models/{model-id}`` - General (built-in) models: - ``projects/{project-id}/locations/{location-id}/models/general/nmt``, - ``projects/{project-id}/locations/{location-id}/models/general/base`` + ``projects/{project-number-or-id}/locations/{location-id}/models/general/nmt``, + ``projects/{project-number-or-id}/locations/{location-id}/models/general/base`` Returns languages supported by the specified model. If missing, we get supported languages of Google general base (PBMT) model. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -377,7 +412,7 @@ async def get_supported_languages( sent along with the request as metadata. Returns: - ~.translation_service.SupportedLanguages: + google.cloud.translate_v3beta1.types.SupportedLanguages: The response message for discovering supported languages. @@ -415,6 +450,7 @@ async def get_supported_languages( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -432,6 +468,56 @@ async def get_supported_languages( # Done; return the response. return response + async def translate_document( + self, + request: translation_service.TranslateDocumentRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> translation_service.TranslateDocumentResponse: + r"""Translates documents in synchronous mode. + + Args: + request (:class:`google.cloud.translate_v3beta1.types.TranslateDocumentRequest`): + The request object. A document translation request. + + 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.translate_v3beta1.types.TranslateDocumentResponse: + A translated document response + message. + + """ + # Create or coerce a protobuf request object. + + request = translation_service.TranslateDocumentRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.translate_document, + default_timeout=600.0, + 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 batch_translate_text( self, request: translation_service.BatchTranslateTextRequest = None, @@ -451,7 +537,7 @@ async def batch_translate_text( of the call. Args: - request (:class:`~.translation_service.BatchTranslateTextRequest`): + request (:class:`google.cloud.translate_v3beta1.types.BatchTranslateTextRequest`): The request object. The batch translation request. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -461,15 +547,13 @@ async def batch_translate_text( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.translation_service.BatchTranslateResponse``: - Stored in the - [google.longrunning.Operation.response][google.longrunning.Operation.response] - field returned by BatchTranslateText if at least one - sentence is translated successfully. + The result type for the operation will be :class:`google.cloud.translate_v3beta1.types.BatchTranslateResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by BatchTranslateText if at least one + sentence is translated successfully. """ # Create or coerce a protobuf request object. @@ -504,6 +588,76 @@ async def batch_translate_text( # Done; return the response. return response + async def batch_translate_document( + self, + request: translation_service.BatchTranslateDocumentRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Translates a large volume of documents in + asynchronous batch mode. This function provides real- + time output as the inputs are being processed. If caller + cancels a request, the partial results (for an input + file, it's all or nothing) may still be available on the + specified output location. + This call returns immediately and you can use + google.longrunning.Operation.name to poll the status of + the call. + + Args: + request (:class:`google.cloud.translate_v3beta1.types.BatchTranslateDocumentRequest`): + The request object. The BatchTranslateDocument request. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.translate_v3beta1.types.BatchTranslateDocumentResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by BatchTranslateDocument if at least + one document is translated successfully. + + """ + # Create or coerce a protobuf request object. + + request = translation_service.BatchTranslateDocumentRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.batch_translate_document, + default_timeout=600.0, + 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,) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + translation_service.BatchTranslateDocumentResponse, + metadata_type=translation_service.BatchTranslateDocumentMetadata, + ) + + # Done; return the response. + return response + async def create_glossary( self, request: translation_service.CreateGlossaryRequest = None, @@ -518,14 +672,14 @@ async def create_glossary( Returns NOT_FOUND, if the project doesn't exist. Args: - request (:class:`~.translation_service.CreateGlossaryRequest`): + request (:class:`google.cloud.translate_v3beta1.types.CreateGlossaryRequest`): The request object. Request message for CreateGlossary. parent (:class:`str`): Required. The project name. This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - glossary (:class:`~.translation_service.Glossary`): + glossary (:class:`google.cloud.translate_v3beta1.types.Glossary`): Required. The glossary to create. This corresponds to the ``glossary`` field on the ``request`` instance; if ``request`` is provided, this @@ -538,12 +692,12 @@ async def create_glossary( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. The result type for the operation will be - :class:``~.translation_service.Glossary``: Represents a - glossary built from user provided data. + :class:`google.cloud.translate_v3beta1.types.Glossary` + Represents a glossary built from user provided data. """ # Create or coerce a protobuf request object. @@ -608,21 +762,47 @@ async def list_glossaries( doesn't exist. Args: - request (:class:`~.translation_service.ListGlossariesRequest`): + request (:class:`google.cloud.translate_v3beta1.types.ListGlossariesRequest`): The request object. Request message for ListGlossaries. parent (:class:`str`): Required. The name of the project from which to list all of the glossaries. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. filter (:class:`str`): Optional. Filter specifying - constraints of a list operation. - Filtering is not supported yet, and the - parameter currently has no effect. If - missing, no filtering is performed. + constraints of a list operation. Specify + the constraint by the format of + "key=value", where key must be "src" or + "tgt", and the value must be a valid + language code. For multiple + restrictions, concatenate them by "AND" + (uppercase only), such as: "src=en-US + AND tgt=zh-CN". Notice that the exact + match is used here, which means using + 'en-US' and 'en' can lead to different + results, which depends on the language + code you used when you create the + glossary. For the unidirectional + glossaries, the "src" and "tgt" add + restrictions on the source and target + language code separately. For the + equivalent term set glossaries, the + "src" and/or "tgt" add restrictions on + the term set. + For example: "src=en-US AND tgt=zh-CN" + will only pick the unidirectional + glossaries which exactly match the + source language code as "en-US" and the + target language code "zh-CN", but all + equivalent term set glossaries which + contain "en-US" and "zh-CN" in their + language set will be picked. If missing, + no filtering is performed. + This corresponds to the ``filter`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -634,7 +814,7 @@ async def list_glossaries( sent along with the request as metadata. Returns: - ~.pagers.ListGlossariesAsyncPager: + google.cloud.translate_v3beta1.services.translation_service.pagers.ListGlossariesAsyncPager: Response message for ListGlossaries. Iterating over this object will yield results and resolve additional pages @@ -672,6 +852,7 @@ async def list_glossaries( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -708,11 +889,12 @@ async def get_glossary( exist. Args: - request (:class:`~.translation_service.GetGlossaryRequest`): + request (:class:`google.cloud.translate_v3beta1.types.GetGlossaryRequest`): The request object. Request message for GetGlossary. name (:class:`str`): Required. The name of the glossary to retrieve. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -724,7 +906,7 @@ async def get_glossary( sent along with the request as metadata. Returns: - ~.translation_service.Glossary: + google.cloud.translate_v3beta1.types.Glossary: Represents a glossary built from user provided data. @@ -758,6 +940,7 @@ async def get_glossary( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, @@ -789,11 +972,12 @@ async def delete_glossary( doesn't exist. Args: - request (:class:`~.translation_service.DeleteGlossaryRequest`): + request (:class:`google.cloud.translate_v3beta1.types.DeleteGlossaryRequest`): The request object. Request message for DeleteGlossary. name (:class:`str`): Required. The name of the glossary to delete. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -805,14 +989,12 @@ async def delete_glossary( sent along with the request as metadata. Returns: - ~.operation_async.AsyncOperation: + google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.translation_service.DeleteGlossaryResponse``: - Stored in the - [google.longrunning.Operation.response][google.longrunning.Operation.response] - field returned by DeleteGlossary. + The result type for the operation will be :class:`google.cloud.translate_v3beta1.types.DeleteGlossaryResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by DeleteGlossary. """ # Create or coerce a protobuf request object. @@ -844,6 +1026,7 @@ async def delete_glossary( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/translate_v3beta1/services/translation_service/client.py b/google/cloud/translate_v3beta1/services/translation_service/client.py index f5039607..f2623a3b 100644 --- a/google/cloud/translate_v3beta1/services/translation_service/client.py +++ b/google/cloud/translate_v3beta1/services/translation_service/client.py @@ -115,6 +115,22 @@ def _get_default_mtls_endpoint(api_endpoint): 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: + TranslationServiceClient: 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 @@ -127,7 +143,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): kwargs: Additional arguments to pass to the constructor. Returns: - {@api.name}: The constructed client. + TranslationServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -235,10 +251,10 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.TranslationServiceTransport]): The + transport (Union[str, TranslationServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (client_options_lib.ClientOptions): Custom options for the + client_options (google.api_core.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 @@ -274,21 +290,17 @@ def __init__( util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) ) - ssl_credentials = None + client_cert_source_func = None is_mtls = False if use_client_cert: if client_options.client_cert_source: - import grpc # type: ignore - - cert, key = client_options.client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) is_mtls = True + client_cert_source_func = client_options.client_cert_source else: - creds = SslCredentials() - is_mtls = creds.is_mtls - ssl_credentials = creds.ssl_credentials if is_mtls else None + is_mtls = mtls.has_default_client_cert_source() + client_cert_source_func = ( + mtls.default_client_cert_source() if is_mtls else None + ) # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -331,7 +343,7 @@ def __init__( credentials_file=client_options.credentials_file, host=api_endpoint, scopes=client_options.scopes, - ssl_channel_credentials=ssl_credentials, + client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, ) @@ -347,7 +359,7 @@ def translate_text( r"""Translates input text and returns translated text. Args: - request (:class:`~.translation_service.TranslateTextRequest`): + request (google.cloud.translate_v3beta1.types.TranslateTextRequest): The request object. The request message for synchronous translation. @@ -358,7 +370,7 @@ def translate_text( sent along with the request as metadata. Returns: - ~.translation_service.TranslateTextResponse: + google.cloud.translate_v3beta1.types.TranslateTextResponse: """ # Create or coerce a protobuf request object. @@ -400,46 +412,49 @@ def detect_language( r"""Detects the language of text within a request. Args: - request (:class:`~.translation_service.DetectLanguageRequest`): + request (google.cloud.translate_v3beta1.types.DetectLanguageRequest): The request object. The request message for language detection. - parent (:class:`str`): + parent (str): Required. Project or location to make a call. Must refer to a caller's project. Format: - ``projects/{project-id}/locations/{location-id}`` or - ``projects/{project-id}``. + ``projects/{project-number-or-id}/locations/{location-id}`` + or ``projects/{project-number-or-id}``. For global calls, use - ``projects/{project-id}/locations/global`` or - ``projects/{project-id}``. + ``projects/{project-number-or-id}/locations/global`` or + ``projects/{project-number-or-id}``. - Only models within the same region (has same - location-id) can be used. Otherwise an INVALID_ARGUMENT + Only models within the same region, which have the same + location-id, can be used. Otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - model (:class:`str`): + model (str): Optional. The language detection model to be used. Format: - ``projects/{project-id}/locations/{location-id}/models/language-detection/{model-id}`` + ``projects/{project-number-or-id}/locations/{location-id}/models/language-detection/{model-id}`` Only one language detection model is currently supported: - ``projects/{project-id}/locations/{location-id}/models/language-detection/default``. + ``projects/{project-number-or-id}/locations/{location-id}/models/language-detection/default``. If not specified, the default model is used. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - mime_type (:class:`str`): + mime_type (str): Optional. The format of the source text, for example, "text/html", "text/plain". If left blank, the MIME type defaults to "text/html". + This corresponds to the ``mime_type`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -451,7 +466,7 @@ def detect_language( sent along with the request as metadata. Returns: - ~.translation_service.DetectLanguageResponse: + google.cloud.translate_v3beta1.types.DetectLanguageResponse: The response message for language detection. @@ -514,52 +529,55 @@ def get_supported_languages( translation. Args: - request (:class:`~.translation_service.GetSupportedLanguagesRequest`): + request (google.cloud.translate_v3beta1.types.GetSupportedLanguagesRequest): The request object. The request message for discovering supported languages. - parent (:class:`str`): + parent (str): Required. Project or location to make a call. Must refer to a caller's project. - Format: ``projects/{project-id}`` or - ``projects/{project-id}/locations/{location-id}``. + Format: ``projects/{project-number-or-id}`` or + ``projects/{project-number-or-id}/locations/{location-id}``. For global calls, use - ``projects/{project-id}/locations/global`` or - ``projects/{project-id}``. + ``projects/{project-number-or-id}/locations/global`` or + ``projects/{project-number-or-id}``. Non-global location is required for AutoML models. Only models within the same region (have same location-id) can be used, otherwise an INVALID_ARGUMENT (400) error is returned. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - display_language_code (:class:`str`): + display_language_code (str): Optional. The language to use to return localized, human readable names of supported languages. If missing, then display names are not returned in a response. + This corresponds to the ``display_language_code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - model (:class:`str`): + model (str): Optional. Get supported languages of this model. The format depends on model type: - AutoML Translation models: - ``projects/{project-id}/locations/{location-id}/models/{model-id}`` + ``projects/{project-number-or-id}/locations/{location-id}/models/{model-id}`` - General (built-in) models: - ``projects/{project-id}/locations/{location-id}/models/general/nmt``, - ``projects/{project-id}/locations/{location-id}/models/general/base`` + ``projects/{project-number-or-id}/locations/{location-id}/models/general/nmt``, + ``projects/{project-number-or-id}/locations/{location-id}/models/general/base`` Returns languages supported by the specified model. If missing, we get supported languages of Google general base (PBMT) model. + This corresponds to the ``model`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -571,7 +589,7 @@ def get_supported_languages( sent along with the request as metadata. Returns: - ~.translation_service.SupportedLanguages: + google.cloud.translate_v3beta1.types.SupportedLanguages: The response message for discovering supported languages. @@ -619,6 +637,57 @@ def get_supported_languages( # Done; return the response. return response + def translate_document( + self, + request: translation_service.TranslateDocumentRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> translation_service.TranslateDocumentResponse: + r"""Translates documents in synchronous mode. + + Args: + request (google.cloud.translate_v3beta1.types.TranslateDocumentRequest): + The request object. A document translation request. + + 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.translate_v3beta1.types.TranslateDocumentResponse: + A translated document response + message. + + """ + # Create or coerce a protobuf request object. + + # Minor optimization to avoid making a copy if the user passes + # in a translation_service.TranslateDocumentRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, translation_service.TranslateDocumentRequest): + request = translation_service.TranslateDocumentRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.translate_document] + + # 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 batch_translate_text( self, request: translation_service.BatchTranslateTextRequest = None, @@ -638,7 +707,7 @@ def batch_translate_text( of the call. Args: - request (:class:`~.translation_service.BatchTranslateTextRequest`): + request (google.cloud.translate_v3beta1.types.BatchTranslateTextRequest): The request object. The batch translation request. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -648,15 +717,13 @@ def batch_translate_text( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.translation_service.BatchTranslateResponse``: - Stored in the - [google.longrunning.Operation.response][google.longrunning.Operation.response] - field returned by BatchTranslateText if at least one - sentence is translated successfully. + The result type for the operation will be :class:`google.cloud.translate_v3beta1.types.BatchTranslateResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by BatchTranslateText if at least one + sentence is translated successfully. """ # Create or coerce a protobuf request object. @@ -692,6 +759,77 @@ def batch_translate_text( # Done; return the response. return response + def batch_translate_document( + self, + request: translation_service.BatchTranslateDocumentRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Translates a large volume of documents in + asynchronous batch mode. This function provides real- + time output as the inputs are being processed. If caller + cancels a request, the partial results (for an input + file, it's all or nothing) may still be available on the + specified output location. + This call returns immediately and you can use + google.longrunning.Operation.name to poll the status of + the call. + + Args: + request (google.cloud.translate_v3beta1.types.BatchTranslateDocumentRequest): + The request object. The BatchTranslateDocument request. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.translate_v3beta1.types.BatchTranslateDocumentResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by BatchTranslateDocument if at least + one document is translated successfully. + + """ + # Create or coerce a protobuf request object. + + # Minor optimization to avoid making a copy if the user passes + # in a translation_service.BatchTranslateDocumentRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, translation_service.BatchTranslateDocumentRequest): + request = translation_service.BatchTranslateDocumentRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.batch_translate_document] + + # 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,) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + translation_service.BatchTranslateDocumentResponse, + metadata_type=translation_service.BatchTranslateDocumentMetadata, + ) + + # Done; return the response. + return response + def create_glossary( self, request: translation_service.CreateGlossaryRequest = None, @@ -706,14 +844,14 @@ def create_glossary( Returns NOT_FOUND, if the project doesn't exist. Args: - request (:class:`~.translation_service.CreateGlossaryRequest`): + request (google.cloud.translate_v3beta1.types.CreateGlossaryRequest): The request object. Request message for CreateGlossary. - parent (:class:`str`): + parent (str): Required. The project name. This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - glossary (:class:`~.translation_service.Glossary`): + glossary (google.cloud.translate_v3beta1.types.Glossary): Required. The glossary to create. This corresponds to the ``glossary`` field on the ``request`` instance; if ``request`` is provided, this @@ -726,12 +864,12 @@ def create_glossary( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. The result type for the operation will be - :class:``~.translation_service.Glossary``: Represents a - glossary built from user provided data. + :class:`google.cloud.translate_v3beta1.types.Glossary` + Represents a glossary built from user provided data. """ # Create or coerce a protobuf request object. @@ -797,21 +935,47 @@ def list_glossaries( doesn't exist. Args: - request (:class:`~.translation_service.ListGlossariesRequest`): + request (google.cloud.translate_v3beta1.types.ListGlossariesRequest): The request object. Request message for ListGlossaries. - parent (:class:`str`): + parent (str): Required. The name of the project from which to list all of the glossaries. + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - filter (:class:`str`): + filter (str): Optional. Filter specifying - constraints of a list operation. - Filtering is not supported yet, and the - parameter currently has no effect. If - missing, no filtering is performed. + constraints of a list operation. Specify + the constraint by the format of + "key=value", where key must be "src" or + "tgt", and the value must be a valid + language code. For multiple + restrictions, concatenate them by "AND" + (uppercase only), such as: "src=en-US + AND tgt=zh-CN". Notice that the exact + match is used here, which means using + 'en-US' and 'en' can lead to different + results, which depends on the language + code you used when you create the + glossary. For the unidirectional + glossaries, the "src" and "tgt" add + restrictions on the source and target + language code separately. For the + equivalent term set glossaries, the + "src" and/or "tgt" add restrictions on + the term set. + For example: "src=en-US AND tgt=zh-CN" + will only pick the unidirectional + glossaries which exactly match the + source language code as "en-US" and the + target language code "zh-CN", but all + equivalent term set glossaries which + contain "en-US" and "zh-CN" in their + language set will be picked. If missing, + no filtering is performed. + This corresponds to the ``filter`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -823,7 +987,7 @@ def list_glossaries( sent along with the request as metadata. Returns: - ~.pagers.ListGlossariesPager: + google.cloud.translate_v3beta1.services.translation_service.pagers.ListGlossariesPager: Response message for ListGlossaries. Iterating over this object will yield results and resolve additional pages @@ -890,11 +1054,12 @@ def get_glossary( exist. Args: - request (:class:`~.translation_service.GetGlossaryRequest`): + request (google.cloud.translate_v3beta1.types.GetGlossaryRequest): The request object. Request message for GetGlossary. - name (:class:`str`): + name (str): Required. The name of the glossary to retrieve. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -906,7 +1071,7 @@ def get_glossary( sent along with the request as metadata. Returns: - ~.translation_service.Glossary: + google.cloud.translate_v3beta1.types.Glossary: Represents a glossary built from user provided data. @@ -964,11 +1129,12 @@ def delete_glossary( doesn't exist. Args: - request (:class:`~.translation_service.DeleteGlossaryRequest`): + request (google.cloud.translate_v3beta1.types.DeleteGlossaryRequest): The request object. Request message for DeleteGlossary. - name (:class:`str`): + name (str): Required. The name of the glossary to delete. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -980,14 +1146,12 @@ def delete_glossary( sent along with the request as metadata. Returns: - ~.operation.Operation: + google.api_core.operation.Operation: An object representing a long-running operation. - The result type for the operation will be - :class:``~.translation_service.DeleteGlossaryResponse``: - Stored in the - [google.longrunning.Operation.response][google.longrunning.Operation.response] - field returned by DeleteGlossary. + The result type for the operation will be :class:`google.cloud.translate_v3beta1.types.DeleteGlossaryResponse` Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by DeleteGlossary. """ # Create or coerce a protobuf request object. diff --git a/google/cloud/translate_v3beta1/services/translation_service/pagers.py b/google/cloud/translate_v3beta1/services/translation_service/pagers.py index a132a74e..a750c43d 100644 --- a/google/cloud/translate_v3beta1/services/translation_service/pagers.py +++ b/google/cloud/translate_v3beta1/services/translation_service/pagers.py @@ -15,7 +15,16 @@ # limitations under the License. # -from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple +from typing import ( + Any, + AsyncIterable, + Awaitable, + Callable, + Iterable, + Sequence, + Tuple, + Optional, +) from google.cloud.translate_v3beta1.types import translation_service @@ -24,7 +33,7 @@ class ListGlossariesPager: """A pager for iterating through ``list_glossaries`` requests. This class thinly wraps an initial - :class:`~.translation_service.ListGlossariesResponse` object, and + :class:`google.cloud.translate_v3beta1.types.ListGlossariesResponse` object, and provides an ``__iter__`` method to iterate through its ``glossaries`` field. @@ -33,7 +42,7 @@ class ListGlossariesPager: through the ``glossaries`` field on the corresponding responses. - All the usual :class:`~.translation_service.ListGlossariesResponse` + All the usual :class:`google.cloud.translate_v3beta1.types.ListGlossariesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -51,9 +60,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.translation_service.ListGlossariesRequest`): + request (google.cloud.translate_v3beta1.types.ListGlossariesRequest): The initial request object. - response (:class:`~.translation_service.ListGlossariesResponse`): + response (google.cloud.translate_v3beta1.types.ListGlossariesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -86,7 +95,7 @@ class ListGlossariesAsyncPager: """A pager for iterating through ``list_glossaries`` requests. This class thinly wraps an initial - :class:`~.translation_service.ListGlossariesResponse` object, and + :class:`google.cloud.translate_v3beta1.types.ListGlossariesResponse` object, and provides an ``__aiter__`` method to iterate through its ``glossaries`` field. @@ -95,7 +104,7 @@ class ListGlossariesAsyncPager: through the ``glossaries`` field on the corresponding responses. - All the usual :class:`~.translation_service.ListGlossariesResponse` + All the usual :class:`google.cloud.translate_v3beta1.types.ListGlossariesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -113,9 +122,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.translation_service.ListGlossariesRequest`): + request (google.cloud.translate_v3beta1.types.ListGlossariesRequest): The initial request object. - response (:class:`~.translation_service.ListGlossariesResponse`): + response (google.cloud.translate_v3beta1.types.ListGlossariesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/translate_v3beta1/services/translation_service/transports/base.py b/google/cloud/translate_v3beta1/services/translation_service/transports/base.py index 39eac87f..c8a24ade 100644 --- a/google/cloud/translate_v3beta1/services/translation_service/transports/base.py +++ b/google/cloud/translate_v3beta1/services/translation_service/transports/base.py @@ -72,10 +72,10 @@ def __init__( scope (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 + 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. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -83,6 +83,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -92,20 +95,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -124,15 +124,24 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, ), + self.translate_document: gapic_v1.method.wrap_method( + self.translate_document, default_timeout=600.0, client_info=client_info, + ), self.batch_translate_text: gapic_v1.method.wrap_method( self.batch_translate_text, default_timeout=600.0, client_info=client_info, ), + self.batch_translate_document: gapic_v1.method.wrap_method( + self.batch_translate_document, + default_timeout=600.0, + client_info=client_info, + ), self.create_glossary: gapic_v1.method.wrap_method( self.create_glossary, default_timeout=600.0, client_info=client_info, ), @@ -145,6 +154,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -158,6 +168,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -171,6 +182,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=600.0, ), default_timeout=600.0, client_info=client_info, @@ -218,6 +230,18 @@ def get_supported_languages( ]: raise NotImplementedError() + @property + def translate_document( + self, + ) -> typing.Callable[ + [translation_service.TranslateDocumentRequest], + typing.Union[ + translation_service.TranslateDocumentResponse, + typing.Awaitable[translation_service.TranslateDocumentResponse], + ], + ]: + raise NotImplementedError() + @property def batch_translate_text( self, @@ -227,6 +251,15 @@ def batch_translate_text( ]: raise NotImplementedError() + @property + def batch_translate_document( + self, + ) -> typing.Callable[ + [translation_service.BatchTranslateDocumentRequest], + typing.Union[operations.Operation, typing.Awaitable[operations.Operation]], + ]: + raise NotImplementedError() + @property def create_glossary( self, diff --git a/google/cloud/translate_v3beta1/services/translation_service/transports/grpc.py b/google/cloud/translate_v3beta1/services/translation_service/transports/grpc.py index d2158382..9a903357 100644 --- a/google/cloud/translate_v3beta1/services/translation_service/transports/grpc.py +++ b/google/cloud/translate_v3beta1/services/translation_service/transports/grpc.py @@ -59,6 +59,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -89,6 +90,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for 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 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): @@ -103,72 +108,61 @@ def __init__( 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] = {} + self._operations_client = None + + 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: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # 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 - elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) + 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 - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials + 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 + ) - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # 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, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -176,18 +170,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - self._operations_client = None - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -201,7 +185,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + 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 @@ -342,6 +326,35 @@ def get_supported_languages( ) return self._stubs["get_supported_languages"] + @property + def translate_document( + self, + ) -> Callable[ + [translation_service.TranslateDocumentRequest], + translation_service.TranslateDocumentResponse, + ]: + r"""Return a callable for the translate document method over gRPC. + + Translates documents in synchronous mode. + + Returns: + Callable[[~.TranslateDocumentRequest], + ~.TranslateDocumentResponse]: + 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_document" not in self._stubs: + self._stubs["translate_document"] = self.grpc_channel.unary_unary( + "/google.cloud.translation.v3beta1.TranslationService/TranslateDocument", + request_serializer=translation_service.TranslateDocumentRequest.serialize, + response_deserializer=translation_service.TranslateDocumentResponse.deserialize, + ) + return self._stubs["translate_document"] + @property def batch_translate_text( self, @@ -378,6 +391,42 @@ def batch_translate_text( ) return self._stubs["batch_translate_text"] + @property + def batch_translate_document( + self, + ) -> Callable[ + [translation_service.BatchTranslateDocumentRequest], operations.Operation + ]: + r"""Return a callable for the batch translate document method over gRPC. + + Translates a large volume of documents in + asynchronous batch mode. This function provides real- + time output as the inputs are being processed. If caller + cancels a request, the partial results (for an input + file, it's all or nothing) may still be available on the + specified output location. + This call returns immediately and you can use + google.longrunning.Operation.name to poll the status of + the call. + + Returns: + Callable[[~.BatchTranslateDocumentRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "batch_translate_document" not in self._stubs: + self._stubs["batch_translate_document"] = self.grpc_channel.unary_unary( + "/google.cloud.translation.v3beta1.TranslationService/BatchTranslateDocument", + request_serializer=translation_service.BatchTranslateDocumentRequest.serialize, + response_deserializer=operations.Operation.FromString, + ) + return self._stubs["batch_translate_document"] + @property def create_glossary( self, diff --git a/google/cloud/translate_v3beta1/services/translation_service/transports/grpc_asyncio.py b/google/cloud/translate_v3beta1/services/translation_service/transports/grpc_asyncio.py index 5f201aa2..72617ed7 100644 --- a/google/cloud/translate_v3beta1/services/translation_service/transports/grpc_asyncio.py +++ b/google/cloud/translate_v3beta1/services/translation_service/transports/grpc_asyncio.py @@ -63,7 +63,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + 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 @@ -103,6 +103,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -134,12 +135,16 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for 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 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 + 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: @@ -148,72 +153,61 @@ def __init__( 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] = {} + self._operations_client = None + + 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: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # 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 - elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( - api_mtls_endpoint - if ":" in api_mtls_endpoint - else api_mtls_endpoint + ":443" - ) + 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 - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials + 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 + ) - # create a new channel. The provided one is ignored. - self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, - credentials_file=credentials_file, - ssl_credentials=ssl_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" - - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # 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, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -221,18 +215,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} - self._operations_client = None + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: @@ -348,6 +332,35 @@ def get_supported_languages( ) return self._stubs["get_supported_languages"] + @property + def translate_document( + self, + ) -> Callable[ + [translation_service.TranslateDocumentRequest], + Awaitable[translation_service.TranslateDocumentResponse], + ]: + r"""Return a callable for the translate document method over gRPC. + + Translates documents in synchronous mode. + + Returns: + Callable[[~.TranslateDocumentRequest], + Awaitable[~.TranslateDocumentResponse]]: + 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_document" not in self._stubs: + self._stubs["translate_document"] = self.grpc_channel.unary_unary( + "/google.cloud.translation.v3beta1.TranslationService/TranslateDocument", + request_serializer=translation_service.TranslateDocumentRequest.serialize, + response_deserializer=translation_service.TranslateDocumentResponse.deserialize, + ) + return self._stubs["translate_document"] + @property def batch_translate_text( self, @@ -384,6 +397,43 @@ def batch_translate_text( ) return self._stubs["batch_translate_text"] + @property + def batch_translate_document( + self, + ) -> Callable[ + [translation_service.BatchTranslateDocumentRequest], + Awaitable[operations.Operation], + ]: + r"""Return a callable for the batch translate document method over gRPC. + + Translates a large volume of documents in + asynchronous batch mode. This function provides real- + time output as the inputs are being processed. If caller + cancels a request, the partial results (for an input + file, it's all or nothing) may still be available on the + specified output location. + This call returns immediately and you can use + google.longrunning.Operation.name to poll the status of + the call. + + Returns: + Callable[[~.BatchTranslateDocumentRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "batch_translate_document" not in self._stubs: + self._stubs["batch_translate_document"] = self.grpc_channel.unary_unary( + "/google.cloud.translation.v3beta1.TranslationService/BatchTranslateDocument", + request_serializer=translation_service.BatchTranslateDocumentRequest.serialize, + response_deserializer=operations.Operation.FromString, + ) + return self._stubs["batch_translate_document"] + @property def create_glossary( self, diff --git a/google/cloud/translate_v3beta1/types/__init__.py b/google/cloud/translate_v3beta1/types/__init__.py index ac1da5b4..64ad8390 100644 --- a/google/cloud/translate_v3beta1/types/__init__.py +++ b/google/cloud/translate_v3beta1/types/__init__.py @@ -16,61 +16,81 @@ # from .translation_service import ( - TranslateTextGlossaryConfig, - TranslateTextRequest, - TranslateTextResponse, - Translation, - DetectLanguageRequest, - DetectedLanguage, - DetectLanguageResponse, - GetSupportedLanguagesRequest, - SupportedLanguages, - SupportedLanguage, - GcsSource, - InputConfig, - GcsDestination, - OutputConfig, - BatchTranslateTextRequest, + BatchDocumentInputConfig, + BatchDocumentOutputConfig, + BatchTranslateDocumentMetadata, + BatchTranslateDocumentRequest, + BatchTranslateDocumentResponse, BatchTranslateMetadata, BatchTranslateResponse, - GlossaryInputConfig, - Glossary, + BatchTranslateTextRequest, + CreateGlossaryMetadata, CreateGlossaryRequest, - GetGlossaryRequest, + DeleteGlossaryMetadata, DeleteGlossaryRequest, + DeleteGlossaryResponse, + DetectedLanguage, + DetectLanguageRequest, + DetectLanguageResponse, + DocumentInputConfig, + DocumentOutputConfig, + DocumentTranslation, + GcsDestination, + GcsSource, + GetGlossaryRequest, + GetSupportedLanguagesRequest, + Glossary, + GlossaryInputConfig, + InputConfig, ListGlossariesRequest, ListGlossariesResponse, - CreateGlossaryMetadata, - DeleteGlossaryMetadata, - DeleteGlossaryResponse, + OutputConfig, + SupportedLanguage, + SupportedLanguages, + TranslateDocumentRequest, + TranslateDocumentResponse, + TranslateTextGlossaryConfig, + TranslateTextRequest, + TranslateTextResponse, + Translation, ) __all__ = ( - "TranslateTextGlossaryConfig", - "TranslateTextRequest", - "TranslateTextResponse", - "Translation", - "DetectLanguageRequest", - "DetectedLanguage", - "DetectLanguageResponse", - "GetSupportedLanguagesRequest", - "SupportedLanguages", - "SupportedLanguage", - "GcsSource", - "InputConfig", - "GcsDestination", - "OutputConfig", - "BatchTranslateTextRequest", + "BatchDocumentInputConfig", + "BatchDocumentOutputConfig", + "BatchTranslateDocumentMetadata", + "BatchTranslateDocumentRequest", + "BatchTranslateDocumentResponse", "BatchTranslateMetadata", "BatchTranslateResponse", - "GlossaryInputConfig", - "Glossary", + "BatchTranslateTextRequest", + "CreateGlossaryMetadata", "CreateGlossaryRequest", - "GetGlossaryRequest", + "DeleteGlossaryMetadata", "DeleteGlossaryRequest", + "DeleteGlossaryResponse", + "DetectedLanguage", + "DetectLanguageRequest", + "DetectLanguageResponse", + "DocumentInputConfig", + "DocumentOutputConfig", + "DocumentTranslation", + "GcsDestination", + "GcsSource", + "GetGlossaryRequest", + "GetSupportedLanguagesRequest", + "Glossary", + "GlossaryInputConfig", + "InputConfig", "ListGlossariesRequest", "ListGlossariesResponse", - "CreateGlossaryMetadata", - "DeleteGlossaryMetadata", - "DeleteGlossaryResponse", + "OutputConfig", + "SupportedLanguage", + "SupportedLanguages", + "TranslateDocumentRequest", + "TranslateDocumentResponse", + "TranslateTextGlossaryConfig", + "TranslateTextRequest", + "TranslateTextResponse", + "Translation", ) diff --git a/google/cloud/translate_v3beta1/types/translation_service.py b/google/cloud/translate_v3beta1/types/translation_service.py index 76f1378c..3398dc13 100644 --- a/google/cloud/translate_v3beta1/types/translation_service.py +++ b/google/cloud/translate_v3beta1/types/translation_service.py @@ -38,6 +38,11 @@ "InputConfig", "GcsDestination", "OutputConfig", + "DocumentInputConfig", + "DocumentOutputConfig", + "TranslateDocumentRequest", + "DocumentTranslation", + "TranslateDocumentResponse", "BatchTranslateTextRequest", "BatchTranslateMetadata", "BatchTranslateResponse", @@ -51,6 +56,11 @@ "CreateGlossaryMetadata", "DeleteGlossaryMetadata", "DeleteGlossaryResponse", + "BatchTranslateDocumentRequest", + "BatchDocumentInputConfig", + "BatchDocumentOutputConfig", + "BatchTranslateDocumentResponse", + "BatchTranslateDocumentMetadata", }, ) @@ -80,8 +90,9 @@ class TranslateTextRequest(proto.Message): contents (Sequence[str]): Required. The content of the input in string format. We recommend the total content be less - than 30k codepoints. Use BatchTranslateText for - larger text. + than 30k codepoints. The max length of this + field is 1024. + Use BatchTranslateText for larger text. mime_type (str): Optional. The format of the source text, for example, "text/html", "text/plain". If left @@ -102,12 +113,12 @@ class TranslateTextRequest(proto.Message): Required. Project or location to make a call. Must refer to a caller's project. - Format: ``projects/{project-id}`` or - ``projects/{project-id}/locations/{location-id}``. + Format: ``projects/{project-number-or-id}`` or + ``projects/{project-number-or-id}/locations/{location-id}``. For global calls, use - ``projects/{project-id}/locations/global`` or - ``projects/{project-id}``. + ``projects/{project-number-or-id}/locations/global`` or + ``projects/{project-number-or-id}``. Non-global location is required for requests using AutoML models or custom glossaries. @@ -121,24 +132,24 @@ class TranslateTextRequest(proto.Message): The format depends on model type: - AutoML Translation models: - ``projects/{project-id}/locations/{location-id}/models/{model-id}`` + ``projects/{project-number-or-id}/locations/{location-id}/models/{model-id}`` - General (built-in) models: - ``projects/{project-id}/locations/{location-id}/models/general/nmt``, - ``projects/{project-id}/locations/{location-id}/models/general/base`` + ``projects/{project-number-or-id}/locations/{location-id}/models/general/nmt``, + ``projects/{project-number-or-id}/locations/{location-id}/models/general/base`` For global (non-regionalized) requests, use ``location-id`` ``global``. For example, - ``projects/{project-id}/locations/global/models/general/nmt``. + ``projects/{project-number-or-id}/locations/global/models/general/nmt``. If missing, the system decides which google base model to use. - glossary_config (~.translation_service.TranslateTextGlossaryConfig): + glossary_config (google.cloud.translate_v3beta1.types.TranslateTextGlossaryConfig): Optional. Glossary to be applied. The glossary must be within the same region (have the same location-id) as the model, otherwise an INVALID_ARGUMENT (400) error is returned. - labels (Sequence[~.translation_service.TranslateTextRequest.LabelsEntry]): + labels (Sequence[google.cloud.translate_v3beta1.types.TranslateTextRequest.LabelsEntry]): Optional. The labels with user-defined metadata for the request. Label keys and values can be no longer than 63 @@ -175,11 +186,11 @@ class TranslateTextResponse(proto.Message): r""" Attributes: - translations (Sequence[~.translation_service.Translation]): + translations (Sequence[google.cloud.translate_v3beta1.types.Translation]): Text translation responses with no glossary applied. This field has the same length as [``contents``][google.cloud.translation.v3beta1.TranslateTextRequest.contents]. - glossary_translations (Sequence[~.translation_service.Translation]): + glossary_translations (Sequence[google.cloud.translate_v3beta1.types.Translation]): Text translation responses if a glossary is provided in the request. This can be the same as [``translations``][google.cloud.translation.v3beta1.TranslateTextResponse.translations] @@ -201,8 +212,14 @@ class Translation(proto.Message): translated_text (str): Text translated into the target language. model (str): - Only present when ``model`` is present in the request. This - is same as ``model`` provided in the request. + Only present when ``model`` is present in the request. + ``model`` here is normalized to have project number. + + For example: If the ``model`` requested in + TranslationTextRequest is + ``projects/{project-id}/locations/{location-id}/models/general/nmt`` + then ``model`` here would be normalized to + ``projects/{project-number}/locations/{location-id}/models/general/nmt``. detected_language_code (str): The BCP-47 language code of source text in the initial request, detected automatically, if @@ -210,7 +227,7 @@ class Translation(proto.Message): request. If the source language was passed, auto-detection of the language does not occur and this field is empty. - glossary_config (~.translation_service.TranslateTextGlossaryConfig): + glossary_config (google.cloud.translate_v3beta1.types.TranslateTextGlossaryConfig): The ``glossary_config`` used for this translation. """ @@ -233,24 +250,25 @@ class DetectLanguageRequest(proto.Message): Required. Project or location to make a call. Must refer to a caller's project. - Format: ``projects/{project-id}/locations/{location-id}`` or - ``projects/{project-id}``. + Format: + ``projects/{project-number-or-id}/locations/{location-id}`` + or ``projects/{project-number-or-id}``. For global calls, use - ``projects/{project-id}/locations/global`` or - ``projects/{project-id}``. + ``projects/{project-number-or-id}/locations/global`` or + ``projects/{project-number-or-id}``. - Only models within the same region (has same location-id) - can be used. Otherwise an INVALID_ARGUMENT (400) error is - returned. + Only models within the same region, which have the same + location-id, can be used. Otherwise an INVALID_ARGUMENT + (400) error is returned. model (str): Optional. The language detection model to be used. Format: - ``projects/{project-id}/locations/{location-id}/models/language-detection/{model-id}`` + ``projects/{project-number-or-id}/locations/{location-id}/models/language-detection/{model-id}`` Only one language detection model is currently supported: - ``projects/{project-id}/locations/{location-id}/models/language-detection/default``. + ``projects/{project-number-or-id}/locations/{location-id}/models/language-detection/default``. If not specified, the default model is used. content (str): @@ -259,7 +277,7 @@ class DetectLanguageRequest(proto.Message): Optional. The format of the source text, for example, "text/html", "text/plain". If left blank, the MIME type defaults to "text/html". - labels (Sequence[~.translation_service.DetectLanguageRequest.LabelsEntry]): + labels (Sequence[google.cloud.translate_v3beta1.types.DetectLanguageRequest.LabelsEntry]): Optional. The labels with user-defined metadata for the request. Label keys and values can be no longer than 63 @@ -305,7 +323,7 @@ class DetectLanguageResponse(proto.Message): r"""The response message for language detection. Attributes: - languages (Sequence[~.translation_service.DetectedLanguage]): + languages (Sequence[google.cloud.translate_v3beta1.types.DetectedLanguage]): A list of detected languages sorted by detection confidence in descending order. The most probable language first. @@ -324,12 +342,12 @@ class GetSupportedLanguagesRequest(proto.Message): Required. Project or location to make a call. Must refer to a caller's project. - Format: ``projects/{project-id}`` or - ``projects/{project-id}/locations/{location-id}``. + Format: ``projects/{project-number-or-id}`` or + ``projects/{project-number-or-id}/locations/{location-id}``. For global calls, use - ``projects/{project-id}/locations/global`` or - ``projects/{project-id}``. + ``projects/{project-number-or-id}/locations/global`` or + ``projects/{project-number-or-id}``. Non-global location is required for AutoML models. @@ -347,11 +365,11 @@ class GetSupportedLanguagesRequest(proto.Message): The format depends on model type: - AutoML Translation models: - ``projects/{project-id}/locations/{location-id}/models/{model-id}`` + ``projects/{project-number-or-id}/locations/{location-id}/models/{model-id}`` - General (built-in) models: - ``projects/{project-id}/locations/{location-id}/models/general/nmt``, - ``projects/{project-id}/locations/{location-id}/models/general/base`` + ``projects/{project-number-or-id}/locations/{location-id}/models/general/nmt``, + ``projects/{project-number-or-id}/locations/{location-id}/models/general/base`` Returns languages supported by the specified model. If missing, we get supported languages of Google general base @@ -369,7 +387,7 @@ class SupportedLanguages(proto.Message): r"""The response message for discovering supported languages. Attributes: - languages (Sequence[~.translation_service.SupportedLanguage]): + languages (Sequence[google.cloud.translate_v3beta1.types.SupportedLanguage]): A list of supported language responses. This list contains an entry for each language the Translation API supports. @@ -431,7 +449,7 @@ class InputConfig(proto.Message): "text/html" is used if mime_type is missing. For ``.html``, this field must be "text/html" or empty. For ``.txt``, this field must be "text/plain" or empty. - gcs_source (~.translation_service.GcsSource): + gcs_source (google.cloud.translate_v3beta1.types.GcsSource): Required. Google Cloud Storage location for the source input. This can be a single file (for example, ``gs://translation-test/input.tsv``) or a wildcard (for @@ -478,7 +496,7 @@ class OutputConfig(proto.Message): r"""Output configuration for BatchTranslateText request. Attributes: - gcs_destination (~.translation_service.GcsDestination): + gcs_destination (google.cloud.translate_v3beta1.types.GcsDestination): Google Cloud Storage destination for output content. For every single input file (for example, gs://a/b/c.[extension]), we generate at most 2 \* n output @@ -510,13 +528,18 @@ class OutputConfig(proto.Message): content to output. Once a row is present in index.csv, the input/output - matching never changes. Callers should also expect all the - content in input_file are processed and ready to be consumed - (that is, no partial output file is written). + matching never changes. Callers should also expect the + contents in the input_file are processed and ready to be + consumed (that is, no partial output file is written). + + Since index.csv will be updated during the process, please + make sure there is no custom retention policy applied on the + output bucket that may prevent file updating. + (https://cloud.google.com/storage/docs/bucket-lock?hl=en#retention-policy) The format of translations_file (for target language code 'trg') is: - ``gs://translation_test/a_b_c\_'trg'_translations.[extension]`` + gs://translation_test/a_b_c\_'trg'_translations.[extension] If the input file extension is tsv, the output has the following columns: Column 1: ID of the request provided in @@ -533,10 +556,10 @@ class OutputConfig(proto.Message): directly written to the output file. If glossary is requested, a separate glossary_translations_file has format of - ``gs://translation_test/a_b_c\_'trg'_glossary_translations.[extension]`` + gs://translation_test/a_b_c\_'trg'_glossary_translations.[extension] The format of errors file (for target language code 'trg') - is: ``gs://translation_test/a_b_c\_'trg'_errors.[extension]`` + is: gs://translation_test/a_b_c\_'trg'_errors.[extension] If the input file extension is tsv, errors_file contains the following: Column 1: ID of the request provided in the @@ -549,7 +572,7 @@ class OutputConfig(proto.Message): If the input file extension is txt or html, glossary_error_file will be generated that contains error details. glossary_error_file has format of - ``gs://translation_test/a_b_c\_'trg'_glossary_errors.[extension]`` + gs://translation_test/a_b_c\_'trg'_glossary_errors.[extension] """ gcs_destination = proto.Field( @@ -557,6 +580,279 @@ class OutputConfig(proto.Message): ) +class DocumentInputConfig(proto.Message): + r"""A document translation request input config. + + Attributes: + content (bytes): + Document's content represented as a stream of + bytes. + gcs_source (google.cloud.translate_v3beta1.types.GcsSource): + Google Cloud Storage location. This must be a single file. + For example: gs://example_bucket/example_file.pdf + mime_type (str): + Specifies the input document's mime_type. + + If not specified it will be determined using the file + extension for gcs_source provided files. For a file provided + through bytes content the mime_type must be provided. + Currently supported mime types are: + + - application/pdf + - application/vnd.openxmlformats-officedocument.wordprocessingml.document + - application/vnd.openxmlformats-officedocument.presentationml.presentation + - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + """ + + content = proto.Field(proto.BYTES, number=1, oneof="source") + + gcs_source = proto.Field( + proto.MESSAGE, number=2, oneof="source", message="GcsSource", + ) + + mime_type = proto.Field(proto.STRING, number=4) + + +class DocumentOutputConfig(proto.Message): + r"""A document translation request output config. + + Attributes: + gcs_destination (google.cloud.translate_v3beta1.types.GcsDestination): + Optional. Google Cloud Storage destination for the + translation output, e.g., ``gs://my_bucket/my_directory/``. + + The destination directory provided does not have to be + empty, but the bucket must exist. If a file with the same + name as the output file already exists in the destination an + error will be returned. + + For a DocumentInputConfig.contents provided document, the + output file will have the name + "output_[trg]_translations.[ext]", where + + - [trg] corresponds to the translated file's language code, + - [ext] corresponds to the translated file's extension + according to its mime type. + + For a DocumentInputConfig.gcs_uri provided document, the + output file will have a name according to its URI. For + example: an input file with URI: "gs://a/b/c.[extension]" + stored in a gcs_destination bucket with name "my_bucket" + will have an output URI: + "gs://my_bucket/a_b_c\_[trg]_translations.[ext]", where + + - [trg] corresponds to the translated file's language code, + - [ext] corresponds to the translated file's extension + according to its mime type. + + If the document was directly provided through the request, + then the output document will have the format: + "gs://my_bucket/translated_document_[trg]_translations.[ext], + where + + - [trg] corresponds to the translated file's language code, + - [ext] corresponds to the translated file's extension + according to its mime type. + + If a glossary was provided, then the output URI for the + glossary translation will be equal to the default output URI + but have ``glossary_translations`` instead of + ``translations``. For the previous example, its glossary URI + would be: + "gs://my_bucket/a_b_c\_[trg]_glossary_translations.[ext]". + + Thus the max number of output files will be 2 (Translated + document, Glossary translated document). + + Callers should expect no partial outputs. If there is any + error during document translation, no output will be stored + in the Cloud Storage bucket. + mime_type (str): + Optional. Specifies the translated document's mime_type. If + not specified, the translated file's mime type will be the + same as the input file's mime type. Currently only support + the output mime type to be the same as input mime type. + + - application/pdf + - application/vnd.openxmlformats-officedocument.wordprocessingml.document + - application/vnd.openxmlformats-officedocument.presentationml.presentation + - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + """ + + gcs_destination = proto.Field( + proto.MESSAGE, number=1, oneof="destination", message="GcsDestination", + ) + + mime_type = proto.Field(proto.STRING, number=3) + + +class TranslateDocumentRequest(proto.Message): + r"""A document translation request. + + Attributes: + parent (str): + Required. Location to make a regional call. + + Format: + ``projects/{project-number-or-id}/locations/{location-id}``. + + For global calls, use + ``projects/{project-number-or-id}/locations/global`` or + ``projects/{project-number-or-id}``. + + Non-global location is required for requests using AutoML + models or custom glossaries. + + Models and glossaries must be within the same region (have + the same location-id), otherwise an INVALID_ARGUMENT (400) + error is returned. + source_language_code (str): + Optional. The BCP-47 language code of the + input document if known, for example, "en-US" or + "sr-Latn". Supported language codes are listed + in Language Support. If the source language + isn't specified, the API attempts to identify + the source language automatically and returns + the source language within the response. Source + language must be specified if the request + contains a glossary or a custom model. + target_language_code (str): + Required. The BCP-47 language code to use for + translation of the input document, set to one of + the language codes listed in Language Support. + document_input_config (google.cloud.translate_v3beta1.types.DocumentInputConfig): + Required. Input configurations. + document_output_config (google.cloud.translate_v3beta1.types.DocumentOutputConfig): + Optional. Output configurations. + Defines if the output file should be stored + within Cloud Storage as well as the desired + output format. If not provided the translated + file will only be returned through a byte-stream + and its output mime type will be the same as the + input file's mime type. + model (str): + Optional. The ``model`` type requested for this translation. + + The format depends on model type: + + - AutoML Translation models: + ``projects/{project-number-or-id}/locations/{location-id}/models/{model-id}`` + + - General (built-in) models: + ``projects/{project-number-or-id}/locations/{location-id}/models/general/nmt``, + ``projects/{project-number-or-id}/locations/{location-id}/models/general/base`` + + If not provided, the default Google model (NMT) will be used + for translation. + glossary_config (google.cloud.translate_v3beta1.types.TranslateTextGlossaryConfig): + Optional. Glossary to be applied. The glossary must be + within the same region (have the same location-id) as the + model, otherwise an INVALID_ARGUMENT (400) error is + returned. + labels (Sequence[google.cloud.translate_v3beta1.types.TranslateDocumentRequest.LabelsEntry]): + Optional. The labels with user-defined + metadata for the request. + Label keys and values can be no longer than 63 + characters (Unicode codepoints), can only + contain lowercase letters, numeric characters, + underscores and dashes. International characters + are allowed. Label values are optional. Label + keys must start with a letter. + See + https://cloud.google.com/translate/docs/advanced/labels + for more information. + """ + + parent = proto.Field(proto.STRING, number=1) + + source_language_code = proto.Field(proto.STRING, number=2) + + target_language_code = proto.Field(proto.STRING, number=3) + + document_input_config = proto.Field( + proto.MESSAGE, number=4, message="DocumentInputConfig", + ) + + document_output_config = proto.Field( + proto.MESSAGE, number=5, message="DocumentOutputConfig", + ) + + model = proto.Field(proto.STRING, number=6) + + glossary_config = proto.Field( + proto.MESSAGE, number=7, message="TranslateTextGlossaryConfig", + ) + + labels = proto.MapField(proto.STRING, proto.STRING, number=8) + + +class DocumentTranslation(proto.Message): + r"""A translated document message. + + Attributes: + byte_stream_outputs (Sequence[bytes]): + The array of translated documents. It is + expected to be size 1 for now. We may produce + multiple translated documents in the future for + other type of file formats. + mime_type (str): + The translated document's mime type. + detected_language_code (str): + The detected language for the input document. + If the user did not provide the source language + for the input document, this field will have the + language code automatically detected. If the + source language was passed, auto-detection of + the language does not occur and this field is + empty. + """ + + byte_stream_outputs = proto.RepeatedField(proto.BYTES, number=1) + + mime_type = proto.Field(proto.STRING, number=2) + + detected_language_code = proto.Field(proto.STRING, number=3) + + +class TranslateDocumentResponse(proto.Message): + r"""A translated document response message. + + Attributes: + document_translation (google.cloud.translate_v3beta1.types.DocumentTranslation): + Translated document. + glossary_document_translation (google.cloud.translate_v3beta1.types.DocumentTranslation): + The document's translation output if a glossary is provided + in the request. This can be the same as + [TranslateDocumentResponse.document_translation] if no + glossary terms apply. + model (str): + Only present when 'model' is present in the request. 'model' + is normalized to have a project number. + + For example: If the 'model' field in + TranslateDocumentRequest is: + ``projects/{project-id}/locations/{location-id}/models/general/nmt`` + then ``model`` here would be normalized to + ``projects/{project-number}/locations/{location-id}/models/general/nmt``. + glossary_config (google.cloud.translate_v3beta1.types.TranslateTextGlossaryConfig): + The ``glossary_config`` used for this translation. + """ + + document_translation = proto.Field( + proto.MESSAGE, number=1, message="DocumentTranslation", + ) + + glossary_document_translation = proto.Field( + proto.MESSAGE, number=2, message="DocumentTranslation", + ) + + model = proto.Field(proto.STRING, number=3) + + glossary_config = proto.Field( + proto.MESSAGE, number=4, message="TranslateTextGlossaryConfig", + ) + + class BatchTranslateTextRequest(proto.Message): r"""The batch translation request. @@ -565,7 +861,8 @@ class BatchTranslateTextRequest(proto.Message): Required. Location to make a call. Must refer to a caller's project. - Format: ``projects/{project-id}/locations/{location-id}``. + Format: + ``projects/{project-number-or-id}/locations/{location-id}``. The ``global`` location is not supported for batch translation. @@ -578,37 +875,38 @@ class BatchTranslateTextRequest(proto.Message): target_language_codes (Sequence[str]): Required. Specify up to 10 language codes here. - models (Sequence[~.translation_service.BatchTranslateTextRequest.ModelsEntry]): + models (Sequence[google.cloud.translate_v3beta1.types.BatchTranslateTextRequest.ModelsEntry]): Optional. The models to use for translation. Map's key is - target language code. Map's value is model name. Value can - be a built-in general model, or an AutoML Translation model. + target language code. Map's value is the model name. Value + can be a built-in general model, or an AutoML Translation + model. The value format depends on model type: - AutoML Translation models: - ``projects/{project-id}/locations/{location-id}/models/{model-id}`` + ``projects/{project-number-or-id}/locations/{location-id}/models/{model-id}`` - General (built-in) models: - ``projects/{project-id}/locations/{location-id}/models/general/nmt``, - ``projects/{project-id}/locations/{location-id}/models/general/base`` + ``projects/{project-number-or-id}/locations/{location-id}/models/general/nmt``, + ``projects/{project-number-or-id}/locations/{location-id}/models/general/base`` If the map is empty or a specific model is not requested for a language pair, then default google model (nmt) is used. - input_configs (Sequence[~.translation_service.InputConfig]): + input_configs (Sequence[google.cloud.translate_v3beta1.types.InputConfig]): Required. Input configurations. The total number of files matched should be <= - 1000. The total content size should be <= 100M + 100. The total content size should be <= 100M Unicode codepoints. The files must use UTF-8 encoding. - output_config (~.translation_service.OutputConfig): + output_config (google.cloud.translate_v3beta1.types.OutputConfig): Required. Output configuration. If 2 input configs match to the same file (that is, same input path), we don't generate output for duplicate inputs. - glossaries (Sequence[~.translation_service.BatchTranslateTextRequest.GlossariesEntry]): + glossaries (Sequence[google.cloud.translate_v3beta1.types.BatchTranslateTextRequest.GlossariesEntry]): Optional. Glossaries to be applied for translation. It's keyed by target language code. - labels (Sequence[~.translation_service.BatchTranslateTextRequest.LabelsEntry]): + labels (Sequence[google.cloud.translate_v3beta1.types.BatchTranslateTextRequest.LabelsEntry]): Optional. The labels with user-defined metadata for the request. Label keys and values can be no longer than 63 @@ -645,7 +943,7 @@ class BatchTranslateMetadata(proto.Message): r"""State metadata for the batch translation operation. Attributes: - state (~.translation_service.BatchTranslateMetadata.State): + state (google.cloud.translate_v3beta1.types.BatchTranslateMetadata.State): The state of the operation. translated_characters (int): Number of successfully translated characters @@ -659,7 +957,7 @@ class BatchTranslateMetadata(proto.Message): codepoints from input files times the number of target languages and appears here shortly after the call is submitted. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): Time when the operation was submitted. """ @@ -699,9 +997,9 @@ class BatchTranslateResponse(proto.Message): failed_characters (int): Number of characters that have failed to process (Unicode codepoints). - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): Time when the operation was submitted. - end_time (~.timestamp.Timestamp): + end_time (google.protobuf.timestamp_pb2.Timestamp): The time when the operation is finished and [google.longrunning.Operation.done][google.longrunning.Operation.done] is set to true. @@ -722,7 +1020,7 @@ class GlossaryInputConfig(proto.Message): r"""Input configuration for glossaries. Attributes: - gcs_source (~.translation_service.GcsSource): + gcs_source (google.cloud.translate_v3beta1.types.GcsSource): Required. Google Cloud Storage location of glossary data. File format is determined based on the filename extension. API returns [google.rpc.Code.INVALID_ARGUMENT] for @@ -762,21 +1060,21 @@ class Glossary(proto.Message): name (str): Required. The resource name of the glossary. Glossary names have the form - ``projects/{project-id}/locations/{location-id}/glossaries/{glossary-id}``. - language_pair (~.translation_service.Glossary.LanguageCodePair): + ``projects/{project-number-or-id}/locations/{location-id}/glossaries/{glossary-id}``. + language_pair (google.cloud.translate_v3beta1.types.Glossary.LanguageCodePair): Used with unidirectional glossaries. - language_codes_set (~.translation_service.Glossary.LanguageCodesSet): + language_codes_set (google.cloud.translate_v3beta1.types.Glossary.LanguageCodesSet): Used with equivalent term set glossaries. - input_config (~.translation_service.GlossaryInputConfig): + input_config (google.cloud.translate_v3beta1.types.GlossaryInputConfig): Required. Provides examples to build the glossary from. Total glossary must not exceed 10M Unicode codepoints. entry_count (int): Output only. The number of entries defined in the glossary. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): Output only. When CreateGlossary was called. - end_time (~.timestamp.Timestamp): + end_time (google.protobuf.timestamp_pb2.Timestamp): Output only. When the glossary creation was finished. """ @@ -837,7 +1135,7 @@ class CreateGlossaryRequest(proto.Message): Attributes: parent (str): Required. The project name. - glossary (~.translation_service.Glossary): + glossary (google.cloud.translate_v3beta1.types.Glossary): Required. The glossary to create. """ @@ -889,9 +1187,29 @@ class ListGlossariesRequest(proto.Message): is returned if ``page_token``\ is empty or missing. filter (str): Optional. Filter specifying constraints of a - list operation. Filtering is not supported yet, - and the parameter currently has no effect. If - missing, no filtering is performed. + list operation. Specify the constraint by the + format of "key=value", where key must be "src" + or "tgt", and the value must be a valid language + code. For multiple restrictions, concatenate + them by "AND" (uppercase only), such as: + "src=en-US AND tgt=zh-CN". Notice that the exact + match is used here, which means using 'en-US' + and 'en' can lead to different results, which + depends on the language code you used when you + create the glossary. For the unidirectional + glossaries, the "src" and "tgt" add restrictions + on the source and target language code + separately. For the equivalent term set + glossaries, the "src" and/or "tgt" add + restrictions on the term set. + For example: "src=en-US AND tgt=zh-CN" will only + pick the unidirectional glossaries which exactly + match the source language code as "en-US" and + the target language code "zh-CN", but all + equivalent term set glossaries which contain + "en-US" and "zh-CN" in their language set will + be picked. If missing, no filtering is + performed. """ parent = proto.Field(proto.STRING, number=1) @@ -907,7 +1225,7 @@ class ListGlossariesResponse(proto.Message): r"""Response message for ListGlossaries. Attributes: - glossaries (Sequence[~.translation_service.Glossary]): + glossaries (Sequence[google.cloud.translate_v3beta1.types.Glossary]): The list of glossaries for a project. next_page_token (str): A token to retrieve a page of results. Pass this value in @@ -934,10 +1252,10 @@ class CreateGlossaryMetadata(proto.Message): name (str): The name of the glossary that is being created. - state (~.translation_service.CreateGlossaryMetadata.State): + state (google.cloud.translate_v3beta1.types.CreateGlossaryMetadata.State): The current state of the glossary creation operation. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): The time when the operation was submitted to the server. """ @@ -969,10 +1287,10 @@ class DeleteGlossaryMetadata(proto.Message): name (str): The name of the glossary that is being deleted. - state (~.translation_service.DeleteGlossaryMetadata.State): + state (google.cloud.translate_v3beta1.types.DeleteGlossaryMetadata.State): The current state of the glossary deletion operation. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): The time when the operation was submitted to the server. """ @@ -1003,10 +1321,10 @@ class DeleteGlossaryResponse(proto.Message): Attributes: name (str): The name of the deleted glossary. - submit_time (~.timestamp.Timestamp): + submit_time (google.protobuf.timestamp_pb2.Timestamp): The time when the operation was submitted to the server. - end_time (~.timestamp.Timestamp): + end_time (google.protobuf.timestamp_pb2.Timestamp): The time when the glossary deletion is finished and [google.longrunning.Operation.done][google.longrunning.Operation.done] is set to true. @@ -1019,4 +1337,314 @@ class DeleteGlossaryResponse(proto.Message): end_time = proto.Field(proto.MESSAGE, number=3, message=timestamp.Timestamp,) +class BatchTranslateDocumentRequest(proto.Message): + r"""The BatchTranslateDocument request. + + Attributes: + parent (str): + Required. Location to make a regional call. + + Format: + ``projects/{project-number-or-id}/locations/{location-id}``. + + The ``global`` location is not supported for batch + translation. + + Only AutoML Translation models or glossaries within the same + region (have the same location-id) can be used, otherwise an + INVALID_ARGUMENT (400) error is returned. + source_language_code (str): + Required. The BCP-47 language code of the + input document if known, for example, "en-US" or + "sr-Latn". Supported language codes are listed + in Language Support + (https://cloud.google.com/translate/docs/languages). + target_language_codes (Sequence[str]): + Required. The BCP-47 language code to use for + translation of the input document. Specify up to + 10 language codes here. + input_configs (Sequence[google.cloud.translate_v3beta1.types.BatchDocumentInputConfig]): + Required. Input configurations. + The total number of files matched should be <= + 100. The total content size to translate should + be <= 100M Unicode codepoints. The files must + use UTF-8 encoding. + output_config (google.cloud.translate_v3beta1.types.BatchDocumentOutputConfig): + Required. Output configuration. + If 2 input configs match to the same file (that + is, same input path), we don't generate output + for duplicate inputs. + models (Sequence[google.cloud.translate_v3beta1.types.BatchTranslateDocumentRequest.ModelsEntry]): + Optional. The models to use for translation. Map's key is + target language code. Map's value is the model name. Value + can be a built-in general model, or an AutoML Translation + model. + + The value format depends on model type: + + - AutoML Translation models: + ``projects/{project-number-or-id}/locations/{location-id}/models/{model-id}`` + + - General (built-in) models: + ``projects/{project-number-or-id}/locations/{location-id}/models/general/nmt``, + ``projects/{project-number-or-id}/locations/{location-id}/models/general/base`` + + If the map is empty or a specific model is not requested for + a language pair, then default google model (nmt) is used. + glossaries (Sequence[google.cloud.translate_v3beta1.types.BatchTranslateDocumentRequest.GlossariesEntry]): + Optional. Glossaries to be applied. It's + keyed by target language code. + """ + + parent = proto.Field(proto.STRING, number=1) + + source_language_code = proto.Field(proto.STRING, number=2) + + target_language_codes = proto.RepeatedField(proto.STRING, number=3) + + input_configs = proto.RepeatedField( + proto.MESSAGE, number=4, message="BatchDocumentInputConfig", + ) + + output_config = proto.Field( + proto.MESSAGE, number=5, message="BatchDocumentOutputConfig", + ) + + models = proto.MapField(proto.STRING, proto.STRING, number=6) + + glossaries = proto.MapField( + proto.STRING, proto.MESSAGE, number=7, message="TranslateTextGlossaryConfig", + ) + + +class BatchDocumentInputConfig(proto.Message): + r"""Input configuration for BatchTranslateDocument request. + + Attributes: + gcs_source (google.cloud.translate_v3beta1.types.GcsSource): + Google Cloud Storage location for the source input. This can + be a single file (for example, + ``gs://translation-test/input.docx``) or a wildcard (for + example, ``gs://translation-test/*``). + + File mime type is determined based on extension. Supported + mime type includes: + + - ``pdf``, application/pdf + - ``docx``, + application/vnd.openxmlformats-officedocument.wordprocessingml.document + - ``pptx``, + application/vnd.openxmlformats-officedocument.presentationml.presentation + - ``xlsx``, + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + + The max file size supported for ``.docx``, ``.pptx`` and + ``.xlsx`` is 100MB. The max file size supported for ``.pdf`` + is 1GB and the max page limit is 1000 pages. The max file + size supported for all input documents is 1GB. + """ + + gcs_source = proto.Field( + proto.MESSAGE, number=1, oneof="source", message="GcsSource", + ) + + +class BatchDocumentOutputConfig(proto.Message): + r"""Output configuration for BatchTranslateDocument request. + + Attributes: + gcs_destination (google.cloud.translate_v3beta1.types.GcsDestination): + Google Cloud Storage destination for output content. For + every single input document (for example, + gs://a/b/c.[extension]), we generate at most 2 \* n output + files. (n is the # of target_language_codes in the + BatchTranslateDocumentRequest). + + While the input documents are being processed, we + write/update an index file ``index.csv`` under + ``gcs_destination.output_uri_prefix`` (for example, + gs://translation_output/index.csv) The index file is + generated/updated as new files are being translated. The + format is: + + input_document,target_language_code,translation_output,error_output, + glossary_translation_output,glossary_error_output + + ``input_document`` is one file we matched using + gcs_source.input_uri. ``target_language_code`` is provided + in the request. ``translation_output`` contains the + translations. (details provided below) ``error_output`` + contains the error message during processing of the file. + Both translations_file and errors_file could be empty + strings if we have no content to output. + ``glossary_translation_output`` and + ``glossary_error_output`` are the translated output/error + when we apply glossaries. They could also be empty if we + have no content to output. + + Once a row is present in index.csv, the input/output + matching never changes. Callers should also expect all the + content in input_file are processed and ready to be consumed + (that is, no partial output file is written). + + Since index.csv will be keeping updated during the process, + please make sure there is no custom retention policy applied + on the output bucket that may avoid file updating. + (https://cloud.google.com/storage/docs/bucket-lock?hl=en#retention-policy) + + The naming format of translation output files follows (for + target language code [trg]): ``translation_output``: + gs://translation_output/a_b_c\_[trg]\ *translation.[extension] + ``glossary_translation_output``: + gs://translation_test/a_b_c*\ [trg]_glossary_translation.[extension] + The output document will maintain the same file format as + the input document. + + The naming format of error output files follows (for target + language code [trg]): ``error_output``: + gs://translation_test/a_b_c\_[trg]\ *errors.txt + ``glossary_error_output``: + gs://translation_test/a_b_c*\ [trg]_glossary_translation.txt + The error output is a txt file containing error details. + """ + + gcs_destination = proto.Field( + proto.MESSAGE, number=1, oneof="destination", message="GcsDestination", + ) + + +class BatchTranslateDocumentResponse(proto.Message): + r"""Stored in the + [google.longrunning.Operation.response][google.longrunning.Operation.response] + field returned by BatchTranslateDocument if at least one document is + translated successfully. + + Attributes: + total_pages (int): + Total number of pages to translate in all + documents. Documents without a clear page + definition (such as XLSX) are not counted. + translated_pages (int): + Number of successfully translated pages in + all documents. Documents without a clear page + definition (such as XLSX) are not counted. + failed_pages (int): + Number of pages that failed to process in all + documents. Documents without a clear page + definition (such as XLSX) are not counted. + total_billable_pages (int): + Number of billable pages in documents with + clear page definition (such as PDF, DOCX, PPTX) + total_characters (int): + Total number of characters (Unicode + codepoints) in all documents. + translated_characters (int): + Number of successfully translated characters + (Unicode codepoints) in all documents. + failed_characters (int): + Number of characters that have failed to + process (Unicode codepoints) in all documents. + total_billable_characters (int): + Number of billable characters (Unicode + codepoints) in documents without clear page + definition, such as XLSX. + submit_time (google.protobuf.timestamp_pb2.Timestamp): + Time when the operation was submitted. + end_time (google.protobuf.timestamp_pb2.Timestamp): + The time when the operation is finished and + [google.longrunning.Operation.done][google.longrunning.Operation.done] + is set to true. + """ + + total_pages = proto.Field(proto.INT64, number=1) + + translated_pages = proto.Field(proto.INT64, number=2) + + failed_pages = proto.Field(proto.INT64, number=3) + + total_billable_pages = proto.Field(proto.INT64, number=4) + + total_characters = proto.Field(proto.INT64, number=5) + + translated_characters = proto.Field(proto.INT64, number=6) + + failed_characters = proto.Field(proto.INT64, number=7) + + total_billable_characters = proto.Field(proto.INT64, number=8) + + submit_time = proto.Field(proto.MESSAGE, number=9, message=timestamp.Timestamp,) + + end_time = proto.Field(proto.MESSAGE, number=10, message=timestamp.Timestamp,) + + +class BatchTranslateDocumentMetadata(proto.Message): + r"""State metadata for the batch translation operation. + + Attributes: + state (google.cloud.translate_v3beta1.types.BatchTranslateDocumentMetadata.State): + The state of the operation. + total_pages (int): + Total number of pages to translate in all + documents so far. Documents without clear page + definition (such as XLSX) are not counted. + translated_pages (int): + Number of successfully translated pages in + all documents so far. Documents without clear + page definition (such as XLSX) are not counted. + failed_pages (int): + Number of pages that failed to process in all + documents so far. Documents without clear page + definition (such as XLSX) are not counted. + total_billable_pages (int): + Number of billable pages in documents with + clear page definition (such as PDF, DOCX, PPTX) + so far. + total_characters (int): + Total number of characters (Unicode + codepoints) in all documents so far. + translated_characters (int): + Number of successfully translated characters + (Unicode codepoints) in all documents so far. + failed_characters (int): + Number of characters that have failed to + process (Unicode codepoints) in all documents so + far. + total_billable_characters (int): + Number of billable characters (Unicode + codepoints) in documents without clear page + definition (such as XLSX) so far. + submit_time (google.protobuf.timestamp_pb2.Timestamp): + Time when the operation was submitted. + """ + + class State(proto.Enum): + r"""State of the job.""" + STATE_UNSPECIFIED = 0 + RUNNING = 1 + SUCCEEDED = 2 + FAILED = 3 + CANCELLING = 4 + CANCELLED = 5 + + state = proto.Field(proto.ENUM, number=1, enum=State,) + + total_pages = proto.Field(proto.INT64, number=2) + + translated_pages = proto.Field(proto.INT64, number=3) + + failed_pages = proto.Field(proto.INT64, number=4) + + total_billable_pages = proto.Field(proto.INT64, number=5) + + total_characters = proto.Field(proto.INT64, number=6) + + translated_characters = proto.Field(proto.INT64, number=7) + + failed_characters = proto.Field(proto.INT64, number=8) + + total_billable_characters = proto.Field(proto.INT64, number=9) + + submit_time = proto.Field(proto.MESSAGE, number=10, message=timestamp.Timestamp,) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/noxfile.py b/noxfile.py index 8004482e..8e9b9413 100644 --- a/noxfile.py +++ b/noxfile.py @@ -18,6 +18,7 @@ from __future__ import absolute_import import os +import pathlib import shutil import nox @@ -30,6 +31,22 @@ SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"] UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() + +# 'docfx' is excluded since it only needs to run in 'docs-presubmit' +nox.options.sessions = [ + "unit", + "system", + "cover", + "lint", + "lint_setup_py", + "blacken", + "docs", +] + +# Error if a python version is missing +nox.options.error_on_missing_interpreters = True + @nox.session(python=DEFAULT_PYTHON_VERSION) def lint(session): @@ -70,17 +87,21 @@ def lint_setup_py(session): def default(session): # Install all test dependencies, then install this package in-place. - session.install("asyncmock", "pytest-asyncio") - session.install( - "mock", "pytest", "pytest-cov", + constraints_path = str( + CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" ) - session.install("-e", ".") + session.install("asyncmock", "pytest-asyncio", "-c", constraints_path) + + session.install("mock", "pytest", "pytest-cov", "-c", constraints_path) + + session.install("-e", ".", "-c", constraints_path) # Run py.test against the unit tests. session.run( "py.test", "--quiet", + f"--junitxml=unit_{session.python}_sponge_log.xml", "--cov=google/cloud", "--cov=tests/unit", "--cov-append", @@ -101,6 +122,9 @@ def unit(session): @nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS) def system(session): """Run the system test suite.""" + constraints_path = str( + CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" + ) system_test_path = os.path.join("tests", "system.py") system_test_folder_path = os.path.join("tests", "system") @@ -110,6 +134,9 @@ def system(session): # Sanity check: Only run tests if the environment variable is set. if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): session.skip("Credentials must be set via environment variable") + # Install pyopenssl for mTLS testing. + if os.environ.get("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true": + session.install("pyopenssl") system_test_exists = os.path.exists(system_test_path) system_test_folder_exists = os.path.exists(system_test_folder_path) @@ -122,16 +149,26 @@ def system(session): # Install all test dependencies, then install this package into the # virtualenv's dist-packages. - session.install( - "mock", "pytest", "google-cloud-testutils", - ) - session.install("-e", ".") + session.install("mock", "pytest", "google-cloud-testutils", "-c", constraints_path) + session.install("-e", ".", "-c", constraints_path) # Run py.test against the system tests. if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_path, + *session.posargs, + ) if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_folder_path, + *session.posargs, + ) @nox.session(python=DEFAULT_PYTHON_VERSION) diff --git a/renovate.json b/renovate.json index 4fa94931..f08bc22c 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,6 @@ { "extends": [ "config:base", ":preserveSemverRanges" - ] + ], + "ignorePaths": [".pre-commit-config.yaml"] } diff --git a/samples/snippets/hybrid_glossaries/noxfile.py b/samples/snippets/hybrid_glossaries/noxfile.py index bca0522e..97bf7da8 100644 --- a/samples/snippets/hybrid_glossaries/noxfile.py +++ b/samples/snippets/hybrid_glossaries/noxfile.py @@ -85,7 +85,7 @@ def get_pytest_env_vars() -> Dict[str, str]: # DO NOT EDIT - automatically generated. # All versions used to tested samples. -ALL_VERSIONS = ["2.7", "3.6", "3.7", "3.8"] +ALL_VERSIONS = ["2.7", "3.6", "3.7", "3.8", "3.9"] # Any default versions that should be ignored. IGNORED_VERSIONS = TEST_CONFIG['ignored_versions'] diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py index bca0522e..97bf7da8 100644 --- a/samples/snippets/noxfile.py +++ b/samples/snippets/noxfile.py @@ -85,7 +85,7 @@ def get_pytest_env_vars() -> Dict[str, str]: # DO NOT EDIT - automatically generated. # All versions used to tested samples. -ALL_VERSIONS = ["2.7", "3.6", "3.7", "3.8"] +ALL_VERSIONS = ["2.7", "3.6", "3.7", "3.8", "3.9"] # Any default versions that should be ignored. IGNORED_VERSIONS = TEST_CONFIG['ignored_versions'] diff --git a/scripts/fixup_translate_v3beta1_keywords.py b/scripts/fixup_translate_v3beta1_keywords.py index 7bf59c96..6df60492 100644 --- a/scripts/fixup_translate_v3beta1_keywords.py +++ b/scripts/fixup_translate_v3beta1_keywords.py @@ -41,6 +41,7 @@ def partition( class translateCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + 'batch_translate_document': ('parent', 'source_language_code', 'target_language_codes', 'input_configs', 'output_config', 'models', 'glossaries', ), 'batch_translate_text': ('parent', 'source_language_code', 'target_language_codes', 'input_configs', 'output_config', 'models', 'glossaries', 'labels', ), 'create_glossary': ('parent', 'glossary', ), 'delete_glossary': ('name', ), @@ -48,6 +49,7 @@ class translateCallTransformer(cst.CSTTransformer): 'get_glossary': ('name', ), 'get_supported_languages': ('parent', 'display_language_code', 'model', ), 'list_glossaries': ('parent', 'page_size', 'page_token', 'filter', ), + 'translate_document': ('parent', 'target_language_code', 'document_input_config', 'source_language_code', 'document_output_config', 'model', 'glossary_config', 'labels', ), 'translate_text': ('contents', 'target_language_code', 'parent', 'mime_type', 'source_language_code', 'model', 'glossary_config', 'labels', ), } diff --git a/setup.py b/setup.py index 9045fdcf..8b3a83cb 100644 --- a/setup.py +++ b/setup.py @@ -29,9 +29,8 @@ # 'Development Status :: 5 - Production/Stable' release_status = "Development Status :: 5 - Production/Stable" dependencies = [ - "google-api-core[grpc] >= 1.22.0, < 2.0.0dev", - "google-cloud-core >= 1.1.0, < 2.0dev", - "libcst >= 0.2.5", + "google-api-core[grpc] >= 1.22.2, < 2.0.0dev", + "google-cloud-core >= 1.3.0, < 2.0dev", "proto-plus >= 0.4.0", ] extras = {} diff --git a/synth.metadata b/synth.metadata index d0aeeac0..74f6b2ee 100644 --- a/synth.metadata +++ b/synth.metadata @@ -3,30 +3,30 @@ { "git": { "name": ".", - "remote": "https://github.com/googleapis/python-translate.git", - "sha": "6b723d40da81a95a60edfd3da1340651f8d1e161" + "remote": "git@github.com:googleapis/python-translate", + "sha": "09cc03ad906596f59b3625e3cf21d096aba395b3" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "57fc4a8a94a5bd015a83fb0f0a1707f62254b2cd", - "internalRef": "348813319" + "sha": "336d6f419fe9466e4540083bbfa46a57f67dc92e", + "internalRef": "364666178" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "41a4e56982620d3edcf110d76f4fcdfdec471ac8" + "sha": "86ed43d4f56e6404d068e62e497029018879c771" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "41a4e56982620d3edcf110d76f4fcdfdec471ac8" + "sha": "86ed43d4f56e6404d068e62e497029018879c771" } } ], @@ -49,114 +49,5 @@ "generator": "bazel" } } - ], - "generatedFiles": [ - ".flake8", - ".github/CONTRIBUTING.md", - ".github/ISSUE_TEMPLATE/bug_report.md", - ".github/ISSUE_TEMPLATE/feature_request.md", - ".github/ISSUE_TEMPLATE/support_request.md", - ".github/PULL_REQUEST_TEMPLATE.md", - ".github/release-please.yml", - ".github/snippet-bot.yml", - ".gitignore", - ".kokoro/build.sh", - ".kokoro/continuous/common.cfg", - ".kokoro/continuous/continuous.cfg", - ".kokoro/docker/docs/Dockerfile", - ".kokoro/docker/docs/fetch_gpg_keys.sh", - ".kokoro/docs/common.cfg", - ".kokoro/docs/docs-presubmit.cfg", - ".kokoro/docs/docs.cfg", - ".kokoro/populate-secrets.sh", - ".kokoro/presubmit/common.cfg", - ".kokoro/presubmit/presubmit.cfg", - ".kokoro/publish-docs.sh", - ".kokoro/release.sh", - ".kokoro/release/common.cfg", - ".kokoro/release/release.cfg", - ".kokoro/samples/lint/common.cfg", - ".kokoro/samples/lint/continuous.cfg", - ".kokoro/samples/lint/periodic.cfg", - ".kokoro/samples/lint/presubmit.cfg", - ".kokoro/samples/python3.6/common.cfg", - ".kokoro/samples/python3.6/continuous.cfg", - ".kokoro/samples/python3.6/periodic.cfg", - ".kokoro/samples/python3.6/presubmit.cfg", - ".kokoro/samples/python3.7/common.cfg", - ".kokoro/samples/python3.7/continuous.cfg", - ".kokoro/samples/python3.7/periodic.cfg", - ".kokoro/samples/python3.7/presubmit.cfg", - ".kokoro/samples/python3.8/common.cfg", - ".kokoro/samples/python3.8/continuous.cfg", - ".kokoro/samples/python3.8/periodic.cfg", - ".kokoro/samples/python3.8/presubmit.cfg", - ".kokoro/test-samples.sh", - ".kokoro/trampoline.sh", - ".kokoro/trampoline_v2.sh", - ".pre-commit-config.yaml", - ".trampolinerc", - "CODE_OF_CONDUCT.md", - "CONTRIBUTING.rst", - "LICENSE", - "MANIFEST.in", - "docs/_static/custom.css", - "docs/_templates/layout.html", - "docs/conf.py", - "docs/multiprocessing.rst", - "docs/translate_v3/services.rst", - "docs/translate_v3/types.rst", - "docs/translate_v3beta1/services.rst", - "docs/translate_v3beta1/types.rst", - "google/cloud/translate/__init__.py", - "google/cloud/translate/py.typed", - "google/cloud/translate_v3/__init__.py", - "google/cloud/translate_v3/py.typed", - "google/cloud/translate_v3/services/__init__.py", - "google/cloud/translate_v3/services/translation_service/__init__.py", - "google/cloud/translate_v3/services/translation_service/async_client.py", - "google/cloud/translate_v3/services/translation_service/client.py", - "google/cloud/translate_v3/services/translation_service/pagers.py", - "google/cloud/translate_v3/services/translation_service/transports/__init__.py", - "google/cloud/translate_v3/services/translation_service/transports/base.py", - "google/cloud/translate_v3/services/translation_service/transports/grpc.py", - "google/cloud/translate_v3/services/translation_service/transports/grpc_asyncio.py", - "google/cloud/translate_v3/types/__init__.py", - "google/cloud/translate_v3/types/translation_service.py", - "google/cloud/translate_v3beta1/__init__.py", - "google/cloud/translate_v3beta1/py.typed", - "google/cloud/translate_v3beta1/services/__init__.py", - "google/cloud/translate_v3beta1/services/translation_service/__init__.py", - "google/cloud/translate_v3beta1/services/translation_service/async_client.py", - "google/cloud/translate_v3beta1/services/translation_service/client.py", - "google/cloud/translate_v3beta1/services/translation_service/pagers.py", - "google/cloud/translate_v3beta1/services/translation_service/transports/__init__.py", - "google/cloud/translate_v3beta1/services/translation_service/transports/base.py", - "google/cloud/translate_v3beta1/services/translation_service/transports/grpc.py", - "google/cloud/translate_v3beta1/services/translation_service/transports/grpc_asyncio.py", - "google/cloud/translate_v3beta1/types/__init__.py", - "google/cloud/translate_v3beta1/types/translation_service.py", - "mypy.ini", - "noxfile.py", - "renovate.json", - "samples/AUTHORING_GUIDE.md", - "samples/CONTRIBUTING.md", - "samples/snippets/hybrid_glossaries/noxfile.py", - "samples/snippets/noxfile.py", - "scripts/decrypt-secrets.sh", - "scripts/fixup_translate_v3_keywords.py", - "scripts/fixup_translate_v3beta1_keywords.py", - "scripts/readme-gen/readme_gen.py", - "scripts/readme-gen/templates/README.tmpl.rst", - "scripts/readme-gen/templates/auth.tmpl.rst", - "scripts/readme-gen/templates/auth_api_key.tmpl.rst", - "scripts/readme-gen/templates/install_deps.tmpl.rst", - "scripts/readme-gen/templates/install_portaudio.tmpl.rst", - "setup.cfg", - "testing/.gitignore", - "tests/unit/gapic/translate_v3/__init__.py", - "tests/unit/gapic/translate_v3/test_translation_service.py", - "tests/unit/gapic/translate_v3beta1/__init__.py", - "tests/unit/gapic/translate_v3beta1/test_translation_service.py" ] } \ No newline at end of file diff --git a/synth.py b/synth.py index 8ca9bf33..71f203b4 100644 --- a/synth.py +++ b/synth.py @@ -62,6 +62,13 @@ # Correct namespace in noxfile s.replace("noxfile.py", "google.cloud.translation", "google.cloud.translate") +# Exclude the v2 from coverage targets +s.replace(".coveragerc", +" google/cloud/translate/__init__.py", +""" google/cloud/translate/__init__.py + google/cloud/translate_v2/__init__.py + google/cloud/__init__.py""" +) # ---------------------------------------------------------------------------- # Samples templates # ---------------------------------------------------------------------------- diff --git a/testing/constraints-3.10.txt b/testing/constraints-3.10.txt new file mode 100644 index 00000000..e69de29b diff --git a/testing/constraints-3.11.txt b/testing/constraints-3.11.txt new file mode 100644 index 00000000..e69de29b diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt new file mode 100644 index 00000000..d698348c --- /dev/null +++ b/testing/constraints-3.6.txt @@ -0,0 +1,10 @@ +# This constraints file is used to check that lower bounds +# are correct in setup.py +# List *all* library dependencies and extras in this file. +# Pin the version to the lower bound. +# +# e.g., if setup.py has "foo >= 1.14.0, < 2.0.0dev", +# Then this file should have foo==1.14.0 +google-api-core==1.22.2 +google-cloud-core==1.3.0 +proto-plus==0.4.0 diff --git a/testing/constraints-3.7.txt b/testing/constraints-3.7.txt new file mode 100644 index 00000000..e69de29b diff --git a/testing/constraints-3.8.txt b/testing/constraints-3.8.txt new file mode 100644 index 00000000..e69de29b diff --git a/testing/constraints-3.9.txt b/testing/constraints-3.9.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/gapic/translate_v3/__init__.py b/tests/unit/gapic/translate_v3/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/translate_v3/__init__.py +++ b/tests/unit/gapic/translate_v3/__init__.py @@ -1 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 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. +# diff --git a/tests/unit/gapic/translate_v3/test_translation_service.py b/tests/unit/gapic/translate_v3/test_translation_service.py index 215b08b1..6950ea3c 100644 --- a/tests/unit/gapic/translate_v3/test_translation_service.py +++ b/tests/unit/gapic/translate_v3/test_translation_service.py @@ -95,7 +95,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [TranslationServiceClient, TranslationServiceAsyncClient] + "client_class", [TranslationServiceClient, TranslationServiceAsyncClient,] +) +def test_translation_service_client_from_service_account_info(client_class): + creds = 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) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == "translate.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [TranslationServiceClient, TranslationServiceAsyncClient,] ) def test_translation_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -105,16 +122,21 @@ def test_translation_service_client_from_service_account_file(client_class): factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) client = client_class.from_service_account_json("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "translate.googleapis.com:443" def test_translation_service_client_get_transport_class(): transport = TranslationServiceClient.get_transport_class() - assert transport == transports.TranslationServiceGrpcTransport + available_transports = [ + transports.TranslationServiceGrpcTransport, + ] + assert transport in available_transports transport = TranslationServiceClient.get_transport_class("grpc") assert transport == transports.TranslationServiceGrpcTransport @@ -165,7 +187,7 @@ def test_translation_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -181,7 +203,7 @@ def test_translation_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -197,7 +219,7 @@ def test_translation_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -225,7 +247,7 @@ def test_translation_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id="octopus", client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -286,29 +308,25 @@ def test_translation_service_client_mtls_env_auto( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - ssl_channel_creds = mock.Mock() - with mock.patch( - "grpc.ssl_channel_credentials", return_value=ssl_channel_creds - ): - patched.return_value = None - client = client_class(client_options=options) + patched.return_value = None + client = client_class(client_options=options) - if use_client_cert_env == "false": - expected_ssl_channel_creds = None - expected_host = client.DEFAULT_ENDPOINT - else: - expected_ssl_channel_creds = ssl_channel_creds - expected_host = client.DEFAULT_MTLS_ENDPOINT + 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, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + 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, + ) # Check the case ADC client cert is provided. Whether client cert is used depends on # GOOGLE_API_USE_CLIENT_CERTIFICATE value. @@ -317,66 +335,53 @@ def test_translation_service_client_mtls_env_auto( ): with mock.patch.object(transport_class, "__init__") as patched: with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, ): with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.ssl_credentials", - new_callable=mock.PropertyMock, - ) as ssl_credentials_mock: - if use_client_cert_env == "false": - is_mtls_mock.return_value = False - ssl_credentials_mock.return_value = None - expected_host = client.DEFAULT_ENDPOINT - expected_ssl_channel_creds = None - else: - is_mtls_mock.return_value = True - ssl_credentials_mock.return_value = mock.Mock() - expected_host = client.DEFAULT_MTLS_ENDPOINT - expected_ssl_channel_creds = ( - ssl_credentials_mock.return_value - ) - - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + "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 - # 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.grpc.SslCredentials.__init__", return_value=None - ): - with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - is_mtls_mock.return_value = False patched.return_value = None client = client_class() patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=expected_host, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) + # 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() + 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, + ) + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -402,7 +407,7 @@ def test_translation_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -432,7 +437,7 @@ def test_translation_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -451,7 +456,7 @@ def test_translation_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -490,6 +495,22 @@ def test_translate_text_from_dict(): test_translate_text(request_type=dict) +def test_translate_text_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.translate_text), "__call__") as call: + client.translate_text() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.TranslateTextRequest() + + @pytest.mark.asyncio async def test_translate_text_async( transport: str = "grpc_asyncio", @@ -730,6 +751,22 @@ def test_detect_language_from_dict(): test_detect_language(request_type=dict) +def test_detect_language_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.detect_language), "__call__") as call: + client.detect_language() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.DetectLanguageRequest() + + @pytest.mark.asyncio async def test_detect_language_async( transport: str = "grpc_asyncio", @@ -957,6 +994,24 @@ def test_get_supported_languages_from_dict(): test_get_supported_languages(request_type=dict) +def test_get_supported_languages_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_supported_languages), "__call__" + ) as call: + client.get_supported_languages() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.GetSupportedLanguagesRequest() + + @pytest.mark.asyncio async def test_get_supported_languages_async( transport: str = "grpc_asyncio", @@ -1184,6 +1239,24 @@ def test_batch_translate_text_from_dict(): test_batch_translate_text(request_type=dict) +def test_batch_translate_text_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_translate_text), "__call__" + ) as call: + client.batch_translate_text() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.BatchTranslateTextRequest() + + @pytest.mark.asyncio async def test_batch_translate_text_async( transport: str = "grpc_asyncio", @@ -1312,6 +1385,22 @@ def test_create_glossary_from_dict(): test_create_glossary(request_type=dict) +def test_create_glossary_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_glossary), "__call__") as call: + client.create_glossary() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.CreateGlossaryRequest() + + @pytest.mark.asyncio async def test_create_glossary_async( transport: str = "grpc_asyncio", @@ -1524,6 +1613,22 @@ def test_list_glossaries_from_dict(): test_list_glossaries(request_type=dict) +def test_list_glossaries_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_glossaries), "__call__") as call: + client.list_glossaries() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.ListGlossariesRequest() + + @pytest.mark.asyncio async def test_list_glossaries_async( transport: str = "grpc_asyncio", @@ -1894,6 +1999,22 @@ def test_get_glossary_from_dict(): test_get_glossary(request_type=dict) +def test_get_glossary_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_glossary), "__call__") as call: + client.get_glossary() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.GetGlossaryRequest() + + @pytest.mark.asyncio async def test_get_glossary_async( transport: str = "grpc_asyncio", request_type=translation_service.GetGlossaryRequest @@ -2090,6 +2211,22 @@ def test_delete_glossary_from_dict(): test_delete_glossary(request_type=dict) +def test_delete_glossary_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_glossary), "__call__") as call: + client.delete_glossary() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.DeleteGlossaryRequest() + + @pytest.mark.asyncio async def test_delete_glossary_async( transport: str = "grpc_asyncio", @@ -2431,6 +2568,56 @@ def test_translation_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.TranslationServiceGrpcTransport, + transports.TranslationServiceGrpcAsyncIOTransport, + ], +) +def test_translation_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = 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=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-translation", + ), + 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 + ) + + def test_translation_service_host_no_port(): client = TranslationServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2452,7 +2639,7 @@ def test_translation_service_host_with_port(): def test_translation_service_grpc_transport_channel(): - channel = grpc.insecure_channel("http://localhost/") + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.TranslationServiceGrpcTransport( @@ -2464,7 +2651,7 @@ def test_translation_service_grpc_transport_channel(): def test_translation_service_grpc_asyncio_transport_channel(): - channel = aio.insecure_channel("http://localhost/") + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.TranslationServiceGrpcAsyncIOTransport( @@ -2475,6 +2662,8 @@ def test_translation_service_grpc_asyncio_transport_channel(): 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", [ @@ -2489,7 +2678,7 @@ def test_translation_service_transport_channel_mtls_with_client_cert_source( "grpc.ssl_channel_credentials", autospec=True ) as grpc_ssl_channel_cred: with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_ssl_cred = mock.Mock() grpc_ssl_channel_cred.return_value = mock_ssl_cred @@ -2530,6 +2719,8 @@ def test_translation_service_transport_channel_mtls_with_client_cert_source( 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", [ @@ -2545,7 +2736,7 @@ def test_translation_service_transport_channel_mtls_with_adc(transport_class): ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel diff --git a/tests/unit/gapic/translate_v3beta1/__init__.py b/tests/unit/gapic/translate_v3beta1/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/translate_v3beta1/__init__.py +++ b/tests/unit/gapic/translate_v3beta1/__init__.py @@ -1 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 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. +# diff --git a/tests/unit/gapic/translate_v3beta1/test_translation_service.py b/tests/unit/gapic/translate_v3beta1/test_translation_service.py index e8d1351b..15060d0e 100644 --- a/tests/unit/gapic/translate_v3beta1/test_translation_service.py +++ b/tests/unit/gapic/translate_v3beta1/test_translation_service.py @@ -95,7 +95,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [TranslationServiceClient, TranslationServiceAsyncClient] + "client_class", [TranslationServiceClient, TranslationServiceAsyncClient,] +) +def test_translation_service_client_from_service_account_info(client_class): + creds = 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) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == "translate.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [TranslationServiceClient, TranslationServiceAsyncClient,] ) def test_translation_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -105,16 +122,21 @@ def test_translation_service_client_from_service_account_file(client_class): factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) client = client_class.from_service_account_json("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "translate.googleapis.com:443" def test_translation_service_client_get_transport_class(): transport = TranslationServiceClient.get_transport_class() - assert transport == transports.TranslationServiceGrpcTransport + available_transports = [ + transports.TranslationServiceGrpcTransport, + ] + assert transport in available_transports transport = TranslationServiceClient.get_transport_class("grpc") assert transport == transports.TranslationServiceGrpcTransport @@ -165,7 +187,7 @@ def test_translation_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -181,7 +203,7 @@ def test_translation_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -197,7 +219,7 @@ def test_translation_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -225,7 +247,7 @@ def test_translation_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id="octopus", client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -286,29 +308,25 @@ def test_translation_service_client_mtls_env_auto( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - ssl_channel_creds = mock.Mock() - with mock.patch( - "grpc.ssl_channel_credentials", return_value=ssl_channel_creds - ): - patched.return_value = None - client = client_class(client_options=options) + patched.return_value = None + client = client_class(client_options=options) - if use_client_cert_env == "false": - expected_ssl_channel_creds = None - expected_host = client.DEFAULT_ENDPOINT - else: - expected_ssl_channel_creds = ssl_channel_creds - expected_host = client.DEFAULT_MTLS_ENDPOINT + 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, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + 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, + ) # Check the case ADC client cert is provided. Whether client cert is used depends on # GOOGLE_API_USE_CLIENT_CERTIFICATE value. @@ -317,66 +335,53 @@ def test_translation_service_client_mtls_env_auto( ): with mock.patch.object(transport_class, "__init__") as patched: with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, ): with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.ssl_credentials", - new_callable=mock.PropertyMock, - ) as ssl_credentials_mock: - if use_client_cert_env == "false": - is_mtls_mock.return_value = False - ssl_credentials_mock.return_value = None - expected_host = client.DEFAULT_ENDPOINT - expected_ssl_channel_creds = None - else: - is_mtls_mock.return_value = True - ssl_credentials_mock.return_value = mock.Mock() - expected_host = client.DEFAULT_MTLS_ENDPOINT - expected_ssl_channel_creds = ( - ssl_credentials_mock.return_value - ) - - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + "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 - # 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.grpc.SslCredentials.__init__", return_value=None - ): - with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - is_mtls_mock.return_value = False patched.return_value = None client = client_class() patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=expected_host, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) + # 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() + 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, + ) + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -402,7 +407,7 @@ def test_translation_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -432,7 +437,7 @@ def test_translation_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -451,7 +456,7 @@ def test_translation_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -490,6 +495,22 @@ def test_translate_text_from_dict(): test_translate_text(request_type=dict) +def test_translate_text_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.translate_text), "__call__") as call: + client.translate_text() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.TranslateTextRequest() + + @pytest.mark.asyncio async def test_translate_text_async( transport: str = "grpc_asyncio", @@ -613,6 +634,22 @@ def test_detect_language_from_dict(): test_detect_language(request_type=dict) +def test_detect_language_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.detect_language), "__call__") as call: + client.detect_language() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.DetectLanguageRequest() + + @pytest.mark.asyncio async def test_detect_language_async( transport: str = "grpc_asyncio", @@ -828,6 +865,24 @@ def test_get_supported_languages_from_dict(): test_get_supported_languages(request_type=dict) +def test_get_supported_languages_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_supported_languages), "__call__" + ) as call: + client.get_supported_languages() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.GetSupportedLanguagesRequest() + + @pytest.mark.asyncio async def test_get_supported_languages_async( transport: str = "grpc_asyncio", @@ -1021,6 +1076,161 @@ async def test_get_supported_languages_flattened_error_async(): ) +def test_translate_document( + transport: str = "grpc", request_type=translation_service.TranslateDocumentRequest +): + client = TranslationServiceClient( + credentials=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_document), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = translation_service.TranslateDocumentResponse( + model="model_value", + ) + + response = client.translate_document(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.TranslateDocumentRequest() + + # Establish that the response is the type that we expect. + + assert isinstance(response, translation_service.TranslateDocumentResponse) + + assert response.model == "model_value" + + +def test_translate_document_from_dict(): + test_translate_document(request_type=dict) + + +def test_translate_document_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.translate_document), "__call__" + ) as call: + client.translate_document() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.TranslateDocumentRequest() + + +@pytest.mark.asyncio +async def test_translate_document_async( + transport: str = "grpc_asyncio", + request_type=translation_service.TranslateDocumentRequest, +): + client = TranslationServiceAsyncClient( + credentials=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_document), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + translation_service.TranslateDocumentResponse(model="model_value",) + ) + + response = await client.translate_document(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.TranslateDocumentRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, translation_service.TranslateDocumentResponse) + + assert response.model == "model_value" + + +@pytest.mark.asyncio +async def test_translate_document_async_from_dict(): + await test_translate_document_async(request_type=dict) + + +def test_translate_document_field_headers(): + client = TranslationServiceClient(credentials=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.TranslateDocumentRequest() + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.translate_document), "__call__" + ) as call: + call.return_value = translation_service.TranslateDocumentResponse() + + client.translate_document(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_document_field_headers_async(): + client = TranslationServiceAsyncClient( + credentials=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.TranslateDocumentRequest() + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.translate_document), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + translation_service.TranslateDocumentResponse() + ) + + await client.translate_document(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_batch_translate_text( transport: str = "grpc", request_type=translation_service.BatchTranslateTextRequest ): @@ -1055,6 +1265,24 @@ def test_batch_translate_text_from_dict(): test_batch_translate_text(request_type=dict) +def test_batch_translate_text_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_translate_text), "__call__" + ) as call: + client.batch_translate_text() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.BatchTranslateTextRequest() + + @pytest.mark.asyncio async def test_batch_translate_text_async( transport: str = "grpc_asyncio", @@ -1151,6 +1379,155 @@ async def test_batch_translate_text_field_headers_async(): assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] +def test_batch_translate_document( + transport: str = "grpc", + request_type=translation_service.BatchTranslateDocumentRequest, +): + client = TranslationServiceClient( + credentials=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.batch_translate_document), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + + response = client.batch_translate_document(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.BatchTranslateDocumentRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_batch_translate_document_from_dict(): + test_batch_translate_document(request_type=dict) + + +def test_batch_translate_document_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_translate_document), "__call__" + ) as call: + client.batch_translate_document() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.BatchTranslateDocumentRequest() + + +@pytest.mark.asyncio +async def test_batch_translate_document_async( + transport: str = "grpc_asyncio", + request_type=translation_service.BatchTranslateDocumentRequest, +): + client = TranslationServiceAsyncClient( + credentials=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.batch_translate_document), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + + response = await client.batch_translate_document(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.BatchTranslateDocumentRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_batch_translate_document_async_from_dict(): + await test_batch_translate_document_async(request_type=dict) + + +def test_batch_translate_document_field_headers(): + client = TranslationServiceClient(credentials=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.BatchTranslateDocumentRequest() + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_translate_document), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + + client.batch_translate_document(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_batch_translate_document_field_headers_async(): + client = TranslationServiceAsyncClient( + credentials=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.BatchTranslateDocumentRequest() + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_translate_document), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + + await client.batch_translate_document(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + def test_create_glossary( transport: str = "grpc", request_type=translation_service.CreateGlossaryRequest ): @@ -1183,6 +1560,22 @@ def test_create_glossary_from_dict(): test_create_glossary(request_type=dict) +def test_create_glossary_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_glossary), "__call__") as call: + client.create_glossary() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.CreateGlossaryRequest() + + @pytest.mark.asyncio async def test_create_glossary_async( transport: str = "grpc_asyncio", @@ -1395,6 +1788,22 @@ def test_list_glossaries_from_dict(): test_list_glossaries(request_type=dict) +def test_list_glossaries_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_glossaries), "__call__") as call: + client.list_glossaries() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.ListGlossariesRequest() + + @pytest.mark.asyncio async def test_list_glossaries_async( transport: str = "grpc_asyncio", @@ -1777,6 +2186,22 @@ def test_get_glossary_from_dict(): test_get_glossary(request_type=dict) +def test_get_glossary_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_glossary), "__call__") as call: + client.get_glossary() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.GetGlossaryRequest() + + @pytest.mark.asyncio async def test_get_glossary_async( transport: str = "grpc_asyncio", request_type=translation_service.GetGlossaryRequest @@ -1973,6 +2398,22 @@ def test_delete_glossary_from_dict(): test_delete_glossary(request_type=dict) +def test_delete_glossary_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 = TranslationServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_glossary), "__call__") as call: + client.delete_glossary() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == translation_service.DeleteGlossaryRequest() + + @pytest.mark.asyncio async def test_delete_glossary_async( transport: str = "grpc_asyncio", @@ -2234,7 +2675,9 @@ def test_translation_service_base_transport(): "translate_text", "detect_language", "get_supported_languages", + "translate_document", "batch_translate_text", + "batch_translate_document", "create_glossary", "list_glossaries", "get_glossary", @@ -2314,6 +2757,56 @@ def test_translation_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.TranslationServiceGrpcTransport, + transports.TranslationServiceGrpcAsyncIOTransport, + ], +) +def test_translation_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = 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=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-translation", + ), + 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 + ) + + def test_translation_service_host_no_port(): client = TranslationServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2335,7 +2828,7 @@ def test_translation_service_host_with_port(): def test_translation_service_grpc_transport_channel(): - channel = grpc.insecure_channel("http://localhost/") + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.TranslationServiceGrpcTransport( @@ -2347,7 +2840,7 @@ def test_translation_service_grpc_transport_channel(): def test_translation_service_grpc_asyncio_transport_channel(): - channel = aio.insecure_channel("http://localhost/") + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.TranslationServiceGrpcAsyncIOTransport( @@ -2358,6 +2851,8 @@ def test_translation_service_grpc_asyncio_transport_channel(): 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", [ @@ -2372,7 +2867,7 @@ def test_translation_service_transport_channel_mtls_with_client_cert_source( "grpc.ssl_channel_credentials", autospec=True ) as grpc_ssl_channel_cred: with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_ssl_cred = mock.Mock() grpc_ssl_channel_cred.return_value = mock_ssl_cred @@ -2413,6 +2908,8 @@ def test_translation_service_transport_channel_mtls_with_client_cert_source( 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", [ @@ -2428,7 +2925,7 @@ def test_translation_service_transport_channel_mtls_with_adc(transport_class): ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel