From 3181b55733da7aecde37009a0dd77117434deceb Mon Sep 17 00:00:00 2001 From: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Date: Mon, 1 Jun 2020 16:23:26 -0700 Subject: [PATCH] feat!: regenerate with microgenerator (#30) BREAKING CHANGE: This commit has breaking changes. For help migrating your code, see UPGRADING.md. --- .coveragerc | 31 +- .flake8 | 4 +- .gitignore | 2 + .kokoro/publish-docs.sh | 2 - .kokoro/release.sh | 2 - .kokoro/test-samples.sh | 20 +- MANIFEST.in | 3 + README.rst | 2 + UPGRADING.md | 151 +++ docs/UPGRADING.md | 1 + docs/api.rst | 30 - docs/gapic/v1/api.rst | 6 - docs/gapic/v1/types.rst | 5 - docs/gapic/v1beta1/api.rst | 6 - docs/gapic/v1beta1/types.rst | 5 - docs/index.rst | 42 +- docs/multiprocessing.rst | 7 + docs/texttospeech_v1/services.rst | 6 + docs/texttospeech_v1/types.rst | 5 + docs/texttospeech_v1beta1/services.rst | 6 + docs/texttospeech_v1beta1/types.rst | 5 + google/cloud/texttospeech/__init__.py | 45 + google/cloud/texttospeech/py.typed | 2 + google/cloud/texttospeech_v1/__init__.py | 55 +- google/cloud/texttospeech_v1/gapic/enums.py | 63 -- .../gapic/text_to_speech_client.py | 323 ------ .../gapic/text_to_speech_client_config.py | 33 - .../text_to_speech_grpc_transport.py | 135 --- .../cloud/texttospeech_v1/proto/__init__.py | 0 .../texttospeech_v1/proto/cloud_tts.proto | 254 ----- .../texttospeech_v1/proto/cloud_tts_pb2.py | 976 ------------------ .../proto/cloud_tts_pb2_grpc.py | 67 -- google/cloud/texttospeech_v1/py.typed | 2 + .../services/__init__.py} | 15 +- .../services/text_to_speech}/__init__.py | 16 +- .../services/text_to_speech/client.py | 369 +++++++ .../text_to_speech/transports/__init__.py | 30 + .../text_to_speech/transports/base.py | 76 ++ .../text_to_speech/transports/grpc.py | 212 ++++ google/cloud/texttospeech_v1/types.py | 43 - .../cloud/texttospeech_v1/types/__init__.py | 39 + .../cloud/texttospeech_v1/types/cloud_tts.py | 265 +++++ google/cloud/texttospeech_v1beta1/__init__.py | 55 +- .../texttospeech_v1beta1/gapic/__init__.py | 0 .../cloud/texttospeech_v1beta1/gapic/enums.py | 63 -- .../gapic/text_to_speech_client.py | 325 ------ .../gapic/text_to_speech_client_config.py | 33 - .../gapic/transports/__init__.py | 0 .../text_to_speech_grpc_transport.py | 135 --- .../texttospeech_v1beta1/proto/__init__.py | 0 .../proto/cloud_tts.proto | 254 ----- .../proto/cloud_tts_pb2.py | 976 ------------------ .../proto/cloud_tts_pb2_grpc.py | 67 -- google/cloud/texttospeech_v1beta1/py.typed | 2 + .../texttospeech_v1beta1/services/__init__.py | 16 + .../services/text_to_speech}/__init__.py | 16 +- .../services/text_to_speech/client.py | 369 +++++++ .../text_to_speech/transports/__init__.py | 30 + .../text_to_speech/transports/base.py | 76 ++ .../text_to_speech/transports/grpc.py | 212 ++++ google/cloud/texttospeech_v1beta1/types.py | 43 - .../texttospeech_v1beta1/types/__init__.py | 39 + .../texttospeech_v1beta1/types/cloud_tts.py | 265 +++++ mypy.ini | 3 + noxfile.py | 18 +- samples/snippets/.gitignore | 1 + samples/snippets/audio_profile.py | 38 +- samples/snippets/audio_profile_test.py | 9 +- samples/snippets/list_voices.py | 17 +- samples/snippets/list_voices_test.py | 6 +- samples/snippets/noxfile.py | 28 +- samples/snippets/quickstart.py | 21 +- samples/snippets/ssml_addresses.py | 36 +- samples/snippets/ssml_addresses_test.py | 10 +- samples/snippets/synthesize_file.py | 60 +- samples/snippets/synthesize_file_test.py | 12 +- samples/snippets/synthesize_text.py | 64 +- samples/snippets/synthesize_text_test.py | 12 +- scripts/decrypt-secrets.sh | 15 +- scripts/fixup_keywords.py | 178 ++++ setup.py | 17 +- synth.metadata | 10 +- synth.py | 41 +- tests/system/v1/test_system_tts_v1.py | 38 - .../system/v1beta1/test_system_tts_v1beta1.py | 40 - .../gapic/v1/test_text_to_speech_client_v1.py | 136 --- .../test_text_to_speech_client_v1beta1.py | 136 --- .../unit/texttospeech_v1}/__init__.py | 0 .../texttospeech_v1/test_text_to_speech.py | 453 ++++++++ .../unit/texttospeech_v1beta1}/__init__.py | 0 .../test_text_to_speech.py | 453 ++++++++ 91 files changed, 3695 insertions(+), 4494 deletions(-) create mode 100644 UPGRADING.md create mode 120000 docs/UPGRADING.md delete mode 100644 docs/api.rst delete mode 100644 docs/gapic/v1/api.rst delete mode 100644 docs/gapic/v1/types.rst delete mode 100644 docs/gapic/v1beta1/api.rst delete mode 100644 docs/gapic/v1beta1/types.rst create mode 100644 docs/multiprocessing.rst create mode 100644 docs/texttospeech_v1/services.rst create mode 100644 docs/texttospeech_v1/types.rst create mode 100644 docs/texttospeech_v1beta1/services.rst create mode 100644 docs/texttospeech_v1beta1/types.rst create mode 100644 google/cloud/texttospeech/__init__.py create mode 100644 google/cloud/texttospeech/py.typed delete mode 100644 google/cloud/texttospeech_v1/gapic/enums.py delete mode 100644 google/cloud/texttospeech_v1/gapic/text_to_speech_client.py delete mode 100644 google/cloud/texttospeech_v1/gapic/text_to_speech_client_config.py delete mode 100644 google/cloud/texttospeech_v1/gapic/transports/text_to_speech_grpc_transport.py delete mode 100644 google/cloud/texttospeech_v1/proto/__init__.py delete mode 100644 google/cloud/texttospeech_v1/proto/cloud_tts.proto delete mode 100644 google/cloud/texttospeech_v1/proto/cloud_tts_pb2.py delete mode 100644 google/cloud/texttospeech_v1/proto/cloud_tts_pb2_grpc.py create mode 100644 google/cloud/texttospeech_v1/py.typed rename google/cloud/{texttospeech.py => texttospeech_v1/services/__init__.py} (64%) rename google/{ => cloud/texttospeech_v1/services/text_to_speech}/__init__.py (66%) create mode 100644 google/cloud/texttospeech_v1/services/text_to_speech/client.py create mode 100644 google/cloud/texttospeech_v1/services/text_to_speech/transports/__init__.py create mode 100644 google/cloud/texttospeech_v1/services/text_to_speech/transports/base.py create mode 100644 google/cloud/texttospeech_v1/services/text_to_speech/transports/grpc.py delete mode 100644 google/cloud/texttospeech_v1/types.py create mode 100644 google/cloud/texttospeech_v1/types/__init__.py create mode 100644 google/cloud/texttospeech_v1/types/cloud_tts.py delete mode 100644 google/cloud/texttospeech_v1beta1/gapic/__init__.py delete mode 100644 google/cloud/texttospeech_v1beta1/gapic/enums.py delete mode 100644 google/cloud/texttospeech_v1beta1/gapic/text_to_speech_client.py delete mode 100644 google/cloud/texttospeech_v1beta1/gapic/text_to_speech_client_config.py delete mode 100644 google/cloud/texttospeech_v1beta1/gapic/transports/__init__.py delete mode 100644 google/cloud/texttospeech_v1beta1/gapic/transports/text_to_speech_grpc_transport.py delete mode 100644 google/cloud/texttospeech_v1beta1/proto/__init__.py delete mode 100644 google/cloud/texttospeech_v1beta1/proto/cloud_tts.proto delete mode 100644 google/cloud/texttospeech_v1beta1/proto/cloud_tts_pb2.py delete mode 100644 google/cloud/texttospeech_v1beta1/proto/cloud_tts_pb2_grpc.py create mode 100644 google/cloud/texttospeech_v1beta1/py.typed create mode 100644 google/cloud/texttospeech_v1beta1/services/__init__.py rename google/cloud/{ => texttospeech_v1beta1/services/text_to_speech}/__init__.py (66%) create mode 100644 google/cloud/texttospeech_v1beta1/services/text_to_speech/client.py create mode 100644 google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/__init__.py create mode 100644 google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/base.py create mode 100644 google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/grpc.py delete mode 100644 google/cloud/texttospeech_v1beta1/types.py create mode 100644 google/cloud/texttospeech_v1beta1/types/__init__.py create mode 100644 google/cloud/texttospeech_v1beta1/types/cloud_tts.py create mode 100644 mypy.ini create mode 100644 samples/snippets/.gitignore create mode 100644 scripts/fixup_keywords.py delete mode 100644 tests/system/v1/test_system_tts_v1.py delete mode 100644 tests/system/v1beta1/test_system_tts_v1beta1.py delete mode 100644 tests/unit/gapic/v1/test_text_to_speech_client_v1.py delete mode 100644 tests/unit/gapic/v1beta1/test_text_to_speech_client_v1beta1.py rename {google/cloud/texttospeech_v1/gapic => tests/unit/texttospeech_v1}/__init__.py (100%) create mode 100644 tests/unit/texttospeech_v1/test_text_to_speech.py rename {google/cloud/texttospeech_v1/gapic/transports => tests/unit/texttospeech_v1beta1}/__init__.py (100%) create mode 100644 tests/unit/texttospeech_v1beta1/test_text_to_speech.py diff --git a/.coveragerc b/.coveragerc index dd39c854..c30e7f80 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,35 +1,18 @@ -# -*- 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/texttospeech/__init__.py exclude_lines = # Re-enable the standard pragma pragma: NO COVER # Ignore debug-only repr def __repr__ - # Ignore abstract methods - raise NotImplementedError -omit = - */gapic/*.py - */proto/*.py - */core/*.py - */site-packages/*.py \ No newline at end of file + # 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 diff --git a/.flake8 b/.flake8 index 20fe9bda..d1134d72 100644 --- a/.flake8 +++ b/.flake8 @@ -16,11 +16,13 @@ # Generated by synthtool. DO NOT EDIT! [flake8] -ignore = E203, E266, E501, W503 +ignore = E203, E266, E501, W503, F401, F841 exclude = # Exclude generated code. **/proto/** **/gapic/** + **/services/** + **/types/** *_pb2.py # Standard linting exemptions. diff --git a/.gitignore b/.gitignore index 3fb06e09..b87e1ed5 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ dist build eggs +.eggs parts bin var @@ -49,6 +50,7 @@ bigquery/docs/generated # Virtual environment env/ coverage.xml +sponge_log.xml # System test environment variables. system_tests/local_test_setup diff --git a/.kokoro/publish-docs.sh b/.kokoro/publish-docs.sh index f61458f7..05976d09 100755 --- a/.kokoro/publish-docs.sh +++ b/.kokoro/publish-docs.sh @@ -13,8 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -#!/bin/bash - set -eo pipefail # Disable buffering, so that the logs stream through. diff --git a/.kokoro/release.sh b/.kokoro/release.sh index 63125c10..6102fdc8 100755 --- a/.kokoro/release.sh +++ b/.kokoro/release.sh @@ -13,8 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -#!/bin/bash - set -eo pipefail # Start the releasetool reporter diff --git a/.kokoro/test-samples.sh b/.kokoro/test-samples.sh index 42349554..51a72c73 100755 --- a/.kokoro/test-samples.sh +++ b/.kokoro/test-samples.sh @@ -37,12 +37,26 @@ env | grep KOKORO # Install nox python3.6 -m pip install --upgrade --quiet nox -# Unencrypt and extract secrets -SECRETS_PASSWORD=$(cat "${KOKORO_GFILE_DIR}/secrets-password.txt") -./scripts/decrypt-secrets.sh "${SECRETS_PASSWORD}" +# 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 ********************" diff --git a/MANIFEST.in b/MANIFEST.in index 68855abc..e9e29d12 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -20,3 +20,6 @@ recursive-include google *.json *.proto 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 diff --git a/README.rst b/README.rst index ee11ca7b..2b05c291 100644 --- a/README.rst +++ b/README.rst @@ -56,6 +56,8 @@ Deprecated Python Versions ^^^^^^^^^^^^^^^^^^^^^^^^^^ Python == 2.7. Python 2.7 support will be removed on January 1, 2020. +The last version of this library compatible with Python 2.7 is google-cloud-texttospeech==1.0.1. + Mac/Linux ^^^^^^^^^ diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 00000000..c198bb82 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,151 @@ +# 2.0.0 Migration Guide + +The 2.0 release of the `google-cloud-texttospeech` client is a significant upgrade based on a [next-gen code generator](https://github.com/googleapis/gapic-generator-python), and includes substantial interface changes. Existing code written for earlier versions of this library will likely require updates to use this version. This document describes the changes that have been made, and what you need to do to update your usage. + +If you experience issues or have questions, please file an [issue](https://github.com/googleapis/python-texttospeech/issues). + +## Supported Python Versions + +> **WARNING**: Breaking change + +The 2.0.0 release requires Python 3.6+. + + +## Method Calls + +> **WARNING**: Breaking change + +Methods expect request objects. We provide a script that will convert most common use cases. + +* Install the library + +```py +python3 -m pip install google-cloud-texttospeech +``` + +* The script `fixup_keywords.py` is shipped with the library. It expects +an input directory (with the code to convert) and an empty destination directory. + +```sh +$ fixup_keywords.py --input-directory .samples/ --output-directory samples/ +``` + +**Before:** +```py +from google.cloud import texttospeech + +client = texttospeech.TextToSpeechClient() + +voices = client.list_voices(language_code="no") +``` + + +**After:** +```py +from google.cloud import texttospeech + +client = texttospeech.TextToSpeechClient() + +voices = client.list_voices(request={"language_code": "no"}) +``` + +### More Details + +In `google-cloud-texttospeech<2.0.0`, parameters required by the API were positional parameters and optional parameters were keyword parameters. + +**Before:** +```py + def synthesize_speech( + self, + input_, + voice, + audio_config, + retry=google.api_core.gapic_v1.method.DEFAULT, + timeout=google.api_core.gapic_v1.method.DEFAULT, + metadata=None, + ): +``` + +In the 2.0.0 release, all methods have a single positional parameter `request`. Method docstrings indicate whether a parameter is required or optional. + +Some methods have additional keyword only parameters. The available parameters depend on the [`google.api.method_signature` annotation](https://github.com/googleapis/googleapis/blob/master/google/cloud/texttospeech/v1/cloud_tts.proto#L53) specified by the API producer. + + +**After:** +```py + def synthesize_speech( + self, + request: cloud_tts.SynthesizeSpeechRequest = None, + *, + input: cloud_tts.SynthesisInput = None, + voice: cloud_tts.VoiceSelectionParams = None, + audio_config: cloud_tts.AudioConfig = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> cloud_tts.SynthesizeSpeechResponse: +``` + +> **NOTE:** The `request` parameter and flattened keyword parameters for the API are mutually exclusive. +> Passing both will result in an error. + + +Both of these calls are valid: + +```py +response = client.synthesize_speech( + request={ + "input": input_text, + "voice": voice, + "audio_config": audio_config + } +) +``` + +```py +response = client.synthesize_speech( + input=input_text, + voice=voice, + audio_config=audio_config +) +``` + +This call is invalid because it mixes `request` with a keyword argument `audio_config`. Executing this code +will result in an error. + +```py +response = client.synthesize_speech( + request={ + "input": input_text, + "voice": voice, + }, + audio_config=audio_config +) +``` + + + +## Enums and Types + + +> **WARNING**: Breaking change + +The submodules `enums` and `types` have been removed. + +**Before:** +```py + +from google.cloud import texttospeech + +encoding = texttospeech.enums.AudioEncoding.MP3 +voice = texttospeech.types.VoiceSelectionParams(language_code="en-US") +``` + + +**After:** +```py +from google.cloud import texttospeech + +encoding = texttospeech.AudioEncoding.MP3 +voice = texttospeech.VoiceSelectionParams(language_code="en-US") +``` \ No newline at end of file diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md new file mode 120000 index 00000000..01097c8c --- /dev/null +++ b/docs/UPGRADING.md @@ -0,0 +1 @@ +../UPGRADING.md \ No newline at end of file diff --git a/docs/api.rst b/docs/api.rst deleted file mode 100644 index 8dd5fb3f..00000000 --- a/docs/api.rst +++ /dev/null @@ -1,30 +0,0 @@ -Text-to-Speech Client API Reference -=================================== - -This package includes clients for multiple versions of the Text-to-Speech -API. By default, you will get ``v1``, the latest GA version. - -.. toctree:: - :maxdepth: 2 - - gapic/v1/api - gapic/v1/types - -If you are interested in beta features ahead of the latest GA, you may -opt-in to the v1.1 beta, which is spelled ``v1beta1``. In order to do this, -you will want to import from ``google.cloud.texttospeech_v1beta1`` in lieu of -``google.cloud.texttospeech``. - -An API and type reference is provided for the v1.1 beta also: - -.. toctree:: - :maxdepth: 2 - - gapic/v1beta1/api - gapic/v1beta1/types - -.. note:: - - The client for the beta API is provided on a provisional basis. The API - surface is subject to change, and it is possible that this client will be - deprecated or removed after its features become GA. diff --git a/docs/gapic/v1/api.rst b/docs/gapic/v1/api.rst deleted file mode 100644 index 06d283f8..00000000 --- a/docs/gapic/v1/api.rst +++ /dev/null @@ -1,6 +0,0 @@ -Client for Cloud Text-to-Speech API -=================================== - -.. automodule:: google.cloud.texttospeech_v1 - :members: - :inherited-members: \ No newline at end of file diff --git a/docs/gapic/v1/types.rst b/docs/gapic/v1/types.rst deleted file mode 100644 index 4d230297..00000000 --- a/docs/gapic/v1/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Types for Cloud Text-to-Speech API Client -========================================= - -.. automodule:: google.cloud.texttospeech_v1.types - :members: \ No newline at end of file diff --git a/docs/gapic/v1beta1/api.rst b/docs/gapic/v1beta1/api.rst deleted file mode 100644 index f43d3383..00000000 --- a/docs/gapic/v1beta1/api.rst +++ /dev/null @@ -1,6 +0,0 @@ -Client for Cloud Text-to-Speech API -=================================== - -.. automodule:: google.cloud.texttospeech_v1beta1 - :members: - :inherited-members: \ No newline at end of file diff --git a/docs/gapic/v1beta1/types.rst b/docs/gapic/v1beta1/types.rst deleted file mode 100644 index 2cd73157..00000000 --- a/docs/gapic/v1beta1/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Types for Cloud Text-to-Speech API Client -========================================= - -.. automodule:: google.cloud.texttospeech_v1beta1.types - :members: \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index ccb81375..c89849d5 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,15 +1,43 @@ .. include:: README.rst -Api Reference -------------- +.. include:: multiprocessing.rst + +This package includes clients for multiple versions of the Text-to-Speech +API. By default, you will get ``v1``, the latest GA version. + +v1 API Reference +---------------- +.. toctree:: + :maxdepth: 2 + + Client (v1) + Types (v1) + + +If you are interested in beta features ahead of the latest GA, you may +opt-in to the v1.1 beta, which is spelled ``v1beta1``. In order to do this, +you will want to import from ``google.cloud.texttospeech_v1beta1`` in lieu of +``google.cloud.texttospeech``. + +v1beta1 API Reference +--------------------- .. toctree:: :maxdepth: 2 + + Client (v1beta1) + Types (v1beta1) + + +Migration Guide +--------------- + +See the guide below for instructions on migrating to the 2.x release of this library. + +.. toctree:: + :maxdepth: 2 + + UPGRADING - Text-to-Speech Client API Reference - Client for Cloud Text-to-Speech API (v1) - Types for Cloud Text-to-Speech API Client (v1) - Client for Cloud Text-to-Speech API (v1beta1) - Types for Cloud Text-to-Speech API Client (v1beta1) Changelog --------- diff --git a/docs/multiprocessing.rst b/docs/multiprocessing.rst new file mode 100644 index 00000000..1cb29d4c --- /dev/null +++ b/docs/multiprocessing.rst @@ -0,0 +1,7 @@ +.. note:: + + Because this client uses :mod:`grpcio` library, it is safe to + share instances across threads. In multiprocessing scenarios, the best + practice is to create client instances *after* the invocation of + :func:`os.fork` by :class:`multiprocessing.Pool` or + :class:`multiprocessing.Process`. diff --git a/docs/texttospeech_v1/services.rst b/docs/texttospeech_v1/services.rst new file mode 100644 index 00000000..9f65d607 --- /dev/null +++ b/docs/texttospeech_v1/services.rst @@ -0,0 +1,6 @@ +Client for Google Cloud Texttospeech API +======================================== + +.. automodule:: google.cloud.texttospeech_v1 + :members: + :inherited-members: diff --git a/docs/texttospeech_v1/types.rst b/docs/texttospeech_v1/types.rst new file mode 100644 index 00000000..bdbf4056 --- /dev/null +++ b/docs/texttospeech_v1/types.rst @@ -0,0 +1,5 @@ +Types for Google Cloud Texttospeech API +======================================= + +.. automodule:: google.cloud.texttospeech_v1.types + :members: diff --git a/docs/texttospeech_v1beta1/services.rst b/docs/texttospeech_v1beta1/services.rst new file mode 100644 index 00000000..22fd9307 --- /dev/null +++ b/docs/texttospeech_v1beta1/services.rst @@ -0,0 +1,6 @@ +Client for Google Cloud Texttospeech API +======================================== + +.. automodule:: google.cloud.texttospeech_v1beta1 + :members: + :inherited-members: diff --git a/docs/texttospeech_v1beta1/types.rst b/docs/texttospeech_v1beta1/types.rst new file mode 100644 index 00000000..ba72a5f1 --- /dev/null +++ b/docs/texttospeech_v1beta1/types.rst @@ -0,0 +1,5 @@ +Types for Google Cloud Texttospeech API +======================================= + +.. automodule:: google.cloud.texttospeech_v1beta1.types + :members: diff --git a/google/cloud/texttospeech/__init__.py b/google/cloud/texttospeech/__init__.py new file mode 100644 index 00000000..5a80d1d1 --- /dev/null +++ b/google/cloud/texttospeech/__init__.py @@ -0,0 +1,45 @@ +# -*- 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. +# + + +from google.cloud.texttospeech_v1.services.text_to_speech.client import ( + TextToSpeechClient, +) +from google.cloud.texttospeech_v1.types.cloud_tts import AudioConfig +from google.cloud.texttospeech_v1.types.cloud_tts import AudioEncoding +from google.cloud.texttospeech_v1.types.cloud_tts import ListVoicesRequest +from google.cloud.texttospeech_v1.types.cloud_tts import ListVoicesResponse +from google.cloud.texttospeech_v1.types.cloud_tts import SsmlVoiceGender +from google.cloud.texttospeech_v1.types.cloud_tts import SynthesisInput +from google.cloud.texttospeech_v1.types.cloud_tts import SynthesizeSpeechRequest +from google.cloud.texttospeech_v1.types.cloud_tts import SynthesizeSpeechResponse +from google.cloud.texttospeech_v1.types.cloud_tts import Voice +from google.cloud.texttospeech_v1.types.cloud_tts import VoiceSelectionParams + +__all__ = ( + "AudioConfig", + "AudioEncoding", + "ListVoicesRequest", + "ListVoicesResponse", + "SsmlVoiceGender", + "SynthesisInput", + "SynthesizeSpeechRequest", + "SynthesizeSpeechResponse", + "TextToSpeechClient", + "Voice", + "VoiceSelectionParams", +) diff --git a/google/cloud/texttospeech/py.typed b/google/cloud/texttospeech/py.typed new file mode 100644 index 00000000..9b87c1e1 --- /dev/null +++ b/google/cloud/texttospeech/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-texttospeech package uses inline types. diff --git a/google/cloud/texttospeech_v1/__init__.py b/google/cloud/texttospeech_v1/__init__.py index 1c5bf4b4..b0f218b1 100644 --- a/google/cloud/texttospeech_v1/__init__.py +++ b/google/cloud/texttospeech_v1/__init__.py @@ -1,41 +1,44 @@ # -*- 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 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# -from __future__ import absolute_import -import sys -import warnings - -from google.cloud.texttospeech_v1 import types -from google.cloud.texttospeech_v1.gapic import enums -from google.cloud.texttospeech_v1.gapic import text_to_speech_client - - -if sys.version_info[:2] == (2, 7): - message = ( - "A future version of this library will drop support for Python 2.7." - "More details about Python 2 support for Google Cloud Client Libraries" - "can be found at https://cloud.google.com/python/docs/python2-sunset/" - ) - warnings.warn(message, DeprecationWarning) - - -class TextToSpeechClient(text_to_speech_client.TextToSpeechClient): - __doc__ = text_to_speech_client.TextToSpeechClient.__doc__ - enums = enums - - -__all__ = ("enums", "types", "TextToSpeechClient") +from .services.text_to_speech import TextToSpeechClient +from .types.cloud_tts import AudioConfig +from .types.cloud_tts import AudioEncoding +from .types.cloud_tts import ListVoicesRequest +from .types.cloud_tts import ListVoicesResponse +from .types.cloud_tts import SsmlVoiceGender +from .types.cloud_tts import SynthesisInput +from .types.cloud_tts import SynthesizeSpeechRequest +from .types.cloud_tts import SynthesizeSpeechResponse +from .types.cloud_tts import Voice +from .types.cloud_tts import VoiceSelectionParams + + +__all__ = ( + "AudioConfig", + "AudioEncoding", + "ListVoicesRequest", + "ListVoicesResponse", + "SsmlVoiceGender", + "SynthesisInput", + "SynthesizeSpeechRequest", + "SynthesizeSpeechResponse", + "Voice", + "VoiceSelectionParams", + "TextToSpeechClient", +) diff --git a/google/cloud/texttospeech_v1/gapic/enums.py b/google/cloud/texttospeech_v1/gapic/enums.py deleted file mode 100644 index b0bc2782..00000000 --- a/google/cloud/texttospeech_v1/gapic/enums.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- 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. - -"""Wrappers for protocol buffer enum types.""" - -import enum - - -class AudioEncoding(enum.IntEnum): - """ - Configuration to set up audio encoder. The encoding determines the output - audio format that we'd like. - - Attributes: - AUDIO_ENCODING_UNSPECIFIED (int): Not specified. Will return result ``google.rpc.Code.INVALID_ARGUMENT``. - LINEAR16 (int): Uncompressed 16-bit signed little-endian samples (Linear PCM). - Audio content returned as LINEAR16 also contains a WAV header. - MP3 (int): MP3 audio at 32kbps. - OGG_OPUS (int): Opus encoded audio wrapped in an ogg container. The result will be a - file which can be played natively on Android, and in browsers (at least - Chrome and Firefox). The quality of the encoding is considerably higher - than MP3 while using approximately the same bitrate. - """ - - AUDIO_ENCODING_UNSPECIFIED = 0 - LINEAR16 = 1 - MP3 = 2 - OGG_OPUS = 3 - - -class SsmlVoiceGender(enum.IntEnum): - """ - Gender of the voice as described in `SSML voice - element `__. - - Attributes: - SSML_VOICE_GENDER_UNSPECIFIED (int): An unspecified gender. - In VoiceSelectionParams, this means that the client doesn't care which - gender the selected voice will have. In the Voice field of - ListVoicesResponse, this may mean that the voice doesn't fit any of the - other categories in this enum, or that the gender of the voice isn't known. - MALE (int): A male voice. - FEMALE (int): A female voice. - NEUTRAL (int): A gender-neutral voice. - """ - - SSML_VOICE_GENDER_UNSPECIFIED = 0 - MALE = 1 - FEMALE = 2 - NEUTRAL = 3 diff --git a/google/cloud/texttospeech_v1/gapic/text_to_speech_client.py b/google/cloud/texttospeech_v1/gapic/text_to_speech_client.py deleted file mode 100644 index eaa362a3..00000000 --- a/google/cloud/texttospeech_v1/gapic/text_to_speech_client.py +++ /dev/null @@ -1,323 +0,0 @@ -# -*- 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. - -"""Accesses the google.cloud.texttospeech.v1 TextToSpeech API.""" - -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.grpc_helpers -import grpc - -from google.cloud.texttospeech_v1.gapic import enums -from google.cloud.texttospeech_v1.gapic import text_to_speech_client_config -from google.cloud.texttospeech_v1.gapic.transports import text_to_speech_grpc_transport -from google.cloud.texttospeech_v1.proto import cloud_tts_pb2 -from google.cloud.texttospeech_v1.proto import cloud_tts_pb2_grpc - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution( - "google-cloud-texttospeech" -).version - - -class TextToSpeechClient(object): - """Service that implements Google Cloud Text-to-Speech API.""" - - SERVICE_ADDRESS = "texttospeech.googleapis.com:443" - """The default address of the service.""" - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.cloud.texttospeech.v1.TextToSpeech" - - @classmethod - def from_service_account_file(cls, filename, *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: - TextToSpeechClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.TextToSpeechGrpcTransport, - Callable[[~.Credentials, type], ~.TextToSpeechGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = text_to_speech_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=text_to_speech_grpc_transport.TextToSpeechGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = text_to_speech_grpc_transport.TextToSpeechGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def list_voices( - self, - language_code=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Returns a list of Voice supported for synthesis. - - Example: - >>> from google.cloud import texttospeech_v1 - >>> - >>> client = texttospeech_v1.TextToSpeechClient() - >>> - >>> response = client.list_voices() - - Args: - language_code (str): Optional. Recommended. - `BCP-47 `__ language tag. - If specified, the ListVoices call will only return voices that can be - used to synthesize this language\_code. E.g. when specifying "en-NZ", - you will get supported "en-*" voices; when specifying "no", you will get - supported "no-*" (Norwegian) and "nb-*" (Norwegian Bokmal) voices; - specifying "zh" will also get supported "cmn-*" voices; specifying - "zh-hk" will also get supported "yue-\*" voices. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.texttospeech_v1.types.ListVoicesResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_voices" not in self._inner_api_calls: - self._inner_api_calls[ - "list_voices" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_voices, - default_retry=self._method_configs["ListVoices"].retry, - default_timeout=self._method_configs["ListVoices"].timeout, - client_info=self._client_info, - ) - - request = cloud_tts_pb2.ListVoicesRequest(language_code=language_code) - return self._inner_api_calls["list_voices"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def synthesize_speech( - self, - input_, - voice, - audio_config, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Synthesizes speech synchronously: receive results after all text input - has been processed. - - Example: - >>> from google.cloud import texttospeech_v1 - >>> - >>> client = texttospeech_v1.TextToSpeechClient() - >>> - >>> # TODO: Initialize `input_`: - >>> input_ = {} - >>> - >>> # TODO: Initialize `voice`: - >>> voice = {} - >>> - >>> # TODO: Initialize `audio_config`: - >>> audio_config = {} - >>> - >>> response = client.synthesize_speech(input_, voice, audio_config) - - Args: - input_ (Union[dict, ~google.cloud.texttospeech_v1.types.SynthesisInput]): Required. The Synthesizer requires either plain text or SSML as input. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.texttospeech_v1.types.SynthesisInput` - voice (Union[dict, ~google.cloud.texttospeech_v1.types.VoiceSelectionParams]): Required. The desired voice of the synthesized audio. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.texttospeech_v1.types.VoiceSelectionParams` - audio_config (Union[dict, ~google.cloud.texttospeech_v1.types.AudioConfig]): Required. The configuration of the synthesized audio. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.texttospeech_v1.types.AudioConfig` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.texttospeech_v1.types.SynthesizeSpeechResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "synthesize_speech" not in self._inner_api_calls: - self._inner_api_calls[ - "synthesize_speech" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.synthesize_speech, - default_retry=self._method_configs["SynthesizeSpeech"].retry, - default_timeout=self._method_configs["SynthesizeSpeech"].timeout, - client_info=self._client_info, - ) - - request = cloud_tts_pb2.SynthesizeSpeechRequest( - input=input_, voice=voice, audio_config=audio_config - ) - return self._inner_api_calls["synthesize_speech"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) diff --git a/google/cloud/texttospeech_v1/gapic/text_to_speech_client_config.py b/google/cloud/texttospeech_v1/gapic/text_to_speech_client_config.py deleted file mode 100644 index 5c86cb22..00000000 --- a/google/cloud/texttospeech_v1/gapic/text_to_speech_client_config.py +++ /dev/null @@ -1,33 +0,0 @@ -config = { - "interfaces": { - "google.cloud.texttospeech.v1.TextToSpeech": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 20000, - "total_timeout_millis": 600000, - } - }, - "methods": { - "ListVoices": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "SynthesizeSpeech": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/google/cloud/texttospeech_v1/gapic/transports/text_to_speech_grpc_transport.py b/google/cloud/texttospeech_v1/gapic/transports/text_to_speech_grpc_transport.py deleted file mode 100644 index 4c0b4922..00000000 --- a/google/cloud/texttospeech_v1/gapic/transports/text_to_speech_grpc_transport.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- 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. - - -import google.api_core.grpc_helpers - -from google.cloud.texttospeech_v1.proto import cloud_tts_pb2_grpc - - -class TextToSpeechGrpcTransport(object): - """gRPC transport class providing stubs for - google.cloud.texttospeech.v1 TextToSpeech API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - - def __init__( - self, channel=None, credentials=None, address="texttospeech.googleapis.com:443" - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = { - "text_to_speech_stub": cloud_tts_pb2_grpc.TextToSpeechStub(channel) - } - - @classmethod - def create_channel( - cls, address="texttospeech.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def list_voices(self): - """Return the gRPC stub for :meth:`TextToSpeechClient.list_voices`. - - Returns a list of Voice supported for synthesis. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["text_to_speech_stub"].ListVoices - - @property - def synthesize_speech(self): - """Return the gRPC stub for :meth:`TextToSpeechClient.synthesize_speech`. - - Synthesizes speech synchronously: receive results after all text input - has been processed. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["text_to_speech_stub"].SynthesizeSpeech diff --git a/google/cloud/texttospeech_v1/proto/__init__.py b/google/cloud/texttospeech_v1/proto/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/google/cloud/texttospeech_v1/proto/cloud_tts.proto b/google/cloud/texttospeech_v1/proto/cloud_tts.proto deleted file mode 100644 index 6134ef64..00000000 --- a/google/cloud/texttospeech_v1/proto/cloud_tts.proto +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2019 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. -// - -syntax = "proto3"; - -package google.cloud.texttospeech.v1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; - -option cc_enable_arenas = true; -option csharp_namespace = "Google.Cloud.TextToSpeech.V1"; -option go_package = "google.golang.org/genproto/googleapis/cloud/texttospeech/v1;texttospeech"; -option java_multiple_files = true; -option java_outer_classname = "TextToSpeechProto"; -option java_package = "com.google.cloud.texttospeech.v1"; -option php_namespace = "Google\\Cloud\\TextToSpeech\\V1"; -option ruby_package = "Google::Cloud::TextToSpeech::V1"; - -// Service that implements Google Cloud Text-to-Speech API. -service TextToSpeech { - option (google.api.default_host) = "texttospeech.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Returns a list of Voice supported for synthesis. - rpc ListVoices(ListVoicesRequest) returns (ListVoicesResponse) { - option (google.api.http) = { - get: "/v1/voices" - }; - option (google.api.method_signature) = "language_code"; - } - - // Synthesizes speech synchronously: receive results after all text input - // has been processed. - rpc SynthesizeSpeech(SynthesizeSpeechRequest) returns (SynthesizeSpeechResponse) { - option (google.api.http) = { - post: "/v1/text:synthesize" - body: "*" - }; - option (google.api.method_signature) = "input,voice,audio_config"; - } -} - -// The top-level message sent by the client for the `ListVoices` method. -message ListVoicesRequest { - // Optional. Recommended. - // [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tag. If - // specified, the ListVoices call will only return voices that can be used to - // synthesize this language_code. E.g. when specifying "en-NZ", you will get - // supported "en-*" voices; when specifying "no", you will get supported - // "no-*" (Norwegian) and "nb-*" (Norwegian Bokmal) voices; specifying "zh" - // will also get supported "cmn-*" voices; specifying "zh-hk" will also get - // supported "yue-*" voices. - string language_code = 1 [(google.api.field_behavior) = OPTIONAL]; -} - -// Gender of the voice as described in -// [SSML voice element](https://www.w3.org/TR/speech-synthesis11/#edef_voice). -enum SsmlVoiceGender { - // An unspecified gender. - // In VoiceSelectionParams, this means that the client doesn't care which - // gender the selected voice will have. In the Voice field of - // ListVoicesResponse, this may mean that the voice doesn't fit any of the - // other categories in this enum, or that the gender of the voice isn't known. - SSML_VOICE_GENDER_UNSPECIFIED = 0; - - // A male voice. - MALE = 1; - - // A female voice. - FEMALE = 2; - - // A gender-neutral voice. - NEUTRAL = 3; -} - -// Configuration to set up audio encoder. The encoding determines the output -// audio format that we'd like. -enum AudioEncoding { - // Not specified. Will return result [google.rpc.Code.INVALID_ARGUMENT][]. - AUDIO_ENCODING_UNSPECIFIED = 0; - - // Uncompressed 16-bit signed little-endian samples (Linear PCM). - // Audio content returned as LINEAR16 also contains a WAV header. - LINEAR16 = 1; - - // MP3 audio at 32kbps. - MP3 = 2; - - // Opus encoded audio wrapped in an ogg container. The result will be a - // file which can be played natively on Android, and in browsers (at least - // Chrome and Firefox). The quality of the encoding is considerably higher - // than MP3 while using approximately the same bitrate. - OGG_OPUS = 3; -} - -// The message returned to the client by the `ListVoices` method. -message ListVoicesResponse { - // The list of voices. - repeated Voice voices = 1; -} - -// Description of a voice supported by the TTS service. -message Voice { - // The languages that this voice supports, expressed as - // [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tags (e.g. - // "en-US", "es-419", "cmn-tw"). - repeated string language_codes = 1; - - // The name of this voice. Each distinct voice has a unique name. - string name = 2; - - // The gender of this voice. - SsmlVoiceGender ssml_gender = 3; - - // The natural sample rate (in hertz) for this voice. - int32 natural_sample_rate_hertz = 4; -} - -// The top-level message sent by the client for the `SynthesizeSpeech` method. -message SynthesizeSpeechRequest { - // Required. The Synthesizer requires either plain text or SSML as input. - SynthesisInput input = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. The desired voice of the synthesized audio. - VoiceSelectionParams voice = 2 [(google.api.field_behavior) = REQUIRED]; - - // Required. The configuration of the synthesized audio. - AudioConfig audio_config = 3 [(google.api.field_behavior) = REQUIRED]; -} - -// Contains text input to be synthesized. Either `text` or `ssml` must be -// supplied. Supplying both or neither returns -// [google.rpc.Code.INVALID_ARGUMENT][]. The input size is limited to 5000 -// characters. -message SynthesisInput { - // The input source, which is either plain text or SSML. - oneof input_source { - // The raw text to be synthesized. - string text = 1; - - // The SSML document to be synthesized. The SSML document must be valid - // and well-formed. Otherwise the RPC will fail and return - // [google.rpc.Code.INVALID_ARGUMENT][]. For more information, see - // [SSML](/speech/text-to-speech/docs/ssml). - string ssml = 2; - } -} - -// Description of which voice to use for a synthesis request. -message VoiceSelectionParams { - // Required. The language (and potentially also the region) of the voice expressed as a - // [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tag, e.g. - // "en-US". This should not include a script tag (e.g. use - // "cmn-cn" rather than "cmn-Hant-cn"), because the script will be inferred - // from the input provided in the SynthesisInput. The TTS service - // will use this parameter to help choose an appropriate voice. Note that - // the TTS service may choose a voice with a slightly different language code - // than the one selected; it may substitute a different region - // (e.g. using en-US rather than en-CA if there isn't a Canadian voice - // available), or even a different language, e.g. using "nb" (Norwegian - // Bokmal) instead of "no" (Norwegian)". - string language_code = 1 [(google.api.field_behavior) = REQUIRED]; - - // The name of the voice. If not set, the service will choose a - // voice based on the other parameters such as language_code and gender. - string name = 2; - - // The preferred gender of the voice. If not set, the service will - // choose a voice based on the other parameters such as language_code and - // name. Note that this is only a preference, not requirement; if a - // voice of the appropriate gender is not available, the synthesizer should - // substitute a voice with a different gender rather than failing the request. - SsmlVoiceGender ssml_gender = 3; -} - -// Description of audio data to be synthesized. -message AudioConfig { - // Required. The format of the audio byte stream. - AudioEncoding audio_encoding = 1 [(google.api.field_behavior) = REQUIRED]; - - // Optional. Input only. Speaking rate/speed, in the range [0.25, 4.0]. 1.0 is - // the normal native speed supported by the specific voice. 2.0 is twice as - // fast, and 0.5 is half as fast. If unset(0.0), defaults to the native 1.0 - // speed. Any other values < 0.25 or > 4.0 will return an error. - double speaking_rate = 2 [ - (google.api.field_behavior) = INPUT_ONLY, - (google.api.field_behavior) = OPTIONAL - ]; - - // Optional. Input only. Speaking pitch, in the range [-20.0, 20.0]. 20 means - // increase 20 semitones from the original pitch. -20 means decrease 20 - // semitones from the original pitch. - double pitch = 3 [ - (google.api.field_behavior) = INPUT_ONLY, - (google.api.field_behavior) = OPTIONAL - ]; - - // Optional. Input only. Volume gain (in dB) of the normal native volume - // supported by the specific voice, in the range [-96.0, 16.0]. If unset, or - // set to a value of 0.0 (dB), will play at normal native signal amplitude. A - // value of -6.0 (dB) will play at approximately half the amplitude of the - // normal native signal amplitude. A value of +6.0 (dB) will play at - // approximately twice the amplitude of the normal native signal amplitude. - // Strongly recommend not to exceed +10 (dB) as there's usually no effective - // increase in loudness for any value greater than that. - double volume_gain_db = 4 [ - (google.api.field_behavior) = INPUT_ONLY, - (google.api.field_behavior) = OPTIONAL - ]; - - // Optional. The synthesis sample rate (in hertz) for this audio. When this is - // specified in SynthesizeSpeechRequest, if this is different from the voice's - // natural sample rate, then the synthesizer will honor this request by - // converting to the desired sample rate (which might result in worse audio - // quality), unless the specified sample rate is not supported for the - // encoding chosen, in which case it will fail the request and return - // [google.rpc.Code.INVALID_ARGUMENT][]. - int32 sample_rate_hertz = 5 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. Input only. An identifier which selects 'audio effects' profiles - // that are applied on (post synthesized) text to speech. Effects are applied - // on top of each other in the order they are given. See - // [audio - // profiles](https://cloud.google.com/text-to-speech/docs/audio-profiles) for - // current supported profile ids. - repeated string effects_profile_id = 6 [ - (google.api.field_behavior) = INPUT_ONLY, - (google.api.field_behavior) = OPTIONAL - ]; -} - -// The message returned to the client by the `SynthesizeSpeech` method. -message SynthesizeSpeechResponse { - // The audio data bytes encoded as specified in the request, including the - // header for encodings that are wrapped in containers (e.g. MP3, OGG_OPUS). - // For LINEAR16 audio, we include the WAV header. Note: as - // with all bytes fields, protobuffers use a pure binary representation, - // whereas JSON representations use base64. - bytes audio_content = 1; -} diff --git a/google/cloud/texttospeech_v1/proto/cloud_tts_pb2.py b/google/cloud/texttospeech_v1/proto/cloud_tts_pb2.py deleted file mode 100644 index 2278576a..00000000 --- a/google/cloud/texttospeech_v1/proto/cloud_tts_pb2.py +++ /dev/null @@ -1,976 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/texttospeech_v1/proto/cloud_tts.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf.internal import enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/texttospeech_v1/proto/cloud_tts.proto", - package="google.cloud.texttospeech.v1", - syntax="proto3", - serialized_options=_b( - "\n com.google.cloud.texttospeech.v1B\021TextToSpeechProtoP\001ZHgoogle.golang.org/genproto/googleapis/cloud/texttospeech/v1;texttospeech\370\001\001\252\002\034Google.Cloud.TextToSpeech.V1\312\002\034Google\\Cloud\\TextToSpeech\\V1\352\002\037Google::Cloud::TextToSpeech::V1" - ), - serialized_pb=_b( - '\n2google/cloud/texttospeech_v1/proto/cloud_tts.proto\x12\x1cgoogle.cloud.texttospeech.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto"/\n\x11ListVoicesRequest\x12\x1a\n\rlanguage_code\x18\x01 \x01(\tB\x03\xe0\x41\x01"I\n\x12ListVoicesResponse\x12\x33\n\x06voices\x18\x01 \x03(\x0b\x32#.google.cloud.texttospeech.v1.Voice"\x94\x01\n\x05Voice\x12\x16\n\x0elanguage_codes\x18\x01 \x03(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x42\n\x0bssml_gender\x18\x03 \x01(\x0e\x32-.google.cloud.texttospeech.v1.SsmlVoiceGender\x12!\n\x19natural_sample_rate_hertz\x18\x04 \x01(\x05"\xe9\x01\n\x17SynthesizeSpeechRequest\x12@\n\x05input\x18\x01 \x01(\x0b\x32,.google.cloud.texttospeech.v1.SynthesisInputB\x03\xe0\x41\x02\x12\x46\n\x05voice\x18\x02 \x01(\x0b\x32\x32.google.cloud.texttospeech.v1.VoiceSelectionParamsB\x03\xe0\x41\x02\x12\x44\n\x0c\x61udio_config\x18\x03 \x01(\x0b\x32).google.cloud.texttospeech.v1.AudioConfigB\x03\xe0\x41\x02"@\n\x0eSynthesisInput\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12\x0e\n\x04ssml\x18\x02 \x01(\tH\x00\x42\x0e\n\x0cinput_source"\x84\x01\n\x14VoiceSelectionParams\x12\x1a\n\rlanguage_code\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x42\n\x0bssml_gender\x18\x03 \x01(\x0e\x32-.google.cloud.texttospeech.v1.SsmlVoiceGender"\xf1\x01\n\x0b\x41udioConfig\x12H\n\x0e\x61udio_encoding\x18\x01 \x01(\x0e\x32+.google.cloud.texttospeech.v1.AudioEncodingB\x03\xe0\x41\x02\x12\x1d\n\rspeaking_rate\x18\x02 \x01(\x01\x42\x06\xe0\x41\x04\xe0\x41\x01\x12\x15\n\x05pitch\x18\x03 \x01(\x01\x42\x06\xe0\x41\x04\xe0\x41\x01\x12\x1e\n\x0evolume_gain_db\x18\x04 \x01(\x01\x42\x06\xe0\x41\x04\xe0\x41\x01\x12\x1e\n\x11sample_rate_hertz\x18\x05 \x01(\x05\x42\x03\xe0\x41\x01\x12"\n\x12\x65\x66\x66\x65\x63ts_profile_id\x18\x06 \x03(\tB\x06\xe0\x41\x04\xe0\x41\x01"1\n\x18SynthesizeSpeechResponse\x12\x15\n\raudio_content\x18\x01 \x01(\x0c*W\n\x0fSsmlVoiceGender\x12!\n\x1dSSML_VOICE_GENDER_UNSPECIFIED\x10\x00\x12\x08\n\x04MALE\x10\x01\x12\n\n\x06\x46\x45MALE\x10\x02\x12\x0b\n\x07NEUTRAL\x10\x03*T\n\rAudioEncoding\x12\x1e\n\x1a\x41UDIO_ENCODING_UNSPECIFIED\x10\x00\x12\x0c\n\x08LINEAR16\x10\x01\x12\x07\n\x03MP3\x10\x02\x12\x0c\n\x08OGG_OPUS\x10\x03\x32\xb4\x03\n\x0cTextToSpeech\x12\x93\x01\n\nListVoices\x12/.google.cloud.texttospeech.v1.ListVoicesRequest\x1a\x30.google.cloud.texttospeech.v1.ListVoicesResponse""\x82\xd3\xe4\x93\x02\x0c\x12\n/v1/voices\xda\x41\rlanguage_code\x12\xbc\x01\n\x10SynthesizeSpeech\x12\x35.google.cloud.texttospeech.v1.SynthesizeSpeechRequest\x1a\x36.google.cloud.texttospeech.v1.SynthesizeSpeechResponse"9\x82\xd3\xe4\x93\x02\x18"\x13/v1/text:synthesize:\x01*\xda\x41\x18input,voice,audio_config\x1aO\xca\x41\x1btexttospeech.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformB\xe4\x01\n com.google.cloud.texttospeech.v1B\x11TextToSpeechProtoP\x01ZHgoogle.golang.org/genproto/googleapis/cloud/texttospeech/v1;texttospeech\xf8\x01\x01\xaa\x02\x1cGoogle.Cloud.TextToSpeech.V1\xca\x02\x1cGoogle\\Cloud\\TextToSpeech\\V1\xea\x02\x1fGoogle::Cloud::TextToSpeech::V1b\x06proto3' - ), - dependencies=[ - google_dot_api_dot_annotations__pb2.DESCRIPTOR, - google_dot_api_dot_client__pb2.DESCRIPTOR, - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - ], -) - -_SSMLVOICEGENDER = _descriptor.EnumDescriptor( - name="SsmlVoiceGender", - full_name="google.cloud.texttospeech.v1.SsmlVoiceGender", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="SSML_VOICE_GENDER_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="MALE", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="FEMALE", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="NEUTRAL", index=3, number=3, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1179, - serialized_end=1266, -) -_sym_db.RegisterEnumDescriptor(_SSMLVOICEGENDER) - -SsmlVoiceGender = enum_type_wrapper.EnumTypeWrapper(_SSMLVOICEGENDER) -_AUDIOENCODING = _descriptor.EnumDescriptor( - name="AudioEncoding", - full_name="google.cloud.texttospeech.v1.AudioEncoding", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="AUDIO_ENCODING_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="LINEAR16", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="MP3", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="OGG_OPUS", index=3, number=3, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1268, - serialized_end=1352, -) -_sym_db.RegisterEnumDescriptor(_AUDIOENCODING) - -AudioEncoding = enum_type_wrapper.EnumTypeWrapper(_AUDIOENCODING) -SSML_VOICE_GENDER_UNSPECIFIED = 0 -MALE = 1 -FEMALE = 2 -NEUTRAL = 3 -AUDIO_ENCODING_UNSPECIFIED = 0 -LINEAR16 = 1 -MP3 = 2 -OGG_OPUS = 3 - - -_LISTVOICESREQUEST = _descriptor.Descriptor( - name="ListVoicesRequest", - full_name="google.cloud.texttospeech.v1.ListVoicesRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="language_code", - full_name="google.cloud.texttospeech.v1.ListVoicesRequest.language_code", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=172, - serialized_end=219, -) - - -_LISTVOICESRESPONSE = _descriptor.Descriptor( - name="ListVoicesResponse", - full_name="google.cloud.texttospeech.v1.ListVoicesResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="voices", - full_name="google.cloud.texttospeech.v1.ListVoicesResponse.voices", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=221, - serialized_end=294, -) - - -_VOICE = _descriptor.Descriptor( - name="Voice", - full_name="google.cloud.texttospeech.v1.Voice", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="language_codes", - full_name="google.cloud.texttospeech.v1.Voice.language_codes", - index=0, - number=1, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.texttospeech.v1.Voice.name", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ssml_gender", - full_name="google.cloud.texttospeech.v1.Voice.ssml_gender", - index=2, - number=3, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="natural_sample_rate_hertz", - full_name="google.cloud.texttospeech.v1.Voice.natural_sample_rate_hertz", - index=3, - number=4, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=297, - serialized_end=445, -) - - -_SYNTHESIZESPEECHREQUEST = _descriptor.Descriptor( - name="SynthesizeSpeechRequest", - full_name="google.cloud.texttospeech.v1.SynthesizeSpeechRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="input", - full_name="google.cloud.texttospeech.v1.SynthesizeSpeechRequest.input", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="voice", - full_name="google.cloud.texttospeech.v1.SynthesizeSpeechRequest.voice", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="audio_config", - full_name="google.cloud.texttospeech.v1.SynthesizeSpeechRequest.audio_config", - index=2, - number=3, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=448, - serialized_end=681, -) - - -_SYNTHESISINPUT = _descriptor.Descriptor( - name="SynthesisInput", - full_name="google.cloud.texttospeech.v1.SynthesisInput", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="text", - full_name="google.cloud.texttospeech.v1.SynthesisInput.text", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ssml", - full_name="google.cloud.texttospeech.v1.SynthesisInput.ssml", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name="input_source", - full_name="google.cloud.texttospeech.v1.SynthesisInput.input_source", - index=0, - containing_type=None, - fields=[], - ) - ], - serialized_start=683, - serialized_end=747, -) - - -_VOICESELECTIONPARAMS = _descriptor.Descriptor( - name="VoiceSelectionParams", - full_name="google.cloud.texttospeech.v1.VoiceSelectionParams", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="language_code", - full_name="google.cloud.texttospeech.v1.VoiceSelectionParams.language_code", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.texttospeech.v1.VoiceSelectionParams.name", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ssml_gender", - full_name="google.cloud.texttospeech.v1.VoiceSelectionParams.ssml_gender", - index=2, - number=3, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=750, - serialized_end=882, -) - - -_AUDIOCONFIG = _descriptor.Descriptor( - name="AudioConfig", - full_name="google.cloud.texttospeech.v1.AudioConfig", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="audio_encoding", - full_name="google.cloud.texttospeech.v1.AudioConfig.audio_encoding", - index=0, - number=1, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="speaking_rate", - full_name="google.cloud.texttospeech.v1.AudioConfig.speaking_rate", - index=1, - number=2, - type=1, - cpp_type=5, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\004\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="pitch", - full_name="google.cloud.texttospeech.v1.AudioConfig.pitch", - index=2, - number=3, - type=1, - cpp_type=5, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\004\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="volume_gain_db", - full_name="google.cloud.texttospeech.v1.AudioConfig.volume_gain_db", - index=3, - number=4, - type=1, - cpp_type=5, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\004\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="sample_rate_hertz", - full_name="google.cloud.texttospeech.v1.AudioConfig.sample_rate_hertz", - index=4, - number=5, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="effects_profile_id", - full_name="google.cloud.texttospeech.v1.AudioConfig.effects_profile_id", - index=5, - number=6, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\004\340A\001"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=885, - serialized_end=1126, -) - - -_SYNTHESIZESPEECHRESPONSE = _descriptor.Descriptor( - name="SynthesizeSpeechResponse", - full_name="google.cloud.texttospeech.v1.SynthesizeSpeechResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="audio_content", - full_name="google.cloud.texttospeech.v1.SynthesizeSpeechResponse.audio_content", - index=0, - number=1, - type=12, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b(""), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1128, - serialized_end=1177, -) - -_LISTVOICESRESPONSE.fields_by_name["voices"].message_type = _VOICE -_VOICE.fields_by_name["ssml_gender"].enum_type = _SSMLVOICEGENDER -_SYNTHESIZESPEECHREQUEST.fields_by_name["input"].message_type = _SYNTHESISINPUT -_SYNTHESIZESPEECHREQUEST.fields_by_name["voice"].message_type = _VOICESELECTIONPARAMS -_SYNTHESIZESPEECHREQUEST.fields_by_name["audio_config"].message_type = _AUDIOCONFIG -_SYNTHESISINPUT.oneofs_by_name["input_source"].fields.append( - _SYNTHESISINPUT.fields_by_name["text"] -) -_SYNTHESISINPUT.fields_by_name[ - "text" -].containing_oneof = _SYNTHESISINPUT.oneofs_by_name["input_source"] -_SYNTHESISINPUT.oneofs_by_name["input_source"].fields.append( - _SYNTHESISINPUT.fields_by_name["ssml"] -) -_SYNTHESISINPUT.fields_by_name[ - "ssml" -].containing_oneof = _SYNTHESISINPUT.oneofs_by_name["input_source"] -_VOICESELECTIONPARAMS.fields_by_name["ssml_gender"].enum_type = _SSMLVOICEGENDER -_AUDIOCONFIG.fields_by_name["audio_encoding"].enum_type = _AUDIOENCODING -DESCRIPTOR.message_types_by_name["ListVoicesRequest"] = _LISTVOICESREQUEST -DESCRIPTOR.message_types_by_name["ListVoicesResponse"] = _LISTVOICESRESPONSE -DESCRIPTOR.message_types_by_name["Voice"] = _VOICE -DESCRIPTOR.message_types_by_name["SynthesizeSpeechRequest"] = _SYNTHESIZESPEECHREQUEST -DESCRIPTOR.message_types_by_name["SynthesisInput"] = _SYNTHESISINPUT -DESCRIPTOR.message_types_by_name["VoiceSelectionParams"] = _VOICESELECTIONPARAMS -DESCRIPTOR.message_types_by_name["AudioConfig"] = _AUDIOCONFIG -DESCRIPTOR.message_types_by_name["SynthesizeSpeechResponse"] = _SYNTHESIZESPEECHRESPONSE -DESCRIPTOR.enum_types_by_name["SsmlVoiceGender"] = _SSMLVOICEGENDER -DESCRIPTOR.enum_types_by_name["AudioEncoding"] = _AUDIOENCODING -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -ListVoicesRequest = _reflection.GeneratedProtocolMessageType( - "ListVoicesRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTVOICESREQUEST, - __module__="google.cloud.texttospeech_v1.proto.cloud_tts_pb2", - __doc__="""The top-level message sent by the client for the ``ListVoices`` - method. - Attributes: - language_code: - Optional. Recommended. `BCP-47 `__ language tag. If specified, - the ListVoices call will only return voices that can be used - to synthesize this language\_code. E.g. when specifying "en- - NZ", you will get supported "en-*" voices; when specifying - "no", you will get supported "no-*" (Norwegian) and "nb-*" - (Norwegian Bokmal) voices; specifying "zh" will also get - supported "cmn-*" voices; specifying "zh-hk" will also get - supported "yue-\*" voices. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1.ListVoicesRequest) - ), -) -_sym_db.RegisterMessage(ListVoicesRequest) - -ListVoicesResponse = _reflection.GeneratedProtocolMessageType( - "ListVoicesResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTVOICESRESPONSE, - __module__="google.cloud.texttospeech_v1.proto.cloud_tts_pb2", - __doc__="""The message returned to the client by the ``ListVoices`` method. - Attributes: - voices: - The list of voices. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1.ListVoicesResponse) - ), -) -_sym_db.RegisterMessage(ListVoicesResponse) - -Voice = _reflection.GeneratedProtocolMessageType( - "Voice", - (_message.Message,), - dict( - DESCRIPTOR=_VOICE, - __module__="google.cloud.texttospeech_v1.proto.cloud_tts_pb2", - __doc__="""Description of a voice supported by the TTS service. - Attributes: - language_codes: - The languages that this voice supports, expressed as `BCP-47 - `__ language - tags (e.g. "en-US", "es-419", "cmn-tw"). - name: - The name of this voice. Each distinct voice has a unique name. - ssml_gender: - The gender of this voice. - natural_sample_rate_hertz: - The natural sample rate (in hertz) for this voice. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1.Voice) - ), -) -_sym_db.RegisterMessage(Voice) - -SynthesizeSpeechRequest = _reflection.GeneratedProtocolMessageType( - "SynthesizeSpeechRequest", - (_message.Message,), - dict( - DESCRIPTOR=_SYNTHESIZESPEECHREQUEST, - __module__="google.cloud.texttospeech_v1.proto.cloud_tts_pb2", - __doc__="""The top-level message sent by the client for the ``SynthesizeSpeech`` - method. - Attributes: - input: - Required. The Synthesizer requires either plain text or SSML - as input. - voice: - Required. The desired voice of the synthesized audio. - audio_config: - Required. The configuration of the synthesized audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1.SynthesizeSpeechRequest) - ), -) -_sym_db.RegisterMessage(SynthesizeSpeechRequest) - -SynthesisInput = _reflection.GeneratedProtocolMessageType( - "SynthesisInput", - (_message.Message,), - dict( - DESCRIPTOR=_SYNTHESISINPUT, - __module__="google.cloud.texttospeech_v1.proto.cloud_tts_pb2", - __doc__="""Contains text input to be synthesized. Either ``text`` or ``ssml`` - must be supplied. Supplying both or neither returns - [google.rpc.Code.INVALID\_ARGUMENT][]. The input size is limited to - 5000 characters. - Attributes: - input_source: - The input source, which is either plain text or SSML. - text: - The raw text to be synthesized. - ssml: - The SSML document to be synthesized. The SSML document must be - valid and well-formed. Otherwise the RPC will fail and return - [google.rpc.Code.INVALID\_ARGUMENT][]. For more information, - see `SSML `__. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1.SynthesisInput) - ), -) -_sym_db.RegisterMessage(SynthesisInput) - -VoiceSelectionParams = _reflection.GeneratedProtocolMessageType( - "VoiceSelectionParams", - (_message.Message,), - dict( - DESCRIPTOR=_VOICESELECTIONPARAMS, - __module__="google.cloud.texttospeech_v1.proto.cloud_tts_pb2", - __doc__="""Description of which voice to use for a synthesis request. - Attributes: - language_code: - Required. The language (and potentially also the region) of - the voice expressed as a `BCP-47 `__ language tag, e.g. "en-US". - This should not include a script tag (e.g. use "cmn-cn" rather - than "cmn-Hant-cn"), because the script will be inferred from - the input provided in the SynthesisInput. The TTS service will - use this parameter to help choose an appropriate voice. Note - that the TTS service may choose a voice with a slightly - different language code than the one selected; it may - substitute a different region (e.g. using en-US rather than - en-CA if there isn't a Canadian voice available), or even a - different language, e.g. using "nb" (Norwegian Bokmal) instead - of "no" (Norwegian)". - name: - The name of the voice. If not set, the service will choose a - voice based on the other parameters such as language\_code and - gender. - ssml_gender: - The preferred gender of the voice. If not set, the service - will choose a voice based on the other parameters such as - language\_code and name. Note that this is only a preference, - not requirement; if a voice of the appropriate gender is not - available, the synthesizer should substitute a voice with a - different gender rather than failing the request. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1.VoiceSelectionParams) - ), -) -_sym_db.RegisterMessage(VoiceSelectionParams) - -AudioConfig = _reflection.GeneratedProtocolMessageType( - "AudioConfig", - (_message.Message,), - dict( - DESCRIPTOR=_AUDIOCONFIG, - __module__="google.cloud.texttospeech_v1.proto.cloud_tts_pb2", - __doc__="""Description of audio data to be synthesized. - Attributes: - audio_encoding: - Required. The format of the audio byte stream. - speaking_rate: - Optional. Input only. Speaking rate/speed, in the range [0.25, - 4.0]. 1.0 is the normal native speed supported by the specific - voice. 2.0 is twice as fast, and 0.5 is half as fast. If - unset(0.0), defaults to the native 1.0 speed. Any other values - < 0.25 or > 4.0 will return an error. - pitch: - Optional. Input only. Speaking pitch, in the range [-20.0, - 20.0]. 20 means increase 20 semitones from the original pitch. - -20 means decrease 20 semitones from the original pitch. - volume_gain_db: - Optional. Input only. Volume gain (in dB) of the normal native - volume supported by the specific voice, in the range [-96.0, - 16.0]. If unset, or set to a value of 0.0 (dB), will play at - normal native signal amplitude. A value of -6.0 (dB) will play - at approximately half the amplitude of the normal native - signal amplitude. A value of +6.0 (dB) will play at - approximately twice the amplitude of the normal native signal - amplitude. Strongly recommend not to exceed +10 (dB) as - there's usually no effective increase in loudness for any - value greater than that. - sample_rate_hertz: - Optional. The synthesis sample rate (in hertz) for this audio. - When this is specified in SynthesizeSpeechRequest, if this is - different from the voice's natural sample rate, then the - synthesizer will honor this request by converting to the - desired sample rate (which might result in worse audio - quality), unless the specified sample rate is not supported - for the encoding chosen, in which case it will fail the - request and return [google.rpc.Code.INVALID\_ARGUMENT][]. - effects_profile_id: - Optional. Input only. An identifier which selects 'audio - effects' profiles that are applied on (post synthesized) text - to speech. Effects are applied on top of each other in the - order they are given. See `audio profiles - `__ for current supported profile ids. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1.AudioConfig) - ), -) -_sym_db.RegisterMessage(AudioConfig) - -SynthesizeSpeechResponse = _reflection.GeneratedProtocolMessageType( - "SynthesizeSpeechResponse", - (_message.Message,), - dict( - DESCRIPTOR=_SYNTHESIZESPEECHRESPONSE, - __module__="google.cloud.texttospeech_v1.proto.cloud_tts_pb2", - __doc__="""The message returned to the client by the ``SynthesizeSpeech`` method. - Attributes: - audio_content: - The audio data bytes encoded as specified in the request, - including the header for encodings that are wrapped in - containers (e.g. MP3, OGG\_OPUS). For LINEAR16 audio, we - include the WAV header. Note: as with all bytes fields, - protobuffers use a pure binary representation, whereas JSON - representations use base64. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1.SynthesizeSpeechResponse) - ), -) -_sym_db.RegisterMessage(SynthesizeSpeechResponse) - - -DESCRIPTOR._options = None -_LISTVOICESREQUEST.fields_by_name["language_code"]._options = None -_SYNTHESIZESPEECHREQUEST.fields_by_name["input"]._options = None -_SYNTHESIZESPEECHREQUEST.fields_by_name["voice"]._options = None -_SYNTHESIZESPEECHREQUEST.fields_by_name["audio_config"]._options = None -_VOICESELECTIONPARAMS.fields_by_name["language_code"]._options = None -_AUDIOCONFIG.fields_by_name["audio_encoding"]._options = None -_AUDIOCONFIG.fields_by_name["speaking_rate"]._options = None -_AUDIOCONFIG.fields_by_name["pitch"]._options = None -_AUDIOCONFIG.fields_by_name["volume_gain_db"]._options = None -_AUDIOCONFIG.fields_by_name["sample_rate_hertz"]._options = None -_AUDIOCONFIG.fields_by_name["effects_profile_id"]._options = None - -_TEXTTOSPEECH = _descriptor.ServiceDescriptor( - name="TextToSpeech", - full_name="google.cloud.texttospeech.v1.TextToSpeech", - file=DESCRIPTOR, - index=0, - serialized_options=_b( - "\312A\033texttospeech.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform" - ), - serialized_start=1355, - serialized_end=1791, - methods=[ - _descriptor.MethodDescriptor( - name="ListVoices", - full_name="google.cloud.texttospeech.v1.TextToSpeech.ListVoices", - index=0, - containing_service=None, - input_type=_LISTVOICESREQUEST, - output_type=_LISTVOICESRESPONSE, - serialized_options=_b( - "\202\323\344\223\002\014\022\n/v1/voices\332A\rlanguage_code" - ), - ), - _descriptor.MethodDescriptor( - name="SynthesizeSpeech", - full_name="google.cloud.texttospeech.v1.TextToSpeech.SynthesizeSpeech", - index=1, - containing_service=None, - input_type=_SYNTHESIZESPEECHREQUEST, - output_type=_SYNTHESIZESPEECHRESPONSE, - serialized_options=_b( - '\202\323\344\223\002\030"\023/v1/text:synthesize:\001*\332A\030input,voice,audio_config' - ), - ), - ], -) -_sym_db.RegisterServiceDescriptor(_TEXTTOSPEECH) - -DESCRIPTOR.services_by_name["TextToSpeech"] = _TEXTTOSPEECH - -# @@protoc_insertion_point(module_scope) diff --git a/google/cloud/texttospeech_v1/proto/cloud_tts_pb2_grpc.py b/google/cloud/texttospeech_v1/proto/cloud_tts_pb2_grpc.py deleted file mode 100644 index b1e7bfed..00000000 --- a/google/cloud/texttospeech_v1/proto/cloud_tts_pb2_grpc.py +++ /dev/null @@ -1,67 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.texttospeech_v1.proto import ( - cloud_tts_pb2 as google_dot_cloud_dot_texttospeech__v1_dot_proto_dot_cloud__tts__pb2, -) - - -class TextToSpeechStub(object): - """Service that implements Google Cloud Text-to-Speech API. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.ListVoices = channel.unary_unary( - "/google.cloud.texttospeech.v1.TextToSpeech/ListVoices", - request_serializer=google_dot_cloud_dot_texttospeech__v1_dot_proto_dot_cloud__tts__pb2.ListVoicesRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_texttospeech__v1_dot_proto_dot_cloud__tts__pb2.ListVoicesResponse.FromString, - ) - self.SynthesizeSpeech = channel.unary_unary( - "/google.cloud.texttospeech.v1.TextToSpeech/SynthesizeSpeech", - request_serializer=google_dot_cloud_dot_texttospeech__v1_dot_proto_dot_cloud__tts__pb2.SynthesizeSpeechRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_texttospeech__v1_dot_proto_dot_cloud__tts__pb2.SynthesizeSpeechResponse.FromString, - ) - - -class TextToSpeechServicer(object): - """Service that implements Google Cloud Text-to-Speech API. - """ - - def ListVoices(self, request, context): - """Returns a list of Voice supported for synthesis. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def SynthesizeSpeech(self, request, context): - """Synthesizes speech synchronously: receive results after all text input - has been processed. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_TextToSpeechServicer_to_server(servicer, server): - rpc_method_handlers = { - "ListVoices": grpc.unary_unary_rpc_method_handler( - servicer.ListVoices, - request_deserializer=google_dot_cloud_dot_texttospeech__v1_dot_proto_dot_cloud__tts__pb2.ListVoicesRequest.FromString, - response_serializer=google_dot_cloud_dot_texttospeech__v1_dot_proto_dot_cloud__tts__pb2.ListVoicesResponse.SerializeToString, - ), - "SynthesizeSpeech": grpc.unary_unary_rpc_method_handler( - servicer.SynthesizeSpeech, - request_deserializer=google_dot_cloud_dot_texttospeech__v1_dot_proto_dot_cloud__tts__pb2.SynthesizeSpeechRequest.FromString, - response_serializer=google_dot_cloud_dot_texttospeech__v1_dot_proto_dot_cloud__tts__pb2.SynthesizeSpeechResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.cloud.texttospeech.v1.TextToSpeech", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/google/cloud/texttospeech_v1/py.typed b/google/cloud/texttospeech_v1/py.typed new file mode 100644 index 00000000..9b87c1e1 --- /dev/null +++ b/google/cloud/texttospeech_v1/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-texttospeech package uses inline types. diff --git a/google/cloud/texttospeech.py b/google/cloud/texttospeech_v1/services/__init__.py similarity index 64% rename from google/cloud/texttospeech.py rename to google/cloud/texttospeech_v1/services/__init__.py index 4f5e3507..42ffdf2b 100644 --- a/google/cloud/texttospeech.py +++ b/google/cloud/texttospeech_v1/services/__init__.py @@ -1,25 +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 # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - - -from __future__ import absolute_import - -from google.cloud.texttospeech_v1 import TextToSpeechClient -from google.cloud.texttospeech_v1 import enums -from google.cloud.texttospeech_v1 import types - - -__all__ = ("enums", "types", "TextToSpeechClient") +# diff --git a/google/__init__.py b/google/cloud/texttospeech_v1/services/text_to_speech/__init__.py similarity index 66% rename from google/__init__.py rename to google/cloud/texttospeech_v1/services/text_to_speech/__init__.py index dd3a9f48..9ec2d969 100644 --- a/google/__init__.py +++ b/google/cloud/texttospeech_v1/services/text_to_speech/__init__.py @@ -1,22 +1,20 @@ -# Copyright 2018 Google LLC +# -*- 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 +# 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. +# -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil +from .client import TextToSpeechClient - __path__ = pkgutil.extend_path(__path__, __name__) +__all__ = ("TextToSpeechClient",) diff --git a/google/cloud/texttospeech_v1/services/text_to_speech/client.py b/google/cloud/texttospeech_v1/services/text_to_speech/client.py new file mode 100644 index 00000000..5c9e45f8 --- /dev/null +++ b/google/cloud/texttospeech_v1/services/text_to_speech/client.py @@ -0,0 +1,369 @@ +# -*- 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. +# + +from collections import OrderedDict +import re +from typing import Callable, Dict, Sequence, Tuple, Type, Union +import pkg_resources + +import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.texttospeech_v1.types import cloud_tts + +from .transports.base import TextToSpeechTransport +from .transports.grpc import TextToSpeechGrpcTransport + + +class TextToSpeechClientMeta(type): + """Metaclass for the TextToSpeech client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = OrderedDict() # type: Dict[str, Type[TextToSpeechTransport]] + _transport_registry["grpc"] = TextToSpeechGrpcTransport + + def get_transport_class(cls, label: str = None) -> Type[TextToSpeechTransport]: + """Return an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class TextToSpeechClient(metaclass=TextToSpeechClientMeta): + """Service that implements Google Cloud Text-to-Speech API.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Convert api endpoint to mTLS endpoint. + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + DEFAULT_ENDPOINT = "texttospeech.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + {@api.name}: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + def __init__( + self, + *, + credentials: credentials.Credentials = None, + transport: Union[str, TextToSpeechTransport] = None, + client_options: ClientOptions = None, + ) -> None: + """Instantiate the text to speech client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Union[str, ~.TextToSpeechTransport]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (ClientOptions): Custom options for the client. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. + (2) If ``transport`` argument is None, ``client_options`` can be + used to create a mutual TLS transport. If ``client_cert_source`` + is provided, mutual TLS transport will be created with the given + ``api_endpoint`` or the default mTLS endpoint, and the client + SSL credentials obtained from ``client_cert_source``. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + if isinstance(client_options, dict): + client_options = ClientOptions.from_dict(client_options) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, TextToSpeechTransport): + # transport is a TextToSpeechTransport instance. + if credentials: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + self._transport = transport + elif client_options is None or ( + client_options.api_endpoint is None + and client_options.client_cert_source is None + ): + # Don't trigger mTLS if we get an empty ClientOptions. + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, host=self.DEFAULT_ENDPOINT + ) + else: + # We have a non-empty ClientOptions. If client_cert_source is + # provided, trigger mTLS with user provided endpoint or the default + # mTLS endpoint. + if client_options.client_cert_source: + api_mtls_endpoint = ( + client_options.api_endpoint + if client_options.api_endpoint + else self.DEFAULT_MTLS_ENDPOINT + ) + else: + api_mtls_endpoint = None + + api_endpoint = ( + client_options.api_endpoint + if client_options.api_endpoint + else self.DEFAULT_ENDPOINT + ) + + self._transport = TextToSpeechGrpcTransport( + credentials=credentials, + host=api_endpoint, + api_mtls_endpoint=api_mtls_endpoint, + client_cert_source=client_options.client_cert_source, + ) + + def list_voices( + self, + request: cloud_tts.ListVoicesRequest = None, + *, + language_code: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> cloud_tts.ListVoicesResponse: + r"""Returns a list of Voice supported for synthesis. + + Args: + request (:class:`~.cloud_tts.ListVoicesRequest`): + The request object. The top-level message sent by the + client for the `ListVoices` method. + language_code (:class:`str`): + Optional. Recommended. + `BCP-47 `__ + language tag. If specified, the ListVoices call will + only return voices that can be used to synthesize this + language_code. E.g. when specifying "en-NZ", you will + get supported "en-\*" voices; when specifying "no", you + will get supported "no-\*" (Norwegian) and "nb-*" + (Norwegian Bokmal) voices; specifying "zh" will also get + supported "cmn-*" voices; specifying "zh-hk" will also + get supported "yue-\*" voices. + This corresponds to the ``language_code`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.cloud_tts.ListVoicesResponse: + The message returned to the client by the ``ListVoices`` + method. + + """ + # Create or coerce a protobuf request object. + # Sanity check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + if request is not None and any([language_code]): + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + request = cloud_tts.ListVoicesRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + + if language_code is not None: + request.language_code = language_code + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.list_voices, default_timeout=None, client_info=_client_info + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata) + + # Done; return the response. + return response + + def synthesize_speech( + self, + request: cloud_tts.SynthesizeSpeechRequest = None, + *, + input: cloud_tts.SynthesisInput = None, + voice: cloud_tts.VoiceSelectionParams = None, + audio_config: cloud_tts.AudioConfig = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> cloud_tts.SynthesizeSpeechResponse: + r"""Synthesizes speech synchronously: receive results + after all text input has been processed. + + Args: + request (:class:`~.cloud_tts.SynthesizeSpeechRequest`): + The request object. The top-level message sent by the + client for the `SynthesizeSpeech` method. + input (:class:`~.cloud_tts.SynthesisInput`): + Required. The Synthesizer requires + either plain text or SSML as input. + This corresponds to the ``input`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + voice (:class:`~.cloud_tts.VoiceSelectionParams`): + Required. The desired voice of the + synthesized audio. + This corresponds to the ``voice`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + audio_config (:class:`~.cloud_tts.AudioConfig`): + Required. The configuration of the + synthesized audio. + This corresponds to the ``audio_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.cloud_tts.SynthesizeSpeechResponse: + The message returned to the client by the + ``SynthesizeSpeech`` method. + + """ + # Create or coerce a protobuf request object. + # Sanity check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + if request is not None and any([input, voice, audio_config]): + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + request = cloud_tts.SynthesizeSpeechRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + + if input is not None: + request.input = input + if voice is not None: + request.voice = voice + if audio_config is not None: + request.audio_config = audio_config + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.synthesize_speech, + default_timeout=None, + client_info=_client_info, + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata) + + # Done; return the response. + return response + + +try: + _client_info = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-cloud-texttospeech" + ).version + ) +except pkg_resources.DistributionNotFound: + _client_info = gapic_v1.client_info.ClientInfo() + + +__all__ = ("TextToSpeechClient",) diff --git a/google/cloud/texttospeech_v1/services/text_to_speech/transports/__init__.py b/google/cloud/texttospeech_v1/services/text_to_speech/transports/__init__.py new file mode 100644 index 00000000..bd57d801 --- /dev/null +++ b/google/cloud/texttospeech_v1/services/text_to_speech/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- 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. +# + +from collections import OrderedDict +from typing import Dict, Type + +from .base import TextToSpeechTransport +from .grpc import TextToSpeechGrpcTransport + + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[TextToSpeechTransport]] +_transport_registry["grpc"] = TextToSpeechGrpcTransport + + +__all__ = ("TextToSpeechTransport", "TextToSpeechGrpcTransport") diff --git a/google/cloud/texttospeech_v1/services/text_to_speech/transports/base.py b/google/cloud/texttospeech_v1/services/text_to_speech/transports/base.py new file mode 100644 index 00000000..d73ae0bf --- /dev/null +++ b/google/cloud/texttospeech_v1/services/text_to_speech/transports/base.py @@ -0,0 +1,76 @@ +# -*- 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. +# + +import abc +import typing + +from google import auth +from google.auth import credentials # type: ignore + +from google.cloud.texttospeech_v1.types import cloud_tts + + +class TextToSpeechTransport(metaclass=abc.ABCMeta): + """Abstract transport class for TextToSpeech.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + def __init__( + self, + *, + host: str = "texttospeech.googleapis.com", + credentials: credentials.Credentials = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials is None: + credentials, _ = auth.default(scopes=self.AUTH_SCOPES) + + # Save the credentials. + self._credentials = credentials + + @property + def list_voices( + self + ) -> typing.Callable[[cloud_tts.ListVoicesRequest], cloud_tts.ListVoicesResponse]: + raise NotImplementedError + + @property + def synthesize_speech( + self + ) -> typing.Callable[ + [cloud_tts.SynthesizeSpeechRequest], cloud_tts.SynthesizeSpeechResponse + ]: + raise NotImplementedError + + +__all__ = ("TextToSpeechTransport",) diff --git a/google/cloud/texttospeech_v1/services/text_to_speech/transports/grpc.py b/google/cloud/texttospeech_v1/services/text_to_speech/transports/grpc.py new file mode 100644 index 00000000..4f121d0c --- /dev/null +++ b/google/cloud/texttospeech_v1/services/text_to_speech/transports/grpc.py @@ -0,0 +1,212 @@ +# -*- 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. +# + +from typing import Callable, Dict, Tuple + +from google.api_core import grpc_helpers # type: ignore +from google.auth import credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore + + +import grpc # type: ignore + +from google.cloud.texttospeech_v1.types import cloud_tts + +from .base import TextToSpeechTransport + + +class TextToSpeechGrpcTransport(TextToSpeechTransport): + """gRPC backend transport for TextToSpeech. + + Service that implements Google Cloud Text-to-Speech API. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + def __init__( + self, + *, + host: str = "texttospeech.googleapis.com", + credentials: credentials.Credentials = None, + channel: grpc.Channel = None, + api_mtls_endpoint: str = None, + client_cert_source: Callable[[], Tuple[bytes, bytes]] = None + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If + provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or applicatin default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A + callback to provide client SSL certificate bytes and private key + bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` + is None. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + if channel: + # Sanity check: Ensure that channel and credentials are not both + # provided. + credentials = False + + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + elif api_mtls_endpoint: + host = ( + api_mtls_endpoint + if ":" in api_mtls_endpoint + else api_mtls_endpoint + ":443" + ) + + # 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 + + # create a new channel. The provided one is ignored. + self._grpc_channel = grpc_helpers.create_channel( + host, + credentials=credentials, + ssl_credentials=ssl_credentials, + scopes=self.AUTH_SCOPES, + ) + + # Run the base constructor. + super().__init__(host=host, credentials=credentials) + self._stubs = {} # type: Dict[str, Callable] + + @classmethod + def create_channel( + cls, + host: str = "texttospeech.googleapis.com", + credentials: credentials.Credentials = None, + **kwargs + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + address (Optionsl[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + """ + return grpc_helpers.create_channel( + host, credentials=credentials, scopes=cls.AUTH_SCOPES, **kwargs + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Sanity check: Only create a new channel if we do not already + # have one. + if not hasattr(self, "_grpc_channel"): + self._grpc_channel = self.create_channel( + self._host, credentials=self._credentials + ) + + # Return the channel from cache. + return self._grpc_channel + + @property + def list_voices( + self + ) -> Callable[[cloud_tts.ListVoicesRequest], cloud_tts.ListVoicesResponse]: + r"""Return a callable for the list voices method over gRPC. + + Returns a list of Voice supported for synthesis. + + Returns: + Callable[[~.ListVoicesRequest], + ~.ListVoicesResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_voices" not in self._stubs: + self._stubs["list_voices"] = self.grpc_channel.unary_unary( + "/google.cloud.texttospeech.v1.TextToSpeech/ListVoices", + request_serializer=cloud_tts.ListVoicesRequest.serialize, + response_deserializer=cloud_tts.ListVoicesResponse.deserialize, + ) + return self._stubs["list_voices"] + + @property + def synthesize_speech( + self + ) -> Callable[ + [cloud_tts.SynthesizeSpeechRequest], cloud_tts.SynthesizeSpeechResponse + ]: + r"""Return a callable for the synthesize speech method over gRPC. + + Synthesizes speech synchronously: receive results + after all text input has been processed. + + Returns: + Callable[[~.SynthesizeSpeechRequest], + ~.SynthesizeSpeechResponse]: + 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 "synthesize_speech" not in self._stubs: + self._stubs["synthesize_speech"] = self.grpc_channel.unary_unary( + "/google.cloud.texttospeech.v1.TextToSpeech/SynthesizeSpeech", + request_serializer=cloud_tts.SynthesizeSpeechRequest.serialize, + response_deserializer=cloud_tts.SynthesizeSpeechResponse.deserialize, + ) + return self._stubs["synthesize_speech"] + + +__all__ = ("TextToSpeechGrpcTransport",) diff --git a/google/cloud/texttospeech_v1/types.py b/google/cloud/texttospeech_v1/types.py deleted file mode 100644 index 62a01d4c..00000000 --- a/google/cloud/texttospeech_v1/types.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- 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. - - -from __future__ import absolute_import -import sys - -from google.api_core.protobuf_helpers import get_messages - -from google.cloud.texttospeech_v1.proto import cloud_tts_pb2 - - -_shared_modules = [] - -_local_modules = [cloud_tts_pb2] - -names = [] - -for module in _shared_modules: # pragma: NO COVER - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.texttospeech_v1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/google/cloud/texttospeech_v1/types/__init__.py b/google/cloud/texttospeech_v1/types/__init__.py new file mode 100644 index 00000000..47b20ad9 --- /dev/null +++ b/google/cloud/texttospeech_v1/types/__init__.py @@ -0,0 +1,39 @@ +# -*- 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. +# + +from .cloud_tts import ( + ListVoicesRequest, + ListVoicesResponse, + Voice, + SynthesizeSpeechRequest, + SynthesisInput, + VoiceSelectionParams, + AudioConfig, + SynthesizeSpeechResponse, +) + + +__all__ = ( + "ListVoicesRequest", + "ListVoicesResponse", + "Voice", + "SynthesizeSpeechRequest", + "SynthesisInput", + "VoiceSelectionParams", + "AudioConfig", + "SynthesizeSpeechResponse", +) diff --git a/google/cloud/texttospeech_v1/types/cloud_tts.py b/google/cloud/texttospeech_v1/types/cloud_tts.py new file mode 100644 index 00000000..1221344b --- /dev/null +++ b/google/cloud/texttospeech_v1/types/cloud_tts.py @@ -0,0 +1,265 @@ +# -*- 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. +# + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.texttospeech.v1", + manifest={ + "SsmlVoiceGender", + "AudioEncoding", + "ListVoicesRequest", + "ListVoicesResponse", + "Voice", + "SynthesizeSpeechRequest", + "SynthesisInput", + "VoiceSelectionParams", + "AudioConfig", + "SynthesizeSpeechResponse", + }, +) + + +class SsmlVoiceGender(proto.Enum): + r"""Gender of the voice as described in `SSML voice + element `__. + """ + SSML_VOICE_GENDER_UNSPECIFIED = 0 + MALE = 1 + FEMALE = 2 + NEUTRAL = 3 + + +class AudioEncoding(proto.Enum): + r"""Configuration to set up audio encoder. The encoding + determines the output audio format that we'd like. + """ + AUDIO_ENCODING_UNSPECIFIED = 0 + LINEAR16 = 1 + MP3 = 2 + OGG_OPUS = 3 + + +class ListVoicesRequest(proto.Message): + r"""The top-level message sent by the client for the ``ListVoices`` + method. + + Attributes: + language_code (str): + Optional. Recommended. + `BCP-47 `__ + language tag. If specified, the ListVoices call will only + return voices that can be used to synthesize this + language_code. E.g. when specifying "en-NZ", you will get + supported "en-\*" voices; when specifying "no", you will get + supported "no-\*" (Norwegian) and "nb-*" (Norwegian Bokmal) + voices; specifying "zh" will also get supported "cmn-*" + voices; specifying "zh-hk" will also get supported "yue-\*" + voices. + """ + + language_code = proto.Field(proto.STRING, number=1) + + +class ListVoicesResponse(proto.Message): + r"""The message returned to the client by the ``ListVoices`` method. + + Attributes: + voices (Sequence[~.cloud_tts.Voice]): + The list of voices. + """ + + voices = proto.RepeatedField(proto.MESSAGE, number=1, message="Voice") + + +class Voice(proto.Message): + r"""Description of a voice supported by the TTS service. + + Attributes: + language_codes (Sequence[str]): + The languages that this voice supports, expressed as + `BCP-47 `__ + language tags (e.g. "en-US", "es-419", "cmn-tw"). + name (str): + The name of this voice. Each distinct voice + has a unique name. + ssml_gender (~.cloud_tts.SsmlVoiceGender): + The gender of this voice. + natural_sample_rate_hertz (int): + The natural sample rate (in hertz) for this + voice. + """ + + language_codes = proto.RepeatedField(proto.STRING, number=1) + name = proto.Field(proto.STRING, number=2) + ssml_gender = proto.Field(proto.ENUM, number=3, enum="SsmlVoiceGender") + natural_sample_rate_hertz = proto.Field(proto.INT32, number=4) + + +class SynthesizeSpeechRequest(proto.Message): + r"""The top-level message sent by the client for the + ``SynthesizeSpeech`` method. + + Attributes: + input (~.cloud_tts.SynthesisInput): + Required. The Synthesizer requires either + plain text or SSML as input. + voice (~.cloud_tts.VoiceSelectionParams): + Required. The desired voice of the + synthesized audio. + audio_config (~.cloud_tts.AudioConfig): + Required. The configuration of the + synthesized audio. + """ + + input = proto.Field(proto.MESSAGE, number=1, message="SynthesisInput") + voice = proto.Field(proto.MESSAGE, number=2, message="VoiceSelectionParams") + audio_config = proto.Field(proto.MESSAGE, number=3, message="AudioConfig") + + +class SynthesisInput(proto.Message): + r"""Contains text input to be synthesized. Either ``text`` or ``ssml`` + must be supplied. Supplying both or neither returns + [google.rpc.Code.INVALID_ARGUMENT][]. The input size is limited to + 5000 characters. + + Attributes: + text (str): + The raw text to be synthesized. + ssml (str): + The SSML document to be synthesized. The SSML document must + be valid and well-formed. Otherwise the RPC will fail and + return [google.rpc.Code.INVALID_ARGUMENT][]. For more + information, see + `SSML `__. + """ + + text = proto.Field(proto.STRING, number=1) + ssml = proto.Field(proto.STRING, number=2) + + +class VoiceSelectionParams(proto.Message): + r"""Description of which voice to use for a synthesis request. + + Attributes: + language_code (str): + Required. The language (and potentially also the region) of + the voice expressed as a + `BCP-47 `__ + language tag, e.g. "en-US". This should not include a script + tag (e.g. use "cmn-cn" rather than "cmn-Hant-cn"), because + the script will be inferred from the input provided in the + SynthesisInput. The TTS service will use this parameter to + help choose an appropriate voice. Note that the TTS service + may choose a voice with a slightly different language code + than the one selected; it may substitute a different region + (e.g. using en-US rather than en-CA if there isn't a + Canadian voice available), or even a different language, + e.g. using "nb" (Norwegian Bokmal) instead of "no" + (Norwegian)". + name (str): + The name of the voice. If not set, the service will choose a + voice based on the other parameters such as language_code + and gender. + ssml_gender (~.cloud_tts.SsmlVoiceGender): + The preferred gender of the voice. If not set, the service + will choose a voice based on the other parameters such as + language_code and name. Note that this is only a preference, + not requirement; if a voice of the appropriate gender is not + available, the synthesizer should substitute a voice with a + different gender rather than failing the request. + """ + + language_code = proto.Field(proto.STRING, number=1) + name = proto.Field(proto.STRING, number=2) + ssml_gender = proto.Field(proto.ENUM, number=3, enum="SsmlVoiceGender") + + +class AudioConfig(proto.Message): + r"""Description of audio data to be synthesized. + + Attributes: + audio_encoding (~.cloud_tts.AudioEncoding): + Required. The format of the audio byte + stream. + speaking_rate (float): + Optional. Input only. Speaking rate/speed, in the range + [0.25, 4.0]. 1.0 is the normal native speed supported by the + specific voice. 2.0 is twice as fast, and 0.5 is half as + fast. If unset(0.0), defaults to the native 1.0 speed. Any + other values < 0.25 or > 4.0 will return an error. + pitch (float): + Optional. Input only. Speaking pitch, in the range [-20.0, + 20.0]. 20 means increase 20 semitones from the original + pitch. -20 means decrease 20 semitones from the original + pitch. + volume_gain_db (float): + Optional. Input only. Volume gain (in dB) of the normal + native volume supported by the specific voice, in the range + [-96.0, 16.0]. If unset, or set to a value of 0.0 (dB), will + play at normal native signal amplitude. A value of -6.0 (dB) + will play at approximately half the amplitude of the normal + native signal amplitude. A value of +6.0 (dB) will play at + approximately twice the amplitude of the normal native + signal amplitude. Strongly recommend not to exceed +10 (dB) + as there's usually no effective increase in loudness for any + value greater than that. + sample_rate_hertz (int): + Optional. The synthesis sample rate (in hertz) for this + audio. When this is specified in SynthesizeSpeechRequest, if + this is different from the voice's natural sample rate, then + the synthesizer will honor this request by converting to the + desired sample rate (which might result in worse audio + quality), unless the specified sample rate is not supported + for the encoding chosen, in which case it will fail the + request and return [google.rpc.Code.INVALID_ARGUMENT][]. + effects_profile_id (Sequence[str]): + Optional. Input only. An identifier which selects 'audio + effects' profiles that are applied on (post synthesized) + text to speech. Effects are applied on top of each other in + the order they are given. See `audio + profiles `__ + for current supported profile ids. + """ + + audio_encoding = proto.Field(proto.ENUM, number=1, enum="AudioEncoding") + speaking_rate = proto.Field(proto.DOUBLE, number=2) + pitch = proto.Field(proto.DOUBLE, number=3) + volume_gain_db = proto.Field(proto.DOUBLE, number=4) + sample_rate_hertz = proto.Field(proto.INT32, number=5) + effects_profile_id = proto.RepeatedField(proto.STRING, number=6) + + +class SynthesizeSpeechResponse(proto.Message): + r"""The message returned to the client by the ``SynthesizeSpeech`` + method. + + Attributes: + audio_content (bytes): + The audio data bytes encoded as specified in the request, + including the header for encodings that are wrapped in + containers (e.g. MP3, OGG_OPUS). For LINEAR16 audio, we + include the WAV header. Note: as with all bytes fields, + protobuffers use a pure binary representation, whereas JSON + representations use base64. + """ + + audio_content = proto.Field(proto.BYTES, number=1) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/texttospeech_v1beta1/__init__.py b/google/cloud/texttospeech_v1beta1/__init__.py index 7c189d45..b0f218b1 100644 --- a/google/cloud/texttospeech_v1beta1/__init__.py +++ b/google/cloud/texttospeech_v1beta1/__init__.py @@ -1,41 +1,44 @@ # -*- 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 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# -from __future__ import absolute_import -import sys -import warnings - -from google.cloud.texttospeech_v1beta1 import types -from google.cloud.texttospeech_v1beta1.gapic import enums -from google.cloud.texttospeech_v1beta1.gapic import text_to_speech_client - - -if sys.version_info[:2] == (2, 7): - message = ( - "A future version of this library will drop support for Python 2.7." - "More details about Python 2 support for Google Cloud Client Libraries" - "can be found at https://cloud.google.com/python/docs/python2-sunset/" - ) - warnings.warn(message, DeprecationWarning) - - -class TextToSpeechClient(text_to_speech_client.TextToSpeechClient): - __doc__ = text_to_speech_client.TextToSpeechClient.__doc__ - enums = enums - - -__all__ = ("enums", "types", "TextToSpeechClient") +from .services.text_to_speech import TextToSpeechClient +from .types.cloud_tts import AudioConfig +from .types.cloud_tts import AudioEncoding +from .types.cloud_tts import ListVoicesRequest +from .types.cloud_tts import ListVoicesResponse +from .types.cloud_tts import SsmlVoiceGender +from .types.cloud_tts import SynthesisInput +from .types.cloud_tts import SynthesizeSpeechRequest +from .types.cloud_tts import SynthesizeSpeechResponse +from .types.cloud_tts import Voice +from .types.cloud_tts import VoiceSelectionParams + + +__all__ = ( + "AudioConfig", + "AudioEncoding", + "ListVoicesRequest", + "ListVoicesResponse", + "SsmlVoiceGender", + "SynthesisInput", + "SynthesizeSpeechRequest", + "SynthesizeSpeechResponse", + "Voice", + "VoiceSelectionParams", + "TextToSpeechClient", +) diff --git a/google/cloud/texttospeech_v1beta1/gapic/__init__.py b/google/cloud/texttospeech_v1beta1/gapic/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/google/cloud/texttospeech_v1beta1/gapic/enums.py b/google/cloud/texttospeech_v1beta1/gapic/enums.py deleted file mode 100644 index b0bc2782..00000000 --- a/google/cloud/texttospeech_v1beta1/gapic/enums.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- 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. - -"""Wrappers for protocol buffer enum types.""" - -import enum - - -class AudioEncoding(enum.IntEnum): - """ - Configuration to set up audio encoder. The encoding determines the output - audio format that we'd like. - - Attributes: - AUDIO_ENCODING_UNSPECIFIED (int): Not specified. Will return result ``google.rpc.Code.INVALID_ARGUMENT``. - LINEAR16 (int): Uncompressed 16-bit signed little-endian samples (Linear PCM). - Audio content returned as LINEAR16 also contains a WAV header. - MP3 (int): MP3 audio at 32kbps. - OGG_OPUS (int): Opus encoded audio wrapped in an ogg container. The result will be a - file which can be played natively on Android, and in browsers (at least - Chrome and Firefox). The quality of the encoding is considerably higher - than MP3 while using approximately the same bitrate. - """ - - AUDIO_ENCODING_UNSPECIFIED = 0 - LINEAR16 = 1 - MP3 = 2 - OGG_OPUS = 3 - - -class SsmlVoiceGender(enum.IntEnum): - """ - Gender of the voice as described in `SSML voice - element `__. - - Attributes: - SSML_VOICE_GENDER_UNSPECIFIED (int): An unspecified gender. - In VoiceSelectionParams, this means that the client doesn't care which - gender the selected voice will have. In the Voice field of - ListVoicesResponse, this may mean that the voice doesn't fit any of the - other categories in this enum, or that the gender of the voice isn't known. - MALE (int): A male voice. - FEMALE (int): A female voice. - NEUTRAL (int): A gender-neutral voice. - """ - - SSML_VOICE_GENDER_UNSPECIFIED = 0 - MALE = 1 - FEMALE = 2 - NEUTRAL = 3 diff --git a/google/cloud/texttospeech_v1beta1/gapic/text_to_speech_client.py b/google/cloud/texttospeech_v1beta1/gapic/text_to_speech_client.py deleted file mode 100644 index 5ebb7a6c..00000000 --- a/google/cloud/texttospeech_v1beta1/gapic/text_to_speech_client.py +++ /dev/null @@ -1,325 +0,0 @@ -# -*- 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. - -"""Accesses the google.cloud.texttospeech.v1beta1 TextToSpeech API.""" - -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.grpc_helpers -import grpc - -from google.cloud.texttospeech_v1beta1.gapic import enums -from google.cloud.texttospeech_v1beta1.gapic import text_to_speech_client_config -from google.cloud.texttospeech_v1beta1.gapic.transports import ( - text_to_speech_grpc_transport, -) -from google.cloud.texttospeech_v1beta1.proto import cloud_tts_pb2 -from google.cloud.texttospeech_v1beta1.proto import cloud_tts_pb2_grpc - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution( - "google-cloud-texttospeech" -).version - - -class TextToSpeechClient(object): - """Service that implements Google Cloud Text-to-Speech API.""" - - SERVICE_ADDRESS = "texttospeech.googleapis.com:443" - """The default address of the service.""" - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.cloud.texttospeech.v1beta1.TextToSpeech" - - @classmethod - def from_service_account_file(cls, filename, *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: - TextToSpeechClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.TextToSpeechGrpcTransport, - Callable[[~.Credentials, type], ~.TextToSpeechGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = text_to_speech_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=text_to_speech_grpc_transport.TextToSpeechGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = text_to_speech_grpc_transport.TextToSpeechGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def list_voices( - self, - language_code=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Returns a list of Voice supported for synthesis. - - Example: - >>> from google.cloud import texttospeech_v1beta1 - >>> - >>> client = texttospeech_v1beta1.TextToSpeechClient() - >>> - >>> response = client.list_voices() - - Args: - language_code (str): Optional. Recommended. - `BCP-47 `__ language tag. - If specified, the ListVoices call will only return voices that can be - used to synthesize this language\_code. E.g. when specifying "en-NZ", - you will get supported "en-*" voices; when specifying "no", you will get - supported "no-*" (Norwegian) and "nb-*" (Norwegian Bokmal) voices; - specifying "zh" will also get supported "cmn-*" voices; specifying - "zh-hk" will also get supported "yue-\*" voices. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.texttospeech_v1beta1.types.ListVoicesResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_voices" not in self._inner_api_calls: - self._inner_api_calls[ - "list_voices" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_voices, - default_retry=self._method_configs["ListVoices"].retry, - default_timeout=self._method_configs["ListVoices"].timeout, - client_info=self._client_info, - ) - - request = cloud_tts_pb2.ListVoicesRequest(language_code=language_code) - return self._inner_api_calls["list_voices"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def synthesize_speech( - self, - input_, - voice, - audio_config, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Synthesizes speech synchronously: receive results after all text input - has been processed. - - Example: - >>> from google.cloud import texttospeech_v1beta1 - >>> - >>> client = texttospeech_v1beta1.TextToSpeechClient() - >>> - >>> # TODO: Initialize `input_`: - >>> input_ = {} - >>> - >>> # TODO: Initialize `voice`: - >>> voice = {} - >>> - >>> # TODO: Initialize `audio_config`: - >>> audio_config = {} - >>> - >>> response = client.synthesize_speech(input_, voice, audio_config) - - Args: - input_ (Union[dict, ~google.cloud.texttospeech_v1beta1.types.SynthesisInput]): Required. The Synthesizer requires either plain text or SSML as input. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.texttospeech_v1beta1.types.SynthesisInput` - voice (Union[dict, ~google.cloud.texttospeech_v1beta1.types.VoiceSelectionParams]): Required. The desired voice of the synthesized audio. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.texttospeech_v1beta1.types.VoiceSelectionParams` - audio_config (Union[dict, ~google.cloud.texttospeech_v1beta1.types.AudioConfig]): Required. The configuration of the synthesized audio. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.texttospeech_v1beta1.types.AudioConfig` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.texttospeech_v1beta1.types.SynthesizeSpeechResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "synthesize_speech" not in self._inner_api_calls: - self._inner_api_calls[ - "synthesize_speech" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.synthesize_speech, - default_retry=self._method_configs["SynthesizeSpeech"].retry, - default_timeout=self._method_configs["SynthesizeSpeech"].timeout, - client_info=self._client_info, - ) - - request = cloud_tts_pb2.SynthesizeSpeechRequest( - input=input_, voice=voice, audio_config=audio_config - ) - return self._inner_api_calls["synthesize_speech"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) diff --git a/google/cloud/texttospeech_v1beta1/gapic/text_to_speech_client_config.py b/google/cloud/texttospeech_v1beta1/gapic/text_to_speech_client_config.py deleted file mode 100644 index 0463d0e9..00000000 --- a/google/cloud/texttospeech_v1beta1/gapic/text_to_speech_client_config.py +++ /dev/null @@ -1,33 +0,0 @@ -config = { - "interfaces": { - "google.cloud.texttospeech.v1beta1.TextToSpeech": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 20000, - "total_timeout_millis": 600000, - } - }, - "methods": { - "ListVoices": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "SynthesizeSpeech": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/google/cloud/texttospeech_v1beta1/gapic/transports/__init__.py b/google/cloud/texttospeech_v1beta1/gapic/transports/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/google/cloud/texttospeech_v1beta1/gapic/transports/text_to_speech_grpc_transport.py b/google/cloud/texttospeech_v1beta1/gapic/transports/text_to_speech_grpc_transport.py deleted file mode 100644 index 53d10c8b..00000000 --- a/google/cloud/texttospeech_v1beta1/gapic/transports/text_to_speech_grpc_transport.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- 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. - - -import google.api_core.grpc_helpers - -from google.cloud.texttospeech_v1beta1.proto import cloud_tts_pb2_grpc - - -class TextToSpeechGrpcTransport(object): - """gRPC transport class providing stubs for - google.cloud.texttospeech.v1beta1 TextToSpeech API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - - def __init__( - self, channel=None, credentials=None, address="texttospeech.googleapis.com:443" - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = { - "text_to_speech_stub": cloud_tts_pb2_grpc.TextToSpeechStub(channel) - } - - @classmethod - def create_channel( - cls, address="texttospeech.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def list_voices(self): - """Return the gRPC stub for :meth:`TextToSpeechClient.list_voices`. - - Returns a list of Voice supported for synthesis. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["text_to_speech_stub"].ListVoices - - @property - def synthesize_speech(self): - """Return the gRPC stub for :meth:`TextToSpeechClient.synthesize_speech`. - - Synthesizes speech synchronously: receive results after all text input - has been processed. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["text_to_speech_stub"].SynthesizeSpeech diff --git a/google/cloud/texttospeech_v1beta1/proto/__init__.py b/google/cloud/texttospeech_v1beta1/proto/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/google/cloud/texttospeech_v1beta1/proto/cloud_tts.proto b/google/cloud/texttospeech_v1beta1/proto/cloud_tts.proto deleted file mode 100644 index f8189b3f..00000000 --- a/google/cloud/texttospeech_v1beta1/proto/cloud_tts.proto +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2019 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. -// - -syntax = "proto3"; - -package google.cloud.texttospeech.v1beta1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; - -option cc_enable_arenas = true; -option csharp_namespace = "Google.Cloud.TextToSpeech.V1beta1"; -option go_package = "google.golang.org/genproto/googleapis/cloud/texttospeech/v1beta1;texttospeech"; -option java_multiple_files = true; -option java_outer_classname = "TextToSpeechProto"; -option java_package = "com.google.cloud.texttospeech.v1beta1"; -option php_namespace = "Google\\Cloud\\TextToSpeech\\V1beta1"; -option ruby_package = "Google::Cloud::TextToSpeech::V1beta1"; - -// Service that implements Google Cloud Text-to-Speech API. -service TextToSpeech { - option (google.api.default_host) = "texttospeech.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Returns a list of Voice supported for synthesis. - rpc ListVoices(ListVoicesRequest) returns (ListVoicesResponse) { - option (google.api.http) = { - get: "/v1beta1/voices" - }; - option (google.api.method_signature) = "language_code"; - } - - // Synthesizes speech synchronously: receive results after all text input - // has been processed. - rpc SynthesizeSpeech(SynthesizeSpeechRequest) returns (SynthesizeSpeechResponse) { - option (google.api.http) = { - post: "/v1beta1/text:synthesize" - body: "*" - }; - option (google.api.method_signature) = "input,voice,audio_config"; - } -} - -// The top-level message sent by the client for the `ListVoices` method. -message ListVoicesRequest { - // Optional. Recommended. - // [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tag. If - // specified, the ListVoices call will only return voices that can be used to - // synthesize this language_code. E.g. when specifying "en-NZ", you will get - // supported "en-*" voices; when specifying "no", you will get supported - // "no-*" (Norwegian) and "nb-*" (Norwegian Bokmal) voices; specifying "zh" - // will also get supported "cmn-*" voices; specifying "zh-hk" will also get - // supported "yue-*" voices. - string language_code = 1 [(google.api.field_behavior) = OPTIONAL]; -} - -// Gender of the voice as described in -// [SSML voice element](https://www.w3.org/TR/speech-synthesis11/#edef_voice). -enum SsmlVoiceGender { - // An unspecified gender. - // In VoiceSelectionParams, this means that the client doesn't care which - // gender the selected voice will have. In the Voice field of - // ListVoicesResponse, this may mean that the voice doesn't fit any of the - // other categories in this enum, or that the gender of the voice isn't known. - SSML_VOICE_GENDER_UNSPECIFIED = 0; - - // A male voice. - MALE = 1; - - // A female voice. - FEMALE = 2; - - // A gender-neutral voice. - NEUTRAL = 3; -} - -// Configuration to set up audio encoder. The encoding determines the output -// audio format that we'd like. -enum AudioEncoding { - // Not specified. Will return result [google.rpc.Code.INVALID_ARGUMENT][]. - AUDIO_ENCODING_UNSPECIFIED = 0; - - // Uncompressed 16-bit signed little-endian samples (Linear PCM). - // Audio content returned as LINEAR16 also contains a WAV header. - LINEAR16 = 1; - - // MP3 audio at 32kbps. - MP3 = 2; - - // Opus encoded audio wrapped in an ogg container. The result will be a - // file which can be played natively on Android, and in browsers (at least - // Chrome and Firefox). The quality of the encoding is considerably higher - // than MP3 while using approximately the same bitrate. - OGG_OPUS = 3; -} - -// The message returned to the client by the `ListVoices` method. -message ListVoicesResponse { - // The list of voices. - repeated Voice voices = 1; -} - -// Description of a voice supported by the TTS service. -message Voice { - // The languages that this voice supports, expressed as - // [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tags (e.g. - // "en-US", "es-419", "cmn-tw"). - repeated string language_codes = 1; - - // The name of this voice. Each distinct voice has a unique name. - string name = 2; - - // The gender of this voice. - SsmlVoiceGender ssml_gender = 3; - - // The natural sample rate (in hertz) for this voice. - int32 natural_sample_rate_hertz = 4; -} - -// The top-level message sent by the client for the `SynthesizeSpeech` method. -message SynthesizeSpeechRequest { - // Required. The Synthesizer requires either plain text or SSML as input. - SynthesisInput input = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. The desired voice of the synthesized audio. - VoiceSelectionParams voice = 2 [(google.api.field_behavior) = REQUIRED]; - - // Required. The configuration of the synthesized audio. - AudioConfig audio_config = 3 [(google.api.field_behavior) = REQUIRED]; -} - -// Contains text input to be synthesized. Either `text` or `ssml` must be -// supplied. Supplying both or neither returns -// [google.rpc.Code.INVALID_ARGUMENT][]. The input size is limited to 5000 -// characters. -message SynthesisInput { - // The input source, which is either plain text or SSML. - oneof input_source { - // The raw text to be synthesized. - string text = 1; - - // The SSML document to be synthesized. The SSML document must be valid - // and well-formed. Otherwise the RPC will fail and return - // [google.rpc.Code.INVALID_ARGUMENT][]. For more information, see - // [SSML](/speech/text-to-speech/docs/ssml). - string ssml = 2; - } -} - -// Description of which voice to use for a synthesis request. -message VoiceSelectionParams { - // Required. The language (and potentially also the region) of the voice expressed as a - // [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tag, e.g. - // "en-US". This should not include a script tag (e.g. use - // "cmn-cn" rather than "cmn-Hant-cn"), because the script will be inferred - // from the input provided in the SynthesisInput. The TTS service - // will use this parameter to help choose an appropriate voice. Note that - // the TTS service may choose a voice with a slightly different language code - // than the one selected; it may substitute a different region - // (e.g. using en-US rather than en-CA if there isn't a Canadian voice - // available), or even a different language, e.g. using "nb" (Norwegian - // Bokmal) instead of "no" (Norwegian)". - string language_code = 1 [(google.api.field_behavior) = REQUIRED]; - - // The name of the voice. If not set, the service will choose a - // voice based on the other parameters such as language_code and gender. - string name = 2; - - // The preferred gender of the voice. If not set, the service will - // choose a voice based on the other parameters such as language_code and - // name. Note that this is only a preference, not requirement; if a - // voice of the appropriate gender is not available, the synthesizer should - // substitute a voice with a different gender rather than failing the request. - SsmlVoiceGender ssml_gender = 3; -} - -// Description of audio data to be synthesized. -message AudioConfig { - // Required. The format of the audio byte stream. - AudioEncoding audio_encoding = 1 [(google.api.field_behavior) = REQUIRED]; - - // Optional. Input only. Speaking rate/speed, in the range [0.25, 4.0]. 1.0 is - // the normal native speed supported by the specific voice. 2.0 is twice as - // fast, and 0.5 is half as fast. If unset(0.0), defaults to the native 1.0 - // speed. Any other values < 0.25 or > 4.0 will return an error. - double speaking_rate = 2 [ - (google.api.field_behavior) = INPUT_ONLY, - (google.api.field_behavior) = OPTIONAL - ]; - - // Optional. Input only. Speaking pitch, in the range [-20.0, 20.0]. 20 means - // increase 20 semitones from the original pitch. -20 means decrease 20 - // semitones from the original pitch. - double pitch = 3 [ - (google.api.field_behavior) = INPUT_ONLY, - (google.api.field_behavior) = OPTIONAL - ]; - - // Optional. Input only. Volume gain (in dB) of the normal native volume - // supported by the specific voice, in the range [-96.0, 16.0]. If unset, or - // set to a value of 0.0 (dB), will play at normal native signal amplitude. A - // value of -6.0 (dB) will play at approximately half the amplitude of the - // normal native signal amplitude. A value of +6.0 (dB) will play at - // approximately twice the amplitude of the normal native signal amplitude. - // Strongly recommend not to exceed +10 (dB) as there's usually no effective - // increase in loudness for any value greater than that. - double volume_gain_db = 4 [ - (google.api.field_behavior) = INPUT_ONLY, - (google.api.field_behavior) = OPTIONAL - ]; - - // Optional. The synthesis sample rate (in hertz) for this audio. When this is - // specified in SynthesizeSpeechRequest, if this is different from the voice's - // natural sample rate, then the synthesizer will honor this request by - // converting to the desired sample rate (which might result in worse audio - // quality), unless the specified sample rate is not supported for the - // encoding chosen, in which case it will fail the request and return - // [google.rpc.Code.INVALID_ARGUMENT][]. - int32 sample_rate_hertz = 5 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. Input only. An identifier which selects 'audio effects' profiles - // that are applied on (post synthesized) text to speech. Effects are applied - // on top of each other in the order they are given. See - // [audio - // profiles](https://cloud.google.com/text-to-speech/docs/audio-profiles) for - // current supported profile ids. - repeated string effects_profile_id = 6 [ - (google.api.field_behavior) = INPUT_ONLY, - (google.api.field_behavior) = OPTIONAL - ]; -} - -// The message returned to the client by the `SynthesizeSpeech` method. -message SynthesizeSpeechResponse { - // The audio data bytes encoded as specified in the request, including the - // header for encodings that are wrapped in containers (e.g. MP3, OGG_OPUS). - // For LINEAR16 audio, we include the WAV header. Note: as - // with all bytes fields, protobuffers use a pure binary representation, - // whereas JSON representations use base64. - bytes audio_content = 1; -} diff --git a/google/cloud/texttospeech_v1beta1/proto/cloud_tts_pb2.py b/google/cloud/texttospeech_v1beta1/proto/cloud_tts_pb2.py deleted file mode 100644 index aa98ca9b..00000000 --- a/google/cloud/texttospeech_v1beta1/proto/cloud_tts_pb2.py +++ /dev/null @@ -1,976 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/texttospeech_v1beta1/proto/cloud_tts.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf.internal import enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/texttospeech_v1beta1/proto/cloud_tts.proto", - package="google.cloud.texttospeech.v1beta1", - syntax="proto3", - serialized_options=_b( - "\n%com.google.cloud.texttospeech.v1beta1B\021TextToSpeechProtoP\001ZMgoogle.golang.org/genproto/googleapis/cloud/texttospeech/v1beta1;texttospeech\370\001\001\252\002!Google.Cloud.TextToSpeech.V1beta1\312\002!Google\\Cloud\\TextToSpeech\\V1beta1\352\002$Google::Cloud::TextToSpeech::V1beta1" - ), - serialized_pb=_b( - '\n7google/cloud/texttospeech_v1beta1/proto/cloud_tts.proto\x12!google.cloud.texttospeech.v1beta1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto"/\n\x11ListVoicesRequest\x12\x1a\n\rlanguage_code\x18\x01 \x01(\tB\x03\xe0\x41\x01"N\n\x12ListVoicesResponse\x12\x38\n\x06voices\x18\x01 \x03(\x0b\x32(.google.cloud.texttospeech.v1beta1.Voice"\x99\x01\n\x05Voice\x12\x16\n\x0elanguage_codes\x18\x01 \x03(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12G\n\x0bssml_gender\x18\x03 \x01(\x0e\x32\x32.google.cloud.texttospeech.v1beta1.SsmlVoiceGender\x12!\n\x19natural_sample_rate_hertz\x18\x04 \x01(\x05"\xf8\x01\n\x17SynthesizeSpeechRequest\x12\x45\n\x05input\x18\x01 \x01(\x0b\x32\x31.google.cloud.texttospeech.v1beta1.SynthesisInputB\x03\xe0\x41\x02\x12K\n\x05voice\x18\x02 \x01(\x0b\x32\x37.google.cloud.texttospeech.v1beta1.VoiceSelectionParamsB\x03\xe0\x41\x02\x12I\n\x0c\x61udio_config\x18\x03 \x01(\x0b\x32..google.cloud.texttospeech.v1beta1.AudioConfigB\x03\xe0\x41\x02"@\n\x0eSynthesisInput\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12\x0e\n\x04ssml\x18\x02 \x01(\tH\x00\x42\x0e\n\x0cinput_source"\x89\x01\n\x14VoiceSelectionParams\x12\x1a\n\rlanguage_code\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x0c\n\x04name\x18\x02 \x01(\t\x12G\n\x0bssml_gender\x18\x03 \x01(\x0e\x32\x32.google.cloud.texttospeech.v1beta1.SsmlVoiceGender"\xf6\x01\n\x0b\x41udioConfig\x12M\n\x0e\x61udio_encoding\x18\x01 \x01(\x0e\x32\x30.google.cloud.texttospeech.v1beta1.AudioEncodingB\x03\xe0\x41\x02\x12\x1d\n\rspeaking_rate\x18\x02 \x01(\x01\x42\x06\xe0\x41\x04\xe0\x41\x01\x12\x15\n\x05pitch\x18\x03 \x01(\x01\x42\x06\xe0\x41\x04\xe0\x41\x01\x12\x1e\n\x0evolume_gain_db\x18\x04 \x01(\x01\x42\x06\xe0\x41\x04\xe0\x41\x01\x12\x1e\n\x11sample_rate_hertz\x18\x05 \x01(\x05\x42\x03\xe0\x41\x01\x12"\n\x12\x65\x66\x66\x65\x63ts_profile_id\x18\x06 \x03(\tB\x06\xe0\x41\x04\xe0\x41\x01"1\n\x18SynthesizeSpeechResponse\x12\x15\n\raudio_content\x18\x01 \x01(\x0c*W\n\x0fSsmlVoiceGender\x12!\n\x1dSSML_VOICE_GENDER_UNSPECIFIED\x10\x00\x12\x08\n\x04MALE\x10\x01\x12\n\n\x06\x46\x45MALE\x10\x02\x12\x0b\n\x07NEUTRAL\x10\x03*T\n\rAudioEncoding\x12\x1e\n\x1a\x41UDIO_ENCODING_UNSPECIFIED\x10\x00\x12\x0c\n\x08LINEAR16\x10\x01\x12\x07\n\x03MP3\x10\x02\x12\x0c\n\x08OGG_OPUS\x10\x03\x32\xd2\x03\n\x0cTextToSpeech\x12\xa2\x01\n\nListVoices\x12\x34.google.cloud.texttospeech.v1beta1.ListVoicesRequest\x1a\x35.google.cloud.texttospeech.v1beta1.ListVoicesResponse"\'\x82\xd3\xe4\x93\x02\x11\x12\x0f/v1beta1/voices\xda\x41\rlanguage_code\x12\xcb\x01\n\x10SynthesizeSpeech\x12:.google.cloud.texttospeech.v1beta1.SynthesizeSpeechRequest\x1a;.google.cloud.texttospeech.v1beta1.SynthesizeSpeechResponse">\x82\xd3\xe4\x93\x02\x1d"\x18/v1beta1/text:synthesize:\x01*\xda\x41\x18input,voice,audio_config\x1aO\xca\x41\x1btexttospeech.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformB\xfd\x01\n%com.google.cloud.texttospeech.v1beta1B\x11TextToSpeechProtoP\x01ZMgoogle.golang.org/genproto/googleapis/cloud/texttospeech/v1beta1;texttospeech\xf8\x01\x01\xaa\x02!Google.Cloud.TextToSpeech.V1beta1\xca\x02!Google\\Cloud\\TextToSpeech\\V1beta1\xea\x02$Google::Cloud::TextToSpeech::V1beta1b\x06proto3' - ), - dependencies=[ - google_dot_api_dot_annotations__pb2.DESCRIPTOR, - google_dot_api_dot_client__pb2.DESCRIPTOR, - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - ], -) - -_SSMLVOICEGENDER = _descriptor.EnumDescriptor( - name="SsmlVoiceGender", - full_name="google.cloud.texttospeech.v1beta1.SsmlVoiceGender", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="SSML_VOICE_GENDER_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="MALE", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="FEMALE", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="NEUTRAL", index=3, number=3, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1224, - serialized_end=1311, -) -_sym_db.RegisterEnumDescriptor(_SSMLVOICEGENDER) - -SsmlVoiceGender = enum_type_wrapper.EnumTypeWrapper(_SSMLVOICEGENDER) -_AUDIOENCODING = _descriptor.EnumDescriptor( - name="AudioEncoding", - full_name="google.cloud.texttospeech.v1beta1.AudioEncoding", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="AUDIO_ENCODING_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="LINEAR16", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="MP3", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="OGG_OPUS", index=3, number=3, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1313, - serialized_end=1397, -) -_sym_db.RegisterEnumDescriptor(_AUDIOENCODING) - -AudioEncoding = enum_type_wrapper.EnumTypeWrapper(_AUDIOENCODING) -SSML_VOICE_GENDER_UNSPECIFIED = 0 -MALE = 1 -FEMALE = 2 -NEUTRAL = 3 -AUDIO_ENCODING_UNSPECIFIED = 0 -LINEAR16 = 1 -MP3 = 2 -OGG_OPUS = 3 - - -_LISTVOICESREQUEST = _descriptor.Descriptor( - name="ListVoicesRequest", - full_name="google.cloud.texttospeech.v1beta1.ListVoicesRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="language_code", - full_name="google.cloud.texttospeech.v1beta1.ListVoicesRequest.language_code", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=182, - serialized_end=229, -) - - -_LISTVOICESRESPONSE = _descriptor.Descriptor( - name="ListVoicesResponse", - full_name="google.cloud.texttospeech.v1beta1.ListVoicesResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="voices", - full_name="google.cloud.texttospeech.v1beta1.ListVoicesResponse.voices", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=231, - serialized_end=309, -) - - -_VOICE = _descriptor.Descriptor( - name="Voice", - full_name="google.cloud.texttospeech.v1beta1.Voice", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="language_codes", - full_name="google.cloud.texttospeech.v1beta1.Voice.language_codes", - index=0, - number=1, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.texttospeech.v1beta1.Voice.name", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ssml_gender", - full_name="google.cloud.texttospeech.v1beta1.Voice.ssml_gender", - index=2, - number=3, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="natural_sample_rate_hertz", - full_name="google.cloud.texttospeech.v1beta1.Voice.natural_sample_rate_hertz", - index=3, - number=4, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=312, - serialized_end=465, -) - - -_SYNTHESIZESPEECHREQUEST = _descriptor.Descriptor( - name="SynthesizeSpeechRequest", - full_name="google.cloud.texttospeech.v1beta1.SynthesizeSpeechRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="input", - full_name="google.cloud.texttospeech.v1beta1.SynthesizeSpeechRequest.input", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="voice", - full_name="google.cloud.texttospeech.v1beta1.SynthesizeSpeechRequest.voice", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="audio_config", - full_name="google.cloud.texttospeech.v1beta1.SynthesizeSpeechRequest.audio_config", - index=2, - number=3, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=468, - serialized_end=716, -) - - -_SYNTHESISINPUT = _descriptor.Descriptor( - name="SynthesisInput", - full_name="google.cloud.texttospeech.v1beta1.SynthesisInput", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="text", - full_name="google.cloud.texttospeech.v1beta1.SynthesisInput.text", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ssml", - full_name="google.cloud.texttospeech.v1beta1.SynthesisInput.ssml", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name="input_source", - full_name="google.cloud.texttospeech.v1beta1.SynthesisInput.input_source", - index=0, - containing_type=None, - fields=[], - ) - ], - serialized_start=718, - serialized_end=782, -) - - -_VOICESELECTIONPARAMS = _descriptor.Descriptor( - name="VoiceSelectionParams", - full_name="google.cloud.texttospeech.v1beta1.VoiceSelectionParams", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="language_code", - full_name="google.cloud.texttospeech.v1beta1.VoiceSelectionParams.language_code", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.texttospeech.v1beta1.VoiceSelectionParams.name", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ssml_gender", - full_name="google.cloud.texttospeech.v1beta1.VoiceSelectionParams.ssml_gender", - index=2, - number=3, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=785, - serialized_end=922, -) - - -_AUDIOCONFIG = _descriptor.Descriptor( - name="AudioConfig", - full_name="google.cloud.texttospeech.v1beta1.AudioConfig", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="audio_encoding", - full_name="google.cloud.texttospeech.v1beta1.AudioConfig.audio_encoding", - index=0, - number=1, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="speaking_rate", - full_name="google.cloud.texttospeech.v1beta1.AudioConfig.speaking_rate", - index=1, - number=2, - type=1, - cpp_type=5, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\004\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="pitch", - full_name="google.cloud.texttospeech.v1beta1.AudioConfig.pitch", - index=2, - number=3, - type=1, - cpp_type=5, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\004\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="volume_gain_db", - full_name="google.cloud.texttospeech.v1beta1.AudioConfig.volume_gain_db", - index=3, - number=4, - type=1, - cpp_type=5, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\004\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="sample_rate_hertz", - full_name="google.cloud.texttospeech.v1beta1.AudioConfig.sample_rate_hertz", - index=4, - number=5, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="effects_profile_id", - full_name="google.cloud.texttospeech.v1beta1.AudioConfig.effects_profile_id", - index=5, - number=6, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\004\340A\001"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=925, - serialized_end=1171, -) - - -_SYNTHESIZESPEECHRESPONSE = _descriptor.Descriptor( - name="SynthesizeSpeechResponse", - full_name="google.cloud.texttospeech.v1beta1.SynthesizeSpeechResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="audio_content", - full_name="google.cloud.texttospeech.v1beta1.SynthesizeSpeechResponse.audio_content", - index=0, - number=1, - type=12, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b(""), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1173, - serialized_end=1222, -) - -_LISTVOICESRESPONSE.fields_by_name["voices"].message_type = _VOICE -_VOICE.fields_by_name["ssml_gender"].enum_type = _SSMLVOICEGENDER -_SYNTHESIZESPEECHREQUEST.fields_by_name["input"].message_type = _SYNTHESISINPUT -_SYNTHESIZESPEECHREQUEST.fields_by_name["voice"].message_type = _VOICESELECTIONPARAMS -_SYNTHESIZESPEECHREQUEST.fields_by_name["audio_config"].message_type = _AUDIOCONFIG -_SYNTHESISINPUT.oneofs_by_name["input_source"].fields.append( - _SYNTHESISINPUT.fields_by_name["text"] -) -_SYNTHESISINPUT.fields_by_name[ - "text" -].containing_oneof = _SYNTHESISINPUT.oneofs_by_name["input_source"] -_SYNTHESISINPUT.oneofs_by_name["input_source"].fields.append( - _SYNTHESISINPUT.fields_by_name["ssml"] -) -_SYNTHESISINPUT.fields_by_name[ - "ssml" -].containing_oneof = _SYNTHESISINPUT.oneofs_by_name["input_source"] -_VOICESELECTIONPARAMS.fields_by_name["ssml_gender"].enum_type = _SSMLVOICEGENDER -_AUDIOCONFIG.fields_by_name["audio_encoding"].enum_type = _AUDIOENCODING -DESCRIPTOR.message_types_by_name["ListVoicesRequest"] = _LISTVOICESREQUEST -DESCRIPTOR.message_types_by_name["ListVoicesResponse"] = _LISTVOICESRESPONSE -DESCRIPTOR.message_types_by_name["Voice"] = _VOICE -DESCRIPTOR.message_types_by_name["SynthesizeSpeechRequest"] = _SYNTHESIZESPEECHREQUEST -DESCRIPTOR.message_types_by_name["SynthesisInput"] = _SYNTHESISINPUT -DESCRIPTOR.message_types_by_name["VoiceSelectionParams"] = _VOICESELECTIONPARAMS -DESCRIPTOR.message_types_by_name["AudioConfig"] = _AUDIOCONFIG -DESCRIPTOR.message_types_by_name["SynthesizeSpeechResponse"] = _SYNTHESIZESPEECHRESPONSE -DESCRIPTOR.enum_types_by_name["SsmlVoiceGender"] = _SSMLVOICEGENDER -DESCRIPTOR.enum_types_by_name["AudioEncoding"] = _AUDIOENCODING -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -ListVoicesRequest = _reflection.GeneratedProtocolMessageType( - "ListVoicesRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTVOICESREQUEST, - __module__="google.cloud.texttospeech_v1beta1.proto.cloud_tts_pb2", - __doc__="""The top-level message sent by the client for the ``ListVoices`` - method. - Attributes: - language_code: - Optional. Recommended. `BCP-47 `__ language tag. If specified, - the ListVoices call will only return voices that can be used - to synthesize this language\_code. E.g. when specifying "en- - NZ", you will get supported "en-*" voices; when specifying - "no", you will get supported "no-*" (Norwegian) and "nb-*" - (Norwegian Bokmal) voices; specifying "zh" will also get - supported "cmn-*" voices; specifying "zh-hk" will also get - supported "yue-\*" voices. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1beta1.ListVoicesRequest) - ), -) -_sym_db.RegisterMessage(ListVoicesRequest) - -ListVoicesResponse = _reflection.GeneratedProtocolMessageType( - "ListVoicesResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTVOICESRESPONSE, - __module__="google.cloud.texttospeech_v1beta1.proto.cloud_tts_pb2", - __doc__="""The message returned to the client by the ``ListVoices`` method. - Attributes: - voices: - The list of voices. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1beta1.ListVoicesResponse) - ), -) -_sym_db.RegisterMessage(ListVoicesResponse) - -Voice = _reflection.GeneratedProtocolMessageType( - "Voice", - (_message.Message,), - dict( - DESCRIPTOR=_VOICE, - __module__="google.cloud.texttospeech_v1beta1.proto.cloud_tts_pb2", - __doc__="""Description of a voice supported by the TTS service. - Attributes: - language_codes: - The languages that this voice supports, expressed as `BCP-47 - `__ language - tags (e.g. "en-US", "es-419", "cmn-tw"). - name: - The name of this voice. Each distinct voice has a unique name. - ssml_gender: - The gender of this voice. - natural_sample_rate_hertz: - The natural sample rate (in hertz) for this voice. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1beta1.Voice) - ), -) -_sym_db.RegisterMessage(Voice) - -SynthesizeSpeechRequest = _reflection.GeneratedProtocolMessageType( - "SynthesizeSpeechRequest", - (_message.Message,), - dict( - DESCRIPTOR=_SYNTHESIZESPEECHREQUEST, - __module__="google.cloud.texttospeech_v1beta1.proto.cloud_tts_pb2", - __doc__="""The top-level message sent by the client for the ``SynthesizeSpeech`` - method. - Attributes: - input: - Required. The Synthesizer requires either plain text or SSML - as input. - voice: - Required. The desired voice of the synthesized audio. - audio_config: - Required. The configuration of the synthesized audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1beta1.SynthesizeSpeechRequest) - ), -) -_sym_db.RegisterMessage(SynthesizeSpeechRequest) - -SynthesisInput = _reflection.GeneratedProtocolMessageType( - "SynthesisInput", - (_message.Message,), - dict( - DESCRIPTOR=_SYNTHESISINPUT, - __module__="google.cloud.texttospeech_v1beta1.proto.cloud_tts_pb2", - __doc__="""Contains text input to be synthesized. Either ``text`` or ``ssml`` - must be supplied. Supplying both or neither returns - [google.rpc.Code.INVALID\_ARGUMENT][]. The input size is limited to - 5000 characters. - Attributes: - input_source: - The input source, which is either plain text or SSML. - text: - The raw text to be synthesized. - ssml: - The SSML document to be synthesized. The SSML document must be - valid and well-formed. Otherwise the RPC will fail and return - [google.rpc.Code.INVALID\_ARGUMENT][]. For more information, - see `SSML `__. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1beta1.SynthesisInput) - ), -) -_sym_db.RegisterMessage(SynthesisInput) - -VoiceSelectionParams = _reflection.GeneratedProtocolMessageType( - "VoiceSelectionParams", - (_message.Message,), - dict( - DESCRIPTOR=_VOICESELECTIONPARAMS, - __module__="google.cloud.texttospeech_v1beta1.proto.cloud_tts_pb2", - __doc__="""Description of which voice to use for a synthesis request. - Attributes: - language_code: - Required. The language (and potentially also the region) of - the voice expressed as a `BCP-47 `__ language tag, e.g. "en-US". - This should not include a script tag (e.g. use "cmn-cn" rather - than "cmn-Hant-cn"), because the script will be inferred from - the input provided in the SynthesisInput. The TTS service will - use this parameter to help choose an appropriate voice. Note - that the TTS service may choose a voice with a slightly - different language code than the one selected; it may - substitute a different region (e.g. using en-US rather than - en-CA if there isn't a Canadian voice available), or even a - different language, e.g. using "nb" (Norwegian Bokmal) instead - of "no" (Norwegian)". - name: - The name of the voice. If not set, the service will choose a - voice based on the other parameters such as language\_code and - gender. - ssml_gender: - The preferred gender of the voice. If not set, the service - will choose a voice based on the other parameters such as - language\_code and name. Note that this is only a preference, - not requirement; if a voice of the appropriate gender is not - available, the synthesizer should substitute a voice with a - different gender rather than failing the request. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1beta1.VoiceSelectionParams) - ), -) -_sym_db.RegisterMessage(VoiceSelectionParams) - -AudioConfig = _reflection.GeneratedProtocolMessageType( - "AudioConfig", - (_message.Message,), - dict( - DESCRIPTOR=_AUDIOCONFIG, - __module__="google.cloud.texttospeech_v1beta1.proto.cloud_tts_pb2", - __doc__="""Description of audio data to be synthesized. - Attributes: - audio_encoding: - Required. The format of the audio byte stream. - speaking_rate: - Optional. Input only. Speaking rate/speed, in the range [0.25, - 4.0]. 1.0 is the normal native speed supported by the specific - voice. 2.0 is twice as fast, and 0.5 is half as fast. If - unset(0.0), defaults to the native 1.0 speed. Any other values - < 0.25 or > 4.0 will return an error. - pitch: - Optional. Input only. Speaking pitch, in the range [-20.0, - 20.0]. 20 means increase 20 semitones from the original pitch. - -20 means decrease 20 semitones from the original pitch. - volume_gain_db: - Optional. Input only. Volume gain (in dB) of the normal native - volume supported by the specific voice, in the range [-96.0, - 16.0]. If unset, or set to a value of 0.0 (dB), will play at - normal native signal amplitude. A value of -6.0 (dB) will play - at approximately half the amplitude of the normal native - signal amplitude. A value of +6.0 (dB) will play at - approximately twice the amplitude of the normal native signal - amplitude. Strongly recommend not to exceed +10 (dB) as - there's usually no effective increase in loudness for any - value greater than that. - sample_rate_hertz: - Optional. The synthesis sample rate (in hertz) for this audio. - When this is specified in SynthesizeSpeechRequest, if this is - different from the voice's natural sample rate, then the - synthesizer will honor this request by converting to the - desired sample rate (which might result in worse audio - quality), unless the specified sample rate is not supported - for the encoding chosen, in which case it will fail the - request and return [google.rpc.Code.INVALID\_ARGUMENT][]. - effects_profile_id: - Optional. Input only. An identifier which selects 'audio - effects' profiles that are applied on (post synthesized) text - to speech. Effects are applied on top of each other in the - order they are given. See `audio profiles - `__ for current supported profile ids. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1beta1.AudioConfig) - ), -) -_sym_db.RegisterMessage(AudioConfig) - -SynthesizeSpeechResponse = _reflection.GeneratedProtocolMessageType( - "SynthesizeSpeechResponse", - (_message.Message,), - dict( - DESCRIPTOR=_SYNTHESIZESPEECHRESPONSE, - __module__="google.cloud.texttospeech_v1beta1.proto.cloud_tts_pb2", - __doc__="""The message returned to the client by the ``SynthesizeSpeech`` method. - Attributes: - audio_content: - The audio data bytes encoded as specified in the request, - including the header for encodings that are wrapped in - containers (e.g. MP3, OGG\_OPUS). For LINEAR16 audio, we - include the WAV header. Note: as with all bytes fields, - protobuffers use a pure binary representation, whereas JSON - representations use base64. - """, - # @@protoc_insertion_point(class_scope:google.cloud.texttospeech.v1beta1.SynthesizeSpeechResponse) - ), -) -_sym_db.RegisterMessage(SynthesizeSpeechResponse) - - -DESCRIPTOR._options = None -_LISTVOICESREQUEST.fields_by_name["language_code"]._options = None -_SYNTHESIZESPEECHREQUEST.fields_by_name["input"]._options = None -_SYNTHESIZESPEECHREQUEST.fields_by_name["voice"]._options = None -_SYNTHESIZESPEECHREQUEST.fields_by_name["audio_config"]._options = None -_VOICESELECTIONPARAMS.fields_by_name["language_code"]._options = None -_AUDIOCONFIG.fields_by_name["audio_encoding"]._options = None -_AUDIOCONFIG.fields_by_name["speaking_rate"]._options = None -_AUDIOCONFIG.fields_by_name["pitch"]._options = None -_AUDIOCONFIG.fields_by_name["volume_gain_db"]._options = None -_AUDIOCONFIG.fields_by_name["sample_rate_hertz"]._options = None -_AUDIOCONFIG.fields_by_name["effects_profile_id"]._options = None - -_TEXTTOSPEECH = _descriptor.ServiceDescriptor( - name="TextToSpeech", - full_name="google.cloud.texttospeech.v1beta1.TextToSpeech", - file=DESCRIPTOR, - index=0, - serialized_options=_b( - "\312A\033texttospeech.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform" - ), - serialized_start=1400, - serialized_end=1866, - methods=[ - _descriptor.MethodDescriptor( - name="ListVoices", - full_name="google.cloud.texttospeech.v1beta1.TextToSpeech.ListVoices", - index=0, - containing_service=None, - input_type=_LISTVOICESREQUEST, - output_type=_LISTVOICESRESPONSE, - serialized_options=_b( - "\202\323\344\223\002\021\022\017/v1beta1/voices\332A\rlanguage_code" - ), - ), - _descriptor.MethodDescriptor( - name="SynthesizeSpeech", - full_name="google.cloud.texttospeech.v1beta1.TextToSpeech.SynthesizeSpeech", - index=1, - containing_service=None, - input_type=_SYNTHESIZESPEECHREQUEST, - output_type=_SYNTHESIZESPEECHRESPONSE, - serialized_options=_b( - '\202\323\344\223\002\035"\030/v1beta1/text:synthesize:\001*\332A\030input,voice,audio_config' - ), - ), - ], -) -_sym_db.RegisterServiceDescriptor(_TEXTTOSPEECH) - -DESCRIPTOR.services_by_name["TextToSpeech"] = _TEXTTOSPEECH - -# @@protoc_insertion_point(module_scope) diff --git a/google/cloud/texttospeech_v1beta1/proto/cloud_tts_pb2_grpc.py b/google/cloud/texttospeech_v1beta1/proto/cloud_tts_pb2_grpc.py deleted file mode 100644 index a469e83d..00000000 --- a/google/cloud/texttospeech_v1beta1/proto/cloud_tts_pb2_grpc.py +++ /dev/null @@ -1,67 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.texttospeech_v1beta1.proto import ( - cloud_tts_pb2 as google_dot_cloud_dot_texttospeech__v1beta1_dot_proto_dot_cloud__tts__pb2, -) - - -class TextToSpeechStub(object): - """Service that implements Google Cloud Text-to-Speech API. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.ListVoices = channel.unary_unary( - "/google.cloud.texttospeech.v1beta1.TextToSpeech/ListVoices", - request_serializer=google_dot_cloud_dot_texttospeech__v1beta1_dot_proto_dot_cloud__tts__pb2.ListVoicesRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_texttospeech__v1beta1_dot_proto_dot_cloud__tts__pb2.ListVoicesResponse.FromString, - ) - self.SynthesizeSpeech = channel.unary_unary( - "/google.cloud.texttospeech.v1beta1.TextToSpeech/SynthesizeSpeech", - request_serializer=google_dot_cloud_dot_texttospeech__v1beta1_dot_proto_dot_cloud__tts__pb2.SynthesizeSpeechRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_texttospeech__v1beta1_dot_proto_dot_cloud__tts__pb2.SynthesizeSpeechResponse.FromString, - ) - - -class TextToSpeechServicer(object): - """Service that implements Google Cloud Text-to-Speech API. - """ - - def ListVoices(self, request, context): - """Returns a list of Voice supported for synthesis. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def SynthesizeSpeech(self, request, context): - """Synthesizes speech synchronously: receive results after all text input - has been processed. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_TextToSpeechServicer_to_server(servicer, server): - rpc_method_handlers = { - "ListVoices": grpc.unary_unary_rpc_method_handler( - servicer.ListVoices, - request_deserializer=google_dot_cloud_dot_texttospeech__v1beta1_dot_proto_dot_cloud__tts__pb2.ListVoicesRequest.FromString, - response_serializer=google_dot_cloud_dot_texttospeech__v1beta1_dot_proto_dot_cloud__tts__pb2.ListVoicesResponse.SerializeToString, - ), - "SynthesizeSpeech": grpc.unary_unary_rpc_method_handler( - servicer.SynthesizeSpeech, - request_deserializer=google_dot_cloud_dot_texttospeech__v1beta1_dot_proto_dot_cloud__tts__pb2.SynthesizeSpeechRequest.FromString, - response_serializer=google_dot_cloud_dot_texttospeech__v1beta1_dot_proto_dot_cloud__tts__pb2.SynthesizeSpeechResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.cloud.texttospeech.v1beta1.TextToSpeech", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/google/cloud/texttospeech_v1beta1/py.typed b/google/cloud/texttospeech_v1beta1/py.typed new file mode 100644 index 00000000..9b87c1e1 --- /dev/null +++ b/google/cloud/texttospeech_v1beta1/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-texttospeech package uses inline types. diff --git a/google/cloud/texttospeech_v1beta1/services/__init__.py b/google/cloud/texttospeech_v1beta1/services/__init__.py new file mode 100644 index 00000000..42ffdf2b --- /dev/null +++ b/google/cloud/texttospeech_v1beta1/services/__init__.py @@ -0,0 +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/google/cloud/__init__.py b/google/cloud/texttospeech_v1beta1/services/text_to_speech/__init__.py similarity index 66% rename from google/cloud/__init__.py rename to google/cloud/texttospeech_v1beta1/services/text_to_speech/__init__.py index dd3a9f48..9ec2d969 100644 --- a/google/cloud/__init__.py +++ b/google/cloud/texttospeech_v1beta1/services/text_to_speech/__init__.py @@ -1,22 +1,20 @@ -# Copyright 2018 Google LLC +# -*- 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 +# 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. +# -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil +from .client import TextToSpeechClient - __path__ = pkgutil.extend_path(__path__, __name__) +__all__ = ("TextToSpeechClient",) diff --git a/google/cloud/texttospeech_v1beta1/services/text_to_speech/client.py b/google/cloud/texttospeech_v1beta1/services/text_to_speech/client.py new file mode 100644 index 00000000..ee9784fb --- /dev/null +++ b/google/cloud/texttospeech_v1beta1/services/text_to_speech/client.py @@ -0,0 +1,369 @@ +# -*- 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. +# + +from collections import OrderedDict +import re +from typing import Callable, Dict, Sequence, Tuple, Type, Union +import pkg_resources + +import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.texttospeech_v1beta1.types import cloud_tts + +from .transports.base import TextToSpeechTransport +from .transports.grpc import TextToSpeechGrpcTransport + + +class TextToSpeechClientMeta(type): + """Metaclass for the TextToSpeech client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = OrderedDict() # type: Dict[str, Type[TextToSpeechTransport]] + _transport_registry["grpc"] = TextToSpeechGrpcTransport + + def get_transport_class(cls, label: str = None) -> Type[TextToSpeechTransport]: + """Return an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class TextToSpeechClient(metaclass=TextToSpeechClientMeta): + """Service that implements Google Cloud Text-to-Speech API.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Convert api endpoint to mTLS endpoint. + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + DEFAULT_ENDPOINT = "texttospeech.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + {@api.name}: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + def __init__( + self, + *, + credentials: credentials.Credentials = None, + transport: Union[str, TextToSpeechTransport] = None, + client_options: ClientOptions = None, + ) -> None: + """Instantiate the text to speech client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Union[str, ~.TextToSpeechTransport]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (ClientOptions): Custom options for the client. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. + (2) If ``transport`` argument is None, ``client_options`` can be + used to create a mutual TLS transport. If ``client_cert_source`` + is provided, mutual TLS transport will be created with the given + ``api_endpoint`` or the default mTLS endpoint, and the client + SSL credentials obtained from ``client_cert_source``. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + if isinstance(client_options, dict): + client_options = ClientOptions.from_dict(client_options) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, TextToSpeechTransport): + # transport is a TextToSpeechTransport instance. + if credentials: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + self._transport = transport + elif client_options is None or ( + client_options.api_endpoint is None + and client_options.client_cert_source is None + ): + # Don't trigger mTLS if we get an empty ClientOptions. + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, host=self.DEFAULT_ENDPOINT + ) + else: + # We have a non-empty ClientOptions. If client_cert_source is + # provided, trigger mTLS with user provided endpoint or the default + # mTLS endpoint. + if client_options.client_cert_source: + api_mtls_endpoint = ( + client_options.api_endpoint + if client_options.api_endpoint + else self.DEFAULT_MTLS_ENDPOINT + ) + else: + api_mtls_endpoint = None + + api_endpoint = ( + client_options.api_endpoint + if client_options.api_endpoint + else self.DEFAULT_ENDPOINT + ) + + self._transport = TextToSpeechGrpcTransport( + credentials=credentials, + host=api_endpoint, + api_mtls_endpoint=api_mtls_endpoint, + client_cert_source=client_options.client_cert_source, + ) + + def list_voices( + self, + request: cloud_tts.ListVoicesRequest = None, + *, + language_code: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> cloud_tts.ListVoicesResponse: + r"""Returns a list of Voice supported for synthesis. + + Args: + request (:class:`~.cloud_tts.ListVoicesRequest`): + The request object. The top-level message sent by the + client for the `ListVoices` method. + language_code (:class:`str`): + Optional. Recommended. + `BCP-47 `__ + language tag. If specified, the ListVoices call will + only return voices that can be used to synthesize this + language_code. E.g. when specifying "en-NZ", you will + get supported "en-\*" voices; when specifying "no", you + will get supported "no-\*" (Norwegian) and "nb-*" + (Norwegian Bokmal) voices; specifying "zh" will also get + supported "cmn-*" voices; specifying "zh-hk" will also + get supported "yue-\*" voices. + This corresponds to the ``language_code`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.cloud_tts.ListVoicesResponse: + The message returned to the client by the ``ListVoices`` + method. + + """ + # Create or coerce a protobuf request object. + # Sanity check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + if request is not None and any([language_code]): + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + request = cloud_tts.ListVoicesRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + + if language_code is not None: + request.language_code = language_code + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.list_voices, default_timeout=None, client_info=_client_info + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata) + + # Done; return the response. + return response + + def synthesize_speech( + self, + request: cloud_tts.SynthesizeSpeechRequest = None, + *, + input: cloud_tts.SynthesisInput = None, + voice: cloud_tts.VoiceSelectionParams = None, + audio_config: cloud_tts.AudioConfig = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> cloud_tts.SynthesizeSpeechResponse: + r"""Synthesizes speech synchronously: receive results + after all text input has been processed. + + Args: + request (:class:`~.cloud_tts.SynthesizeSpeechRequest`): + The request object. The top-level message sent by the + client for the `SynthesizeSpeech` method. + input (:class:`~.cloud_tts.SynthesisInput`): + Required. The Synthesizer requires + either plain text or SSML as input. + This corresponds to the ``input`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + voice (:class:`~.cloud_tts.VoiceSelectionParams`): + Required. The desired voice of the + synthesized audio. + This corresponds to the ``voice`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + audio_config (:class:`~.cloud_tts.AudioConfig`): + Required. The configuration of the + synthesized audio. + This corresponds to the ``audio_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.cloud_tts.SynthesizeSpeechResponse: + The message returned to the client by the + ``SynthesizeSpeech`` method. + + """ + # Create or coerce a protobuf request object. + # Sanity check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + if request is not None and any([input, voice, audio_config]): + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + request = cloud_tts.SynthesizeSpeechRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + + if input is not None: + request.input = input + if voice is not None: + request.voice = voice + if audio_config is not None: + request.audio_config = audio_config + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.synthesize_speech, + default_timeout=None, + client_info=_client_info, + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata) + + # Done; return the response. + return response + + +try: + _client_info = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-cloud-texttospeech" + ).version + ) +except pkg_resources.DistributionNotFound: + _client_info = gapic_v1.client_info.ClientInfo() + + +__all__ = ("TextToSpeechClient",) diff --git a/google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/__init__.py b/google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/__init__.py new file mode 100644 index 00000000..bd57d801 --- /dev/null +++ b/google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- 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. +# + +from collections import OrderedDict +from typing import Dict, Type + +from .base import TextToSpeechTransport +from .grpc import TextToSpeechGrpcTransport + + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[TextToSpeechTransport]] +_transport_registry["grpc"] = TextToSpeechGrpcTransport + + +__all__ = ("TextToSpeechTransport", "TextToSpeechGrpcTransport") diff --git a/google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/base.py b/google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/base.py new file mode 100644 index 00000000..b1ebfa21 --- /dev/null +++ b/google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/base.py @@ -0,0 +1,76 @@ +# -*- 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. +# + +import abc +import typing + +from google import auth +from google.auth import credentials # type: ignore + +from google.cloud.texttospeech_v1beta1.types import cloud_tts + + +class TextToSpeechTransport(metaclass=abc.ABCMeta): + """Abstract transport class for TextToSpeech.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + def __init__( + self, + *, + host: str = "texttospeech.googleapis.com", + credentials: credentials.Credentials = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials is None: + credentials, _ = auth.default(scopes=self.AUTH_SCOPES) + + # Save the credentials. + self._credentials = credentials + + @property + def list_voices( + self + ) -> typing.Callable[[cloud_tts.ListVoicesRequest], cloud_tts.ListVoicesResponse]: + raise NotImplementedError + + @property + def synthesize_speech( + self + ) -> typing.Callable[ + [cloud_tts.SynthesizeSpeechRequest], cloud_tts.SynthesizeSpeechResponse + ]: + raise NotImplementedError + + +__all__ = ("TextToSpeechTransport",) diff --git a/google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/grpc.py b/google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/grpc.py new file mode 100644 index 00000000..9d110b51 --- /dev/null +++ b/google/cloud/texttospeech_v1beta1/services/text_to_speech/transports/grpc.py @@ -0,0 +1,212 @@ +# -*- 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. +# + +from typing import Callable, Dict, Tuple + +from google.api_core import grpc_helpers # type: ignore +from google.auth import credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore + + +import grpc # type: ignore + +from google.cloud.texttospeech_v1beta1.types import cloud_tts + +from .base import TextToSpeechTransport + + +class TextToSpeechGrpcTransport(TextToSpeechTransport): + """gRPC backend transport for TextToSpeech. + + Service that implements Google Cloud Text-to-Speech API. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + def __init__( + self, + *, + host: str = "texttospeech.googleapis.com", + credentials: credentials.Credentials = None, + channel: grpc.Channel = None, + api_mtls_endpoint: str = None, + client_cert_source: Callable[[], Tuple[bytes, bytes]] = None + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If + provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or applicatin default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A + callback to provide client SSL certificate bytes and private key + bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` + is None. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + if channel: + # Sanity check: Ensure that channel and credentials are not both + # provided. + credentials = False + + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + elif api_mtls_endpoint: + host = ( + api_mtls_endpoint + if ":" in api_mtls_endpoint + else api_mtls_endpoint + ":443" + ) + + # 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 + + # create a new channel. The provided one is ignored. + self._grpc_channel = grpc_helpers.create_channel( + host, + credentials=credentials, + ssl_credentials=ssl_credentials, + scopes=self.AUTH_SCOPES, + ) + + # Run the base constructor. + super().__init__(host=host, credentials=credentials) + self._stubs = {} # type: Dict[str, Callable] + + @classmethod + def create_channel( + cls, + host: str = "texttospeech.googleapis.com", + credentials: credentials.Credentials = None, + **kwargs + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + address (Optionsl[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + """ + return grpc_helpers.create_channel( + host, credentials=credentials, scopes=cls.AUTH_SCOPES, **kwargs + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Sanity check: Only create a new channel if we do not already + # have one. + if not hasattr(self, "_grpc_channel"): + self._grpc_channel = self.create_channel( + self._host, credentials=self._credentials + ) + + # Return the channel from cache. + return self._grpc_channel + + @property + def list_voices( + self + ) -> Callable[[cloud_tts.ListVoicesRequest], cloud_tts.ListVoicesResponse]: + r"""Return a callable for the list voices method over gRPC. + + Returns a list of Voice supported for synthesis. + + Returns: + Callable[[~.ListVoicesRequest], + ~.ListVoicesResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_voices" not in self._stubs: + self._stubs["list_voices"] = self.grpc_channel.unary_unary( + "/google.cloud.texttospeech.v1beta1.TextToSpeech/ListVoices", + request_serializer=cloud_tts.ListVoicesRequest.serialize, + response_deserializer=cloud_tts.ListVoicesResponse.deserialize, + ) + return self._stubs["list_voices"] + + @property + def synthesize_speech( + self + ) -> Callable[ + [cloud_tts.SynthesizeSpeechRequest], cloud_tts.SynthesizeSpeechResponse + ]: + r"""Return a callable for the synthesize speech method over gRPC. + + Synthesizes speech synchronously: receive results + after all text input has been processed. + + Returns: + Callable[[~.SynthesizeSpeechRequest], + ~.SynthesizeSpeechResponse]: + 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 "synthesize_speech" not in self._stubs: + self._stubs["synthesize_speech"] = self.grpc_channel.unary_unary( + "/google.cloud.texttospeech.v1beta1.TextToSpeech/SynthesizeSpeech", + request_serializer=cloud_tts.SynthesizeSpeechRequest.serialize, + response_deserializer=cloud_tts.SynthesizeSpeechResponse.deserialize, + ) + return self._stubs["synthesize_speech"] + + +__all__ = ("TextToSpeechGrpcTransport",) diff --git a/google/cloud/texttospeech_v1beta1/types.py b/google/cloud/texttospeech_v1beta1/types.py deleted file mode 100644 index 724c9da6..00000000 --- a/google/cloud/texttospeech_v1beta1/types.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- 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. - - -from __future__ import absolute_import -import sys - -from google.api_core.protobuf_helpers import get_messages - -from google.cloud.texttospeech_v1beta1.proto import cloud_tts_pb2 - - -_shared_modules = [] - -_local_modules = [cloud_tts_pb2] - -names = [] - -for module in _shared_modules: # pragma: NO COVER - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.texttospeech_v1beta1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/google/cloud/texttospeech_v1beta1/types/__init__.py b/google/cloud/texttospeech_v1beta1/types/__init__.py new file mode 100644 index 00000000..47b20ad9 --- /dev/null +++ b/google/cloud/texttospeech_v1beta1/types/__init__.py @@ -0,0 +1,39 @@ +# -*- 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. +# + +from .cloud_tts import ( + ListVoicesRequest, + ListVoicesResponse, + Voice, + SynthesizeSpeechRequest, + SynthesisInput, + VoiceSelectionParams, + AudioConfig, + SynthesizeSpeechResponse, +) + + +__all__ = ( + "ListVoicesRequest", + "ListVoicesResponse", + "Voice", + "SynthesizeSpeechRequest", + "SynthesisInput", + "VoiceSelectionParams", + "AudioConfig", + "SynthesizeSpeechResponse", +) diff --git a/google/cloud/texttospeech_v1beta1/types/cloud_tts.py b/google/cloud/texttospeech_v1beta1/types/cloud_tts.py new file mode 100644 index 00000000..f0dfb5f5 --- /dev/null +++ b/google/cloud/texttospeech_v1beta1/types/cloud_tts.py @@ -0,0 +1,265 @@ +# -*- 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. +# + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.texttospeech.v1beta1", + manifest={ + "SsmlVoiceGender", + "AudioEncoding", + "ListVoicesRequest", + "ListVoicesResponse", + "Voice", + "SynthesizeSpeechRequest", + "SynthesisInput", + "VoiceSelectionParams", + "AudioConfig", + "SynthesizeSpeechResponse", + }, +) + + +class SsmlVoiceGender(proto.Enum): + r"""Gender of the voice as described in `SSML voice + element `__. + """ + SSML_VOICE_GENDER_UNSPECIFIED = 0 + MALE = 1 + FEMALE = 2 + NEUTRAL = 3 + + +class AudioEncoding(proto.Enum): + r"""Configuration to set up audio encoder. The encoding + determines the output audio format that we'd like. + """ + AUDIO_ENCODING_UNSPECIFIED = 0 + LINEAR16 = 1 + MP3 = 2 + OGG_OPUS = 3 + + +class ListVoicesRequest(proto.Message): + r"""The top-level message sent by the client for the ``ListVoices`` + method. + + Attributes: + language_code (str): + Optional. Recommended. + `BCP-47 `__ + language tag. If specified, the ListVoices call will only + return voices that can be used to synthesize this + language_code. E.g. when specifying "en-NZ", you will get + supported "en-\*" voices; when specifying "no", you will get + supported "no-\*" (Norwegian) and "nb-*" (Norwegian Bokmal) + voices; specifying "zh" will also get supported "cmn-*" + voices; specifying "zh-hk" will also get supported "yue-\*" + voices. + """ + + language_code = proto.Field(proto.STRING, number=1) + + +class ListVoicesResponse(proto.Message): + r"""The message returned to the client by the ``ListVoices`` method. + + Attributes: + voices (Sequence[~.cloud_tts.Voice]): + The list of voices. + """ + + voices = proto.RepeatedField(proto.MESSAGE, number=1, message="Voice") + + +class Voice(proto.Message): + r"""Description of a voice supported by the TTS service. + + Attributes: + language_codes (Sequence[str]): + The languages that this voice supports, expressed as + `BCP-47 `__ + language tags (e.g. "en-US", "es-419", "cmn-tw"). + name (str): + The name of this voice. Each distinct voice + has a unique name. + ssml_gender (~.cloud_tts.SsmlVoiceGender): + The gender of this voice. + natural_sample_rate_hertz (int): + The natural sample rate (in hertz) for this + voice. + """ + + language_codes = proto.RepeatedField(proto.STRING, number=1) + name = proto.Field(proto.STRING, number=2) + ssml_gender = proto.Field(proto.ENUM, number=3, enum="SsmlVoiceGender") + natural_sample_rate_hertz = proto.Field(proto.INT32, number=4) + + +class SynthesizeSpeechRequest(proto.Message): + r"""The top-level message sent by the client for the + ``SynthesizeSpeech`` method. + + Attributes: + input (~.cloud_tts.SynthesisInput): + Required. The Synthesizer requires either + plain text or SSML as input. + voice (~.cloud_tts.VoiceSelectionParams): + Required. The desired voice of the + synthesized audio. + audio_config (~.cloud_tts.AudioConfig): + Required. The configuration of the + synthesized audio. + """ + + input = proto.Field(proto.MESSAGE, number=1, message="SynthesisInput") + voice = proto.Field(proto.MESSAGE, number=2, message="VoiceSelectionParams") + audio_config = proto.Field(proto.MESSAGE, number=3, message="AudioConfig") + + +class SynthesisInput(proto.Message): + r"""Contains text input to be synthesized. Either ``text`` or ``ssml`` + must be supplied. Supplying both or neither returns + [google.rpc.Code.INVALID_ARGUMENT][]. The input size is limited to + 5000 characters. + + Attributes: + text (str): + The raw text to be synthesized. + ssml (str): + The SSML document to be synthesized. The SSML document must + be valid and well-formed. Otherwise the RPC will fail and + return [google.rpc.Code.INVALID_ARGUMENT][]. For more + information, see + `SSML `__. + """ + + text = proto.Field(proto.STRING, number=1) + ssml = proto.Field(proto.STRING, number=2) + + +class VoiceSelectionParams(proto.Message): + r"""Description of which voice to use for a synthesis request. + + Attributes: + language_code (str): + Required. The language (and potentially also the region) of + the voice expressed as a + `BCP-47 `__ + language tag, e.g. "en-US". This should not include a script + tag (e.g. use "cmn-cn" rather than "cmn-Hant-cn"), because + the script will be inferred from the input provided in the + SynthesisInput. The TTS service will use this parameter to + help choose an appropriate voice. Note that the TTS service + may choose a voice with a slightly different language code + than the one selected; it may substitute a different region + (e.g. using en-US rather than en-CA if there isn't a + Canadian voice available), or even a different language, + e.g. using "nb" (Norwegian Bokmal) instead of "no" + (Norwegian)". + name (str): + The name of the voice. If not set, the service will choose a + voice based on the other parameters such as language_code + and gender. + ssml_gender (~.cloud_tts.SsmlVoiceGender): + The preferred gender of the voice. If not set, the service + will choose a voice based on the other parameters such as + language_code and name. Note that this is only a preference, + not requirement; if a voice of the appropriate gender is not + available, the synthesizer should substitute a voice with a + different gender rather than failing the request. + """ + + language_code = proto.Field(proto.STRING, number=1) + name = proto.Field(proto.STRING, number=2) + ssml_gender = proto.Field(proto.ENUM, number=3, enum="SsmlVoiceGender") + + +class AudioConfig(proto.Message): + r"""Description of audio data to be synthesized. + + Attributes: + audio_encoding (~.cloud_tts.AudioEncoding): + Required. The format of the audio byte + stream. + speaking_rate (float): + Optional. Input only. Speaking rate/speed, in the range + [0.25, 4.0]. 1.0 is the normal native speed supported by the + specific voice. 2.0 is twice as fast, and 0.5 is half as + fast. If unset(0.0), defaults to the native 1.0 speed. Any + other values < 0.25 or > 4.0 will return an error. + pitch (float): + Optional. Input only. Speaking pitch, in the range [-20.0, + 20.0]. 20 means increase 20 semitones from the original + pitch. -20 means decrease 20 semitones from the original + pitch. + volume_gain_db (float): + Optional. Input only. Volume gain (in dB) of the normal + native volume supported by the specific voice, in the range + [-96.0, 16.0]. If unset, or set to a value of 0.0 (dB), will + play at normal native signal amplitude. A value of -6.0 (dB) + will play at approximately half the amplitude of the normal + native signal amplitude. A value of +6.0 (dB) will play at + approximately twice the amplitude of the normal native + signal amplitude. Strongly recommend not to exceed +10 (dB) + as there's usually no effective increase in loudness for any + value greater than that. + sample_rate_hertz (int): + Optional. The synthesis sample rate (in hertz) for this + audio. When this is specified in SynthesizeSpeechRequest, if + this is different from the voice's natural sample rate, then + the synthesizer will honor this request by converting to the + desired sample rate (which might result in worse audio + quality), unless the specified sample rate is not supported + for the encoding chosen, in which case it will fail the + request and return [google.rpc.Code.INVALID_ARGUMENT][]. + effects_profile_id (Sequence[str]): + Optional. Input only. An identifier which selects 'audio + effects' profiles that are applied on (post synthesized) + text to speech. Effects are applied on top of each other in + the order they are given. See `audio + profiles `__ + for current supported profile ids. + """ + + audio_encoding = proto.Field(proto.ENUM, number=1, enum="AudioEncoding") + speaking_rate = proto.Field(proto.DOUBLE, number=2) + pitch = proto.Field(proto.DOUBLE, number=3) + volume_gain_db = proto.Field(proto.DOUBLE, number=4) + sample_rate_hertz = proto.Field(proto.INT32, number=5) + effects_profile_id = proto.RepeatedField(proto.STRING, number=6) + + +class SynthesizeSpeechResponse(proto.Message): + r"""The message returned to the client by the ``SynthesizeSpeech`` + method. + + Attributes: + audio_content (bytes): + The audio data bytes encoded as specified in the request, + including the header for encodings that are wrapped in + containers (e.g. MP3, OGG_OPUS). For LINEAR16 audio, we + include the WAV header. Note: as with all bytes fields, + protobuffers use a pure binary representation, whereas JSON + representations use base64. + """ + + audio_content = proto.Field(proto.BYTES, number=1) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 00000000..4505b485 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,3 @@ +[mypy] +python_version = 3.6 +namespace_packages = True diff --git a/noxfile.py b/noxfile.py index 44c0ddf9..640ccd4f 100644 --- a/noxfile.py +++ b/noxfile.py @@ -26,8 +26,12 @@ BLACK_VERSION = "black==19.3b0" BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] +DEFAULT_PYTHON_VERSION = "3.7" +SYSTEM_TEST_PYTHON_VERSIONS = ["3.7"] +UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8"] -@nox.session(python="3.7") + +@nox.session(python=DEFAULT_PYTHON_VERSION) def lint(session): """Run linters. @@ -53,7 +57,7 @@ def blacken(session): session.run("black", *BLACK_PATHS) -@nox.session(python="3.7") +@nox.session(python=DEFAULT_PYTHON_VERSION) def lint_setup_py(session): """Verify that setup.py is valid (including RST check).""" session.install("docutils", "pygments") @@ -81,13 +85,13 @@ def default(session): ) -@nox.session(python=["2.7", "3.5", "3.6", "3.7", "3.8"]) +@nox.session(python=UNIT_TEST_PYTHON_VERSIONS) def unit(session): """Run the unit test suite.""" default(session) -@nox.session(python=["2.7", "3.7"]) +@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS) def system(session): """Run the system test suite.""" system_test_path = os.path.join("tests", "system.py") @@ -117,7 +121,7 @@ def system(session): session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) -@nox.session(python="3.7") +@nox.session(python=DEFAULT_PYTHON_VERSION) def cover(session): """Run the final coverage report. @@ -125,12 +129,12 @@ def cover(session): test runs (not system test runs), and then erases coverage data. """ session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=85") + session.run("coverage", "report", "--show-missing", "--fail-under=100") session.run("coverage", "erase") -@nox.session(python="3.7") +@nox.session(python=DEFAULT_PYTHON_VERSION) def docs(session): """Build the docs for this library.""" diff --git a/samples/snippets/.gitignore b/samples/snippets/.gitignore new file mode 100644 index 00000000..8f6514bd --- /dev/null +++ b/samples/snippets/.gitignore @@ -0,0 +1 @@ +output.mp3 \ No newline at end of file diff --git a/samples/snippets/audio_profile.py b/samples/snippets/audio_profile.py index 01f2ba88..cfecdb98 100644 --- a/samples/snippets/audio_profile.py +++ b/samples/snippets/audio_profile.py @@ -32,41 +32,43 @@ def synthesize_text_with_audio_profile(text, output, effects_profile_id): client = texttospeech.TextToSpeechClient() - input_text = texttospeech.types.SynthesisInput(text=text) + input_text = texttospeech.SynthesisInput(text=text) # Note: the voice can also be specified by name. # Names of voices can be retrieved with client.list_voices(). - voice = texttospeech.types.VoiceSelectionParams(language_code='en-US') + voice = texttospeech.VoiceSelectionParams(language_code="en-US") # Note: you can pass in multiple effects_profile_id. They will be applied # in the same order they are provided. - audio_config = texttospeech.types.AudioConfig( - audio_encoding=texttospeech.enums.AudioEncoding.MP3, - effects_profile_id=[effects_profile_id]) + audio_config = texttospeech.AudioConfig( + audio_encoding=texttospeech.AudioEncoding.MP3, + effects_profile_id=[effects_profile_id], + ) - response = client.synthesize_speech(input_text, voice, audio_config) + response = client.synthesize_speech( + input=input_text, voice=voice, audio_config=audio_config + ) # The response's audio_content is binary. - with open(output, 'wb') as out: + with open(output, "wb") as out: out.write(response.audio_content) print('Audio content written to file "%s"' % output) + # [END tts_synthesize_text_audio_profile_beta] # [END tts_synthesize_text_audio_profile] -if __name__ == '__main__': +if __name__ == "__main__": parser = argparse.ArgumentParser( - description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument('--output', - help='The output mp3 file.') - parser.add_argument('--text', - help='The text from which to synthesize speech.') - parser.add_argument('--effects_profile_id', - help='The audio effects profile id to be applied.') + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument("--output", help="The output mp3 file.") + parser.add_argument("--text", help="The text from which to synthesize speech.") + parser.add_argument( + "--effects_profile_id", help="The audio effects profile id to be applied." + ) args = parser.parse_args() - synthesize_text_with_audio_profile(args.text, args.output, - args.effects_profile_id) + synthesize_text_with_audio_profile(args.text, args.output, args.effects_profile_id) diff --git a/samples/snippets/audio_profile_test.py b/samples/snippets/audio_profile_test.py index 43a30bf0..89616cf8 100644 --- a/samples/snippets/audio_profile_test.py +++ b/samples/snippets/audio_profile_test.py @@ -16,17 +16,16 @@ import audio_profile -TEXT = 'hello' -OUTPUT = 'output.mp3' -EFFECTS_PROFILE_ID = 'telephony-class-application' +TEXT = "hello" +OUTPUT = "output.mp3" +EFFECTS_PROFILE_ID = "telephony-class-application" def test_audio_profile(capsys): if os.path.exists(OUTPUT): os.remove(OUTPUT) assert not os.path.exists(OUTPUT) - audio_profile.synthesize_text_with_audio_profile(TEXT, OUTPUT, - EFFECTS_PROFILE_ID) + audio_profile.synthesize_text_with_audio_profile(TEXT, OUTPUT, EFFECTS_PROFILE_ID) out, err = capsys.readouterr() assert ('Audio content written to file "%s"' % OUTPUT) in out diff --git a/samples/snippets/list_voices.py b/samples/snippets/list_voices.py index a2da5a17..4d991a95 100644 --- a/samples/snippets/list_voices.py +++ b/samples/snippets/list_voices.py @@ -25,7 +25,7 @@ def list_voices(): """Lists the available voices.""" from google.cloud import texttospeech - from google.cloud.texttospeech import enums + client = texttospeech.TextToSpeechClient() # Performs the list voices request @@ -33,22 +33,23 @@ def list_voices(): for voice in voices.voices: # Display the voice's name. Example: tpc-vocoded - print('Name: {}'.format(voice.name)) + print(f"Name: {voice.name}") # Display the supported language codes for this voice. Example: "en-US" for language_code in voice.language_codes: - print('Supported language: {}'.format(language_code)) + print(f"Supported language: {language_code}") - ssml_gender = enums.SsmlVoiceGender(voice.ssml_gender) + ssml_gender = texttospeech.SsmlVoiceGender(voice.ssml_gender) # Display the SSML Voice Gender - print('SSML Voice Gender: {}'.format(ssml_gender.name)) + print(f"SSML Voice Gender: {ssml_gender.name}") # Display the natural sample rate hertz for this voice. Example: 24000 - print('Natural Sample Rate Hertz: {}\n'.format( - voice.natural_sample_rate_hertz)) + print(f"Natural Sample Rate Hertz: {voice.natural_sample_rate_hertz}\n") + + # [END tts_list_voices] -if __name__ == '__main__': +if __name__ == "__main__": list_voices() diff --git a/samples/snippets/list_voices_test.py b/samples/snippets/list_voices_test.py index fd325569..9260e86d 100644 --- a/samples/snippets/list_voices_test.py +++ b/samples/snippets/list_voices_test.py @@ -18,6 +18,6 @@ def test_list_voices(capsys): list_voices.list_voices() out, err = capsys.readouterr() - assert 'en-US' in out - assert 'SSML Voice Gender: MALE' in out - assert 'SSML Voice Gender: FEMALE' in out + assert "en-US" in out + assert "SSML Voice Gender: MALE" in out + assert "SSML Voice Gender: FEMALE" in out diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py index b23055f1..c92cf2ab 100644 --- a/samples/snippets/noxfile.py +++ b/samples/snippets/noxfile.py @@ -37,24 +37,22 @@ TEST_CONFIG = { # You can opt out from the test for specific Python versions. - 'ignored_versions': ["2.7"], - + "ignored_versions": ["2.7"], # An envvar key for determining the project id to use. Change it # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a # build specific Cloud project. You can also use your own string # to use your own Cloud project. - 'gcloud_project_env': 'GCLOUD_PROJECT', + "gcloud_project_env": "GCLOUD_PROJECT", # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', - # A dictionary you want to inject into your test. Don't put any # secrets here. These values will override predefined values. - 'envs': {}, + "envs": {}, } try: # Ensure we can import noxfile_config in the project's directory. - sys.path.append('.') + sys.path.append(".") from noxfile_config import TEST_CONFIG_OVERRIDE except ImportError as e: print("No user noxfile_config found: detail: {}".format(e)) @@ -69,13 +67,13 @@ def get_pytest_env_vars(): ret = {} # Override the GCLOUD_PROJECT and the alias. - env_key = TEST_CONFIG['gcloud_project_env'] + env_key = TEST_CONFIG["gcloud_project_env"] # This should error out if not set. - ret['GOOGLE_CLOUD_PROJECT'] = os.environ[env_key] - ret['GCLOUD_PROJECT'] = os.environ[env_key] + ret["GOOGLE_CLOUD_PROJECT"] = os.environ[env_key] + ret["GCLOUD_PROJECT"] = os.environ[env_key] # Apply user supplied envs. - ret.update(TEST_CONFIG['envs']) + ret.update(TEST_CONFIG["envs"]) return ret @@ -84,7 +82,7 @@ def get_pytest_env_vars(): ALL_VERSIONS = ["2.7", "3.6", "3.7", "3.8"] # Any default versions that should be ignored. -IGNORED_VERSIONS = TEST_CONFIG['ignored_versions'] +IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] TESTED_VERSIONS = sorted([v for v in ALL_VERSIONS if v not in IGNORED_VERSIONS]) @@ -139,7 +137,7 @@ def lint(session): args = FLAKE8_COMMON_ARGS + [ "--application-import-names", ",".join(local_names), - "." + ".", ] session.run("flake8", *args) @@ -183,9 +181,9 @@ def py(session): if session.python in TESTED_VERSIONS: _session_tests(session) else: - session.skip("SKIPPED: {} tests are disabled for this sample.".format( - session.python - )) + session.skip( + "SKIPPED: {} tests are disabled for this sample.".format(session.python) + ) # diff --git a/samples/snippets/quickstart.py b/samples/snippets/quickstart.py index f462139d..f9e3da5c 100644 --- a/samples/snippets/quickstart.py +++ b/samples/snippets/quickstart.py @@ -34,29 +34,32 @@ def run_quickstart(): client = texttospeech.TextToSpeechClient() # Set the text input to be synthesized - synthesis_input = texttospeech.types.SynthesisInput(text="Hello, World!") + synthesis_input = texttospeech.SynthesisInput(text="Hello, World!") # Build the voice request, select the language code ("en-US") and the ssml # voice gender ("neutral") - voice = texttospeech.types.VoiceSelectionParams( - language_code='en-US', - ssml_gender=texttospeech.enums.SsmlVoiceGender.NEUTRAL) + voice = texttospeech.VoiceSelectionParams( + language_code="en-US", ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL + ) # Select the type of audio file you want returned - audio_config = texttospeech.types.AudioConfig( - audio_encoding=texttospeech.enums.AudioEncoding.MP3) + audio_config = texttospeech.AudioConfig( + audio_encoding=texttospeech.AudioEncoding.MP3 + ) # Perform the text-to-speech request on the text input with the selected # voice parameters and audio file type - response = client.synthesize_speech(synthesis_input, voice, audio_config) + response = client.synthesize_speech( + input=synthesis_input, voice=voice, audio_config=audio_config + ) # The response's audio_content is binary. - with open('output.mp3', 'wb') as out: + with open("output.mp3", "wb") as out: # Write the response to the output file. out.write(response.audio_content) print('Audio content written to file "output.mp3"') # [END tts_quickstart] -if __name__ == '__main__': +if __name__ == "__main__": run_quickstart() diff --git a/samples/snippets/ssml_addresses.py b/samples/snippets/ssml_addresses.py index dd927605..51229357 100644 --- a/samples/snippets/ssml_addresses.py +++ b/samples/snippets/ssml_addresses.py @@ -41,26 +41,29 @@ def ssml_to_audio(ssml_text, outfile): client = texttospeech.TextToSpeechClient() # Sets the text input to be synthesized - synthesis_input = texttospeech.types.SynthesisInput(ssml=ssml_text) + synthesis_input = texttospeech.SynthesisInput(ssml=ssml_text) # Builds the voice request, selects the language code ("en-US") and # the SSML voice gender ("MALE") - voice = texttospeech.types.VoiceSelectionParams( - language_code='en-US', - ssml_gender=texttospeech.enums.SsmlVoiceGender.MALE) + voice = texttospeech.VoiceSelectionParams( + language_code="en-US", ssml_gender=texttospeech.SsmlVoiceGender.MALE + ) # Selects the type of audio file to return - audio_config = texttospeech.types.AudioConfig( - audio_encoding=texttospeech.enums.AudioEncoding.MP3) + audio_config = texttospeech.AudioConfig( + audio_encoding=texttospeech.AudioEncoding.MP3 + ) # Performs the text-to-speech request on the text input with the selected # voice parameters and audio file type - response = client.synthesize_speech(synthesis_input, voice, audio_config) + response = client.synthesize_speech( + input=synthesis_input, voice=voice, audio_config=audio_config + ) # Writes the synthetic audio to the output file. - with open(outfile, 'wb') as out: + with open(outfile, "wb") as out: out.write(response.audio_content) - print('Audio content written to file ' + outfile) + print("Audio content written to file " + outfile) # [END tts_ssml_address_audio] @@ -80,7 +83,7 @@ def text_to_ssml(inputfile): # A string of SSML text based on plaintext input # Parses lines of input file - with open(inputfile, 'r') as f: + with open(inputfile, "r") as f: raw_lines = f.read() # Replace special characters with HTML Ampersand Character Codes @@ -92,22 +95,25 @@ def text_to_ssml(inputfile): # Convert plaintext to SSML # Wait two seconds between each address - ssml = '{}'.format( - escaped_lines.replace('\n', '\n')) + ssml = "{}".format( + escaped_lines.replace("\n", '\n') + ) # Return the concatenated string of ssml script return ssml + + # [END tts_ssml_address_ssml] # [START tts_ssml_address_test] def main(): # test example address file - plaintext = 'resources/example.txt' + plaintext = "resources/example.txt" ssml_text = text_to_ssml(plaintext) - ssml_to_audio(ssml_text, 'resources/example.mp3') + ssml_to_audio(ssml_text, "resources/example.mp3") # [END tts_ssml_address_test] -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/samples/snippets/ssml_addresses_test.py b/samples/snippets/ssml_addresses_test.py index 5f001608..caf25c09 100644 --- a/samples/snippets/ssml_addresses_test.py +++ b/samples/snippets/ssml_addresses_test.py @@ -20,11 +20,11 @@ def test_text_to_ssml(capsys): # Read expected SSML output from resources - with open('resources/example.ssml', 'r') as f: + with open("resources/example.ssml", "r") as f: expected_ssml = f.read() # Assert plaintext converted to SSML - input_text = 'resources/example.txt' + input_text = "resources/example.txt" tested_ssml = text_to_ssml(input_text) assert expected_ssml == tested_ssml @@ -32,15 +32,15 @@ def test_text_to_ssml(capsys): def test_ssml_to_audio(capsys): # Read SSML input from resources - with open('resources/example.ssml', 'r') as f: + with open("resources/example.ssml", "r") as f: input_ssml = f.read() # Assert audio file generated - ssml_to_audio(input_ssml, 'test_example.mp3') + ssml_to_audio(input_ssml, "test_example.mp3") out, err = capsys.readouterr() # Assert MP3 file created - assert os.path.isfile('test_example.mp3') + assert os.path.isfile("test_example.mp3") assert "Audio content written to file test_example.mp3" in out # Delete MP3 test file diff --git a/samples/snippets/synthesize_file.py b/samples/snippets/synthesize_file.py index f62d6330..977c0495 100644 --- a/samples/snippets/synthesize_file.py +++ b/samples/snippets/synthesize_file.py @@ -28,27 +28,33 @@ def synthesize_text_file(text_file): """Synthesizes speech from the input file of text.""" from google.cloud import texttospeech + client = texttospeech.TextToSpeechClient() - with open(text_file, 'r') as f: + with open(text_file, "r") as f: text = f.read() - input_text = texttospeech.types.SynthesisInput(text=text) + input_text = texttospeech.SynthesisInput(text=text) # Note: the voice can also be specified by name. # Names of voices can be retrieved with client.list_voices(). - voice = texttospeech.types.VoiceSelectionParams( - language_code='en-US', - ssml_gender=texttospeech.enums.SsmlVoiceGender.FEMALE) + voice = texttospeech.VoiceSelectionParams( + language_code="en-US", ssml_gender=texttospeech.SsmlVoiceGender.FEMALE + ) - audio_config = texttospeech.types.AudioConfig( - audio_encoding=texttospeech.enums.AudioEncoding.MP3) + audio_config = texttospeech.AudioConfig( + audio_encoding=texttospeech.AudioEncoding.MP3 + ) - response = client.synthesize_speech(input_text, voice, audio_config) + response = client.synthesize_speech( + request={"input": input_text, "voice": voice, "audio_config": audio_config} + ) # The response's audio_content is binary. - with open('output.mp3', 'wb') as out: + with open("output.mp3", "wb") as out: out.write(response.audio_content) print('Audio content written to file "output.mp3"') + + # [END tts_synthesize_text_file] @@ -60,39 +66,43 @@ def synthesize_ssml_file(ssml_file): https://www.w3.org/TR/speech-synthesis/ """ from google.cloud import texttospeech + client = texttospeech.TextToSpeechClient() - with open(ssml_file, 'r') as f: + with open(ssml_file, "r") as f: ssml = f.read() - input_text = texttospeech.types.SynthesisInput(ssml=ssml) + input_text = texttospeech.SynthesisInput(ssml=ssml) # Note: the voice can also be specified by name. # Names of voices can be retrieved with client.list_voices(). - voice = texttospeech.types.VoiceSelectionParams( - language_code='en-US', - ssml_gender=texttospeech.enums.SsmlVoiceGender.FEMALE) + voice = texttospeech.VoiceSelectionParams( + language_code="en-US", ssml_gender=texttospeech.SsmlVoiceGender.FEMALE + ) - audio_config = texttospeech.types.AudioConfig( - audio_encoding=texttospeech.enums.AudioEncoding.MP3) + audio_config = texttospeech.AudioConfig( + audio_encoding=texttospeech.AudioEncoding.MP3 + ) - response = client.synthesize_speech(input_text, voice, audio_config) + response = client.synthesize_speech( + input=input_text, voice=voice, audio_config=audio_config + ) # The response's audio_content is binary. - with open('output.mp3', 'wb') as out: + with open("output.mp3", "wb") as out: out.write(response.audio_content) print('Audio content written to file "output.mp3"') + + # [END tts_synthesize_ssml_file] -if __name__ == '__main__': +if __name__ == "__main__": parser = argparse.ArgumentParser( - description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter) + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('--text', - help='The text file from which to synthesize speech.') - group.add_argument('--ssml', - help='The ssml file from which to synthesize speech.') + group.add_argument("--text", help="The text file from which to synthesize speech.") + group.add_argument("--ssml", help="The ssml file from which to synthesize speech.") args = parser.parse_args() diff --git a/samples/snippets/synthesize_file_test.py b/samples/snippets/synthesize_file_test.py index 2652009f..be6b6e05 100644 --- a/samples/snippets/synthesize_file_test.py +++ b/samples/snippets/synthesize_file_test.py @@ -15,16 +15,16 @@ import synthesize_file -TEXT_FILE = 'resources/hello.txt' -SSML_FILE = 'resources/hello.ssml' +TEXT_FILE = "resources/hello.txt" +SSML_FILE = "resources/hello.ssml" def test_synthesize_text_file(capsys): synthesize_file.synthesize_text_file(text_file=TEXT_FILE) out, err = capsys.readouterr() - assert 'Audio content written to file' in out - statinfo = os.stat('output.mp3') + assert "Audio content written to file" in out + statinfo = os.stat("output.mp3") assert statinfo.st_size > 0 @@ -32,6 +32,6 @@ def test_synthesize_ssml_file(capsys): synthesize_file.synthesize_ssml_file(ssml_file=SSML_FILE) out, err = capsys.readouterr() - assert 'Audio content written to file' in out - statinfo = os.stat('output.mp3') + assert "Audio content written to file" in out + statinfo = os.stat("output.mp3") assert statinfo.st_size > 0 diff --git a/samples/snippets/synthesize_text.py b/samples/snippets/synthesize_text.py index 768c0da0..c22bff40 100644 --- a/samples/snippets/synthesize_text.py +++ b/samples/snippets/synthesize_text.py @@ -28,26 +28,33 @@ def synthesize_text(text): """Synthesizes speech from the input string of text.""" from google.cloud import texttospeech + client = texttospeech.TextToSpeechClient() - input_text = texttospeech.types.SynthesisInput(text=text) + input_text = texttospeech.SynthesisInput(text=text) # Note: the voice can also be specified by name. # Names of voices can be retrieved with client.list_voices(). - voice = texttospeech.types.VoiceSelectionParams( - language_code='en-US', - name='en-US-Standard-C', - ssml_gender=texttospeech.enums.SsmlVoiceGender.FEMALE) + voice = texttospeech.VoiceSelectionParams( + language_code="en-US", + name="en-US-Standard-C", + ssml_gender=texttospeech.SsmlVoiceGender.FEMALE, + ) - audio_config = texttospeech.types.AudioConfig( - audio_encoding=texttospeech.enums.AudioEncoding.MP3) + audio_config = texttospeech.AudioConfig( + audio_encoding=texttospeech.AudioEncoding.MP3 + ) - response = client.synthesize_speech(input_text, voice, audio_config) + response = client.synthesize_speech( + request={"input": input_text, "voice": voice, "audio_config": audio_config} + ) # The response's audio_content is binary. - with open('output.mp3', 'wb') as out: + with open("output.mp3", "wb") as out: out.write(response.audio_content) print('Audio content written to file "output.mp3"') + + # [END tts_synthesize_text] @@ -61,38 +68,45 @@ def synthesize_ssml(ssml): Example: Hello there. """ from google.cloud import texttospeech + client = texttospeech.TextToSpeechClient() - input_text = texttospeech.types.SynthesisInput(ssml=ssml) + input_text = texttospeech.SynthesisInput(ssml=ssml) # Note: the voice can also be specified by name. # Names of voices can be retrieved with client.list_voices(). - voice = texttospeech.types.VoiceSelectionParams( - language_code='en-US', - name='en-US-Standard-C', - ssml_gender=texttospeech.enums.SsmlVoiceGender.FEMALE) + voice = texttospeech.VoiceSelectionParams( + language_code="en-US", + name="en-US-Standard-C", + ssml_gender=texttospeech.SsmlVoiceGender.FEMALE, + ) - audio_config = texttospeech.types.AudioConfig( - audio_encoding=texttospeech.enums.AudioEncoding.MP3) + audio_config = texttospeech.AudioConfig( + audio_encoding=texttospeech.AudioEncoding.MP3 + ) - response = client.synthesize_speech(input_text, voice, audio_config) + response = client.synthesize_speech( + input=input_text, voice=voice, audio_config=audio_config + ) # The response's audio_content is binary. - with open('output.mp3', 'wb') as out: + with open("output.mp3", "wb") as out: out.write(response.audio_content) print('Audio content written to file "output.mp3"') + + # [END tts_synthesize_ssml] -if __name__ == '__main__': +if __name__ == "__main__": parser = argparse.ArgumentParser( - description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter) + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('--text', - help='The text from which to synthesize speech.') - group.add_argument('--ssml', - help='The ssml string from which to synthesize speech.') + group.add_argument("--text", help="The text from which to synthesize speech.") + group.add_argument( + "--ssml", help="The ssml string from which to synthesize speech." + ) args = parser.parse_args() diff --git a/samples/snippets/synthesize_text_test.py b/samples/snippets/synthesize_text_test.py index 948d58da..68c52e38 100644 --- a/samples/snippets/synthesize_text_test.py +++ b/samples/snippets/synthesize_text_test.py @@ -15,16 +15,16 @@ import synthesize_text -TEXT = 'Hello there.' -SSML = 'Hello there.' +TEXT = "Hello there." +SSML = "Hello there." def test_synthesize_text(capsys): synthesize_text.synthesize_text(text=TEXT) out, err = capsys.readouterr() - assert 'Audio content written to file' in out - statinfo = os.stat('output.mp3') + assert "Audio content written to file" in out + statinfo = os.stat("output.mp3") assert statinfo.st_size > 0 @@ -32,6 +32,6 @@ def test_synthesize_ssml(capsys): synthesize_text.synthesize_ssml(ssml=SSML) out, err = capsys.readouterr() - assert 'Audio content written to file' in out - statinfo = os.stat('output.mp3') + assert "Audio content written to file" in out + statinfo = os.stat("output.mp3") assert statinfo.st_size > 0 diff --git a/scripts/decrypt-secrets.sh b/scripts/decrypt-secrets.sh index 6140da66..ff599eb2 100755 --- a/scripts/decrypt-secrets.sh +++ b/scripts/decrypt-secrets.sh @@ -20,7 +20,14 @@ ROOT=$( dirname "$DIR" ) # Work from the project root. cd $ROOT -openssl aes-256-cbc -k "$1" -md sha256 \ - -in testing/secrets.tar.enc -out secrets.tar -d -tar xvf secrets.tar -rm secrets.tar +# Use SECRET_MANAGER_PROJECT if set, fallback to cloud-devrel-kokoro-resources. +PROJECT_ID="${SECRET_MANAGER_PROJECT:-cloud-devrel-kokoro-resources}" + +gcloud secrets versions access latest --secret="python-docs-samples-test-env" \ + > testing/test-env.sh +gcloud secrets versions access latest \ + --secret="python-docs-samples-service-account" \ + > testing/service-account.json +gcloud secrets versions access latest \ + --secret="python-docs-samples-client-secrets" \ + > testing/client-secrets.json \ No newline at end of file diff --git a/scripts/fixup_keywords.py b/scripts/fixup_keywords.py new file mode 100644 index 00000000..c216d0ba --- /dev/null +++ b/scripts/fixup_keywords.py @@ -0,0 +1,178 @@ +# -*- 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. +# + +import argparse +import os +import libcst as cst +import pathlib +import sys +from typing import (Any, Callable, Dict, List, Sequence, Tuple) + + +def partition( + predicate: Callable[[Any], bool], + iterator: Sequence[Any] +) -> Tuple[List[Any], List[Any]]: + """A stable, out-of-place partition.""" + results = ([], []) + + for i in iterator: + results[int(predicate(i))].append(i) + + # Returns trueList, falseList + return results[1], results[0] + + +class texttospeechCallTransformer(cst.CSTTransformer): + CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') + METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + 'list_voices': ('language_code', ), + 'synthesize_speech': ('input', 'voice', 'audio_config', ), + } + + def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: + try: + key = original.func.attr.value + kword_params = self.METHOD_TO_PARAMS[key] + except (AttributeError, KeyError): + # Either not a method from the API or too convoluted to be sure. + return updated + + # If the existing code is valid, keyword args come after positional args. + # Therefore, all positional args must map to the first parameters. + args, kwargs = partition(lambda a: not bool(a.keyword), updated.args) + if any(k.keyword.value == "request" for k in kwargs): + # We've already fixed this file, don't fix it again. + return updated + + kwargs, ctrl_kwargs = partition( + lambda a: not a.keyword.value in self.CTRL_PARAMS, + kwargs + ) + + args, ctrl_args = args[:len(kword_params)], args[len(kword_params):] + ctrl_kwargs.extend(cst.Arg(value=a.value, keyword=cst.Name(value=ctrl)) + for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS)) + + request_arg = cst.Arg( + value=cst.Dict([ + cst.DictElement( + cst.SimpleString("'{}'".format(name)), + cst.Element(value=arg.value) + ) + # Note: the args + kwargs looks silly, but keep in mind that + # the control parameters had to be stripped out, and that + # those could have been passed positionally or by keyword. + for name, arg in zip(kword_params, args + kwargs)]), + keyword=cst.Name("request") + ) + + return updated.with_changes( + args=[request_arg] + ctrl_kwargs + ) + + +def fix_files( + in_dir: pathlib.Path, + out_dir: pathlib.Path, + *, + transformer=texttospeechCallTransformer(), +): + """Duplicate the input dir to the output dir, fixing file method calls. + + Preconditions: + * in_dir is a real directory + * out_dir is a real, empty directory + """ + pyfile_gen = ( + pathlib.Path(os.path.join(root, f)) + for root, _, files in os.walk(in_dir) + for f in files if os.path.splitext(f)[1] == ".py" + ) + + for fpath in pyfile_gen: + with open(fpath, 'r') as f: + src = f.read() + + # Parse the code and insert method call fixes. + tree = cst.parse_module(src) + updated = tree.visit(transformer) + + # Create the path and directory structure for the new file. + updated_path = out_dir.joinpath(fpath.relative_to(in_dir)) + updated_path.parent.mkdir(parents=True, exist_ok=True) + + # Generate the updated source file at the corresponding path. + with open(updated_path, 'w') as f: + f.write(updated.code) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="""Fix up source that uses the texttospeech client library. + +The existing sources are NOT overwritten but are copied to output_dir with changes made. + +Note: This tool operates at a best-effort level at converting positional + parameters in client method calls to keyword based parameters. + Cases where it WILL FAIL include + A) * or ** expansion in a method call. + B) Calls via function or method alias (includes free function calls) + C) Indirect or dispatched calls (e.g. the method is looked up dynamically) + + These all constitute false negatives. The tool will also detect false + positives when an API method shares a name with another method. +""") + parser.add_argument( + '-d', + '--input-directory', + required=True, + dest='input_dir', + help='the input directory to walk for python files to fix up', + ) + parser.add_argument( + '-o', + '--output-directory', + required=True, + dest='output_dir', + help='the directory to output files fixed via un-flattening', + ) + args = parser.parse_args() + input_dir = pathlib.Path(args.input_dir) + output_dir = pathlib.Path(args.output_dir) + if not input_dir.is_dir(): + print( + f"input directory '{input_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if not output_dir.is_dir(): + print( + f"output directory '{output_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if os.listdir(output_dir): + print( + f"output directory '{output_dir}' is not empty", + file=sys.stderr, + ) + sys.exit(-1) + + fix_files(input_dir, output_dir) diff --git a/setup.py b/setup.py index fa759977..a9b882a7 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,11 @@ # 'Development Status :: 4 - Beta' # 'Development Status :: 5 - Production/Stable' release_status = "Development Status :: 5 - Production/Stable" -dependencies = ["google-api-core[grpc] >= 1.14.0, < 2.0.0dev"] +dependencies = [ + "google-api-core[grpc] >= 1.17.0, < 2.0.0dev", + "proto-plus >= 0.4.0", + "libcst >= 0.2.5", +] extras = {} @@ -56,7 +60,9 @@ # Only include packages under the 'google' namespace. Do not include tests, # benchmarks, etc. packages = [ - package for package in setuptools.find_packages() if package.startswith("google") + package + for package in setuptools.PEP420PackageFinder.find() + if package.startswith("google") ] # Determine which namespaces are needed. @@ -79,12 +85,10 @@ "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Operating System :: OS Independent", "Topic :: Internet", ], @@ -93,7 +97,8 @@ namespace_packages=namespaces, install_requires=dependencies, extras_require=extras, - python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*", + python_requires=">=3.6", + scripts=["scripts/fixup_keywords.py"], include_package_data=True, zip_safe=False, ) diff --git a/synth.metadata b/synth.metadata index e67b1b31..f3c65bcc 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,15 +4,15 @@ "git": { "name": ".", "remote": "git@github.com:googleapis/python-texttospeech", - "sha": "b54229fcc2bd1460c3f7f8207d125fd1379e56b1" + "sha": "b265df8e43ac71d22ee3bbdf96b5e3a457b9f956" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "89e89786896d256c70f43e68a975470c4f4f220e", - "internalRef": "311239362" + "sha": "eafa840ceec23b44a5c21670288107c661252711", + "internalRef": "313488995" } } ], @@ -23,7 +23,7 @@ "apiName": "texttospeech", "apiVersion": "v1beta1", "language": "python", - "generator": "bazel" + "generator": "gapic-generator-python" } }, { @@ -32,7 +32,7 @@ "apiName": "texttospeech", "apiVersion": "v1", "language": "python", - "generator": "bazel" + "generator": "gapic-generator-python" } } ] diff --git a/synth.py b/synth.py index 1b8ac736..7b11e286 100644 --- a/synth.py +++ b/synth.py @@ -19,7 +19,7 @@ from synthtool import gcp from synthtool.languages import python -gapic = gcp.GAPICBazel() +gapic = gcp.GAPICMicrogenerator() common = gcp.CommonTemplates() versions = ["v1beta1", "v1"] @@ -27,31 +27,34 @@ # Generate texttospeech GAPIC layer # ---------------------------------------------------------------------------- for version in versions: - library = gapic.py_library( - service="texttospeech", - version=version, - bazel_target=f"//google/cloud/texttospeech/{version}:texttospeech-{version}-py", - include_protos=True, - ) - s.move(library / f"google/cloud/texttospeech_{version}") - s.move(library / f"tests/unit/gapic/{version}") - s.move(library / f"docs/gapic/{version}") - -# Use the highest version library to generate import alias. -s.move(library / "google/cloud/texttospeech.py") - -# Fix bad docstrings. -s.replace("**/gapic/*_client.py", r'\\"(.+?)-\*\\"', r'"\1-\\*"') + library = gapic.py_library(service="texttospeech", version=version,) + s.move(library, excludes=["setup.py", "docs/index.rst"]) + +# Sphinx interprets `*` as emphasis +s.replace( + ["google/cloud/**/client.py", "google/cloud/**/cloud_tts.py"], + "((en)|(no)|(nb)(cmn)|(yue))-\*", + "\g<1>-\*", +) # ---------------------------------------------------------------------------- # Add templated files # ---------------------------------------------------------------------------- -templated_files = common.py_library(unit_cov_level=85, cov_level=85) -s.move(templated_files) +templated_files = common.py_library( + cov_level=100, + samples=True, + unit_test_python_versions=["3.6", "3.7", "3.8"], + system_test_python_versions=["3.7"], +) +s.move(templated_files, excludes=[".coveragerc"]) # microgenerator has a good .coveragerc file # ---------------------------------------------------------------------------- # Samples templates # ---------------------------------------------------------------------------- -python.py_samples() +python.py_samples(skip_readmes=True) + +# Extra lint ignores for microgenerator tests +# TODO: Remove when https://github.com/googleapis/gapic-generator-python/issues/425 is closed +s.replace(".flake8", "(ignore = .*)", "\g<1>, F401, F841") s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/tests/system/v1/test_system_tts_v1.py b/tests/system/v1/test_system_tts_v1.py deleted file mode 100644 index 4d90bae5..00000000 --- a/tests/system/v1/test_system_tts_v1.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2019 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. - -from google.cloud import texttospeech_v1 - - -class TestSystemSpeech(object): - def test_synthesize_speech(self): - client = texttospeech_v1.TextToSpeechClient() - - synthesis_input = texttospeech_v1.types.SynthesisInput(text="Hello, World!") - voice = texttospeech_v1.types.VoiceSelectionParams( - language_code="en-US", - ssml_gender=texttospeech_v1.enums.SsmlVoiceGender.NEUTRAL, - ) - audio_config = texttospeech_v1.types.AudioConfig( - audio_encoding=texttospeech_v1.enums.AudioEncoding.MP3 - ) - - response = client.synthesize_speech(synthesis_input, voice, audio_config) - assert response.audio_content is not None - - def test_list_voices(self): - client = texttospeech_v1.TextToSpeechClient() - - voices = client.list_voices() - assert len(voices.voices) > 0 diff --git a/tests/system/v1beta1/test_system_tts_v1beta1.py b/tests/system/v1beta1/test_system_tts_v1beta1.py deleted file mode 100644 index c6058acf..00000000 --- a/tests/system/v1beta1/test_system_tts_v1beta1.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2019 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. - -from google.cloud import texttospeech_v1beta1 - - -class TestSystemSpeech(object): - def test_synthesize_speech(self): - client = texttospeech_v1beta1.TextToSpeechClient() - - synthesis_input = texttospeech_v1beta1.types.SynthesisInput( - text="Hello, World!" - ) - voice = texttospeech_v1beta1.types.VoiceSelectionParams( - language_code="en-US", - ssml_gender=texttospeech_v1beta1.enums.SsmlVoiceGender.NEUTRAL, - ) - audio_config = texttospeech_v1beta1.types.AudioConfig( - audio_encoding=texttospeech_v1beta1.enums.AudioEncoding.MP3 - ) - - response = client.synthesize_speech(synthesis_input, voice, audio_config) - assert response.audio_content is not None - - def test_list_voices(self): - client = texttospeech_v1beta1.TextToSpeechClient() - - voices = client.list_voices() - assert len(voices.voices) > 0 diff --git a/tests/unit/gapic/v1/test_text_to_speech_client_v1.py b/tests/unit/gapic/v1/test_text_to_speech_client_v1.py deleted file mode 100644 index c0c2c5a9..00000000 --- a/tests/unit/gapic/v1/test_text_to_speech_client_v1.py +++ /dev/null @@ -1,136 +0,0 @@ -# -*- 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. - -"""Unit tests.""" - -import mock -import pytest - -from google.cloud import texttospeech_v1 -from google.cloud.texttospeech_v1.proto import cloud_tts_pb2 - - -class MultiCallableStub(object): - """Stub for the grpc.UnaryUnaryMultiCallable interface.""" - - def __init__(self, method, channel_stub): - self.method = method - self.channel_stub = channel_stub - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - self.channel_stub.requests.append((self.method, request)) - - response = None - if self.channel_stub.responses: - response = self.channel_stub.responses.pop() - - if isinstance(response, Exception): - raise response - - if response: - return response - - -class ChannelStub(object): - """Stub for the grpc.Channel interface.""" - - def __init__(self, responses=[]): - self.responses = responses - self.requests = [] - - def unary_unary(self, method, request_serializer=None, response_deserializer=None): - return MultiCallableStub(method, self) - - -class CustomException(Exception): - pass - - -class TestTextToSpeechClient(object): - def test_list_voices(self): - # Setup Expected Response - expected_response = {} - expected_response = cloud_tts_pb2.ListVoicesResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = texttospeech_v1.TextToSpeechClient() - - response = client.list_voices() - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = cloud_tts_pb2.ListVoicesRequest() - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_voices_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = texttospeech_v1.TextToSpeechClient() - - with pytest.raises(CustomException): - client.list_voices() - - def test_synthesize_speech(self): - # Setup Expected Response - audio_content = b"16" - expected_response = {"audio_content": audio_content} - expected_response = cloud_tts_pb2.SynthesizeSpeechResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = texttospeech_v1.TextToSpeechClient() - - # Setup Request - input_ = {} - voice = {} - audio_config = {} - - response = client.synthesize_speech(input_, voice, audio_config) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = cloud_tts_pb2.SynthesizeSpeechRequest( - input=input_, voice=voice, audio_config=audio_config - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_synthesize_speech_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = texttospeech_v1.TextToSpeechClient() - - # Setup request - input_ = {} - voice = {} - audio_config = {} - - with pytest.raises(CustomException): - client.synthesize_speech(input_, voice, audio_config) diff --git a/tests/unit/gapic/v1beta1/test_text_to_speech_client_v1beta1.py b/tests/unit/gapic/v1beta1/test_text_to_speech_client_v1beta1.py deleted file mode 100644 index 52344757..00000000 --- a/tests/unit/gapic/v1beta1/test_text_to_speech_client_v1beta1.py +++ /dev/null @@ -1,136 +0,0 @@ -# -*- 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. - -"""Unit tests.""" - -import mock -import pytest - -from google.cloud import texttospeech_v1beta1 -from google.cloud.texttospeech_v1beta1.proto import cloud_tts_pb2 - - -class MultiCallableStub(object): - """Stub for the grpc.UnaryUnaryMultiCallable interface.""" - - def __init__(self, method, channel_stub): - self.method = method - self.channel_stub = channel_stub - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - self.channel_stub.requests.append((self.method, request)) - - response = None - if self.channel_stub.responses: - response = self.channel_stub.responses.pop() - - if isinstance(response, Exception): - raise response - - if response: - return response - - -class ChannelStub(object): - """Stub for the grpc.Channel interface.""" - - def __init__(self, responses=[]): - self.responses = responses - self.requests = [] - - def unary_unary(self, method, request_serializer=None, response_deserializer=None): - return MultiCallableStub(method, self) - - -class CustomException(Exception): - pass - - -class TestTextToSpeechClient(object): - def test_list_voices(self): - # Setup Expected Response - expected_response = {} - expected_response = cloud_tts_pb2.ListVoicesResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = texttospeech_v1beta1.TextToSpeechClient() - - response = client.list_voices() - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = cloud_tts_pb2.ListVoicesRequest() - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_voices_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = texttospeech_v1beta1.TextToSpeechClient() - - with pytest.raises(CustomException): - client.list_voices() - - def test_synthesize_speech(self): - # Setup Expected Response - audio_content = b"16" - expected_response = {"audio_content": audio_content} - expected_response = cloud_tts_pb2.SynthesizeSpeechResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = texttospeech_v1beta1.TextToSpeechClient() - - # Setup Request - input_ = {} - voice = {} - audio_config = {} - - response = client.synthesize_speech(input_, voice, audio_config) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = cloud_tts_pb2.SynthesizeSpeechRequest( - input=input_, voice=voice, audio_config=audio_config - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_synthesize_speech_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = texttospeech_v1beta1.TextToSpeechClient() - - # Setup request - input_ = {} - voice = {} - audio_config = {} - - with pytest.raises(CustomException): - client.synthesize_speech(input_, voice, audio_config) diff --git a/google/cloud/texttospeech_v1/gapic/__init__.py b/tests/unit/texttospeech_v1/__init__.py similarity index 100% rename from google/cloud/texttospeech_v1/gapic/__init__.py rename to tests/unit/texttospeech_v1/__init__.py diff --git a/tests/unit/texttospeech_v1/test_text_to_speech.py b/tests/unit/texttospeech_v1/test_text_to_speech.py new file mode 100644 index 00000000..6ed9e648 --- /dev/null +++ b/tests/unit/texttospeech_v1/test_text_to_speech.py @@ -0,0 +1,453 @@ +# -*- 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. +# + +from unittest import mock + +import grpc +import math +import pytest + +from google import auth +from google.api_core import client_options +from google.api_core import grpc_helpers +from google.auth import credentials +from google.cloud.texttospeech_v1.services.text_to_speech import TextToSpeechClient +from google.cloud.texttospeech_v1.services.text_to_speech import transports +from google.cloud.texttospeech_v1.types import cloud_tts +from google.oauth2 import service_account + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert TextToSpeechClient._get_default_mtls_endpoint(None) is None + assert ( + TextToSpeechClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint + ) + assert ( + TextToSpeechClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + TextToSpeechClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + TextToSpeechClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert TextToSpeechClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi + + +def test_text_to_speech_client_from_service_account_file(): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + factory.return_value = creds + client = TextToSpeechClient.from_service_account_file("dummy/file/path.json") + assert client._transport._credentials == creds + + client = TextToSpeechClient.from_service_account_json("dummy/file/path.json") + assert client._transport._credentials == creds + + assert client._transport._host == "texttospeech.googleapis.com:443" + + +def test_text_to_speech_client_client_options(): + # Check that if channel is provided we won't create a new one. + with mock.patch( + "google.cloud.texttospeech_v1.services.text_to_speech.TextToSpeechClient.get_transport_class" + ) as gtc: + transport = transports.TextToSpeechGrpcTransport( + credentials=credentials.AnonymousCredentials() + ) + client = TextToSpeechClient(transport=transport) + gtc.assert_not_called() + + # Check mTLS is not triggered with empty client options. + options = client_options.ClientOptions() + with mock.patch( + "google.cloud.texttospeech_v1.services.text_to_speech.TextToSpeechClient.get_transport_class" + ) as gtc: + transport = gtc.return_value = mock.MagicMock() + client = TextToSpeechClient(client_options=options) + transport.assert_called_once_with( + credentials=None, host=client.DEFAULT_ENDPOINT + ) + + # Check mTLS is not triggered if api_endpoint is provided but + # client_cert_source is None. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + with mock.patch( + "google.cloud.texttospeech_v1.services.text_to_speech.transports.TextToSpeechGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = TextToSpeechClient(client_options=options) + grpc_transport.assert_called_once_with( + api_mtls_endpoint=None, + client_cert_source=None, + credentials=None, + host="squid.clam.whelk", + ) + + # Check mTLS is triggered if client_cert_source is provided. + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch( + "google.cloud.texttospeech_v1.services.text_to_speech.transports.TextToSpeechGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = TextToSpeechClient(client_options=options) + grpc_transport.assert_called_once_with( + api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, + client_cert_source=client_cert_source_callback, + credentials=None, + host=client.DEFAULT_ENDPOINT, + ) + + # Check mTLS is triggered if api_endpoint and client_cert_source are provided. + options = client_options.ClientOptions( + api_endpoint="squid.clam.whelk", client_cert_source=client_cert_source_callback + ) + with mock.patch( + "google.cloud.texttospeech_v1.services.text_to_speech.transports.TextToSpeechGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = TextToSpeechClient(client_options=options) + grpc_transport.assert_called_once_with( + api_mtls_endpoint="squid.clam.whelk", + client_cert_source=client_cert_source_callback, + credentials=None, + host="squid.clam.whelk", + ) + + +def test_text_to_speech_client_client_options_from_dict(): + with mock.patch( + "google.cloud.texttospeech_v1.services.text_to_speech.transports.TextToSpeechGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = TextToSpeechClient(client_options={"api_endpoint": "squid.clam.whelk"}) + grpc_transport.assert_called_once_with( + api_mtls_endpoint=None, + client_cert_source=None, + credentials=None, + host="squid.clam.whelk", + ) + + +def test_list_voices(transport: str = "grpc"): + client = TextToSpeechClient( + 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 = cloud_tts.ListVoicesRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.list_voices), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = cloud_tts.ListVoicesResponse() + + response = client.list_voices(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 response is the type that we expect. + assert isinstance(response, cloud_tts.ListVoicesResponse) + + +def test_list_voices_flattened(): + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.list_voices), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = cloud_tts.ListVoicesResponse() + + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = client.list_voices(language_code="language_code_value") + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].language_code == "language_code_value" + + +def test_list_voices_flattened_error(): + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_voices( + cloud_tts.ListVoicesRequest(), language_code="language_code_value" + ) + + +def test_synthesize_speech(transport: str = "grpc"): + client = TextToSpeechClient( + 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 = cloud_tts.SynthesizeSpeechRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._transport.synthesize_speech), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = cloud_tts.SynthesizeSpeechResponse( + audio_content=b"audio_content_blob" + ) + + response = client.synthesize_speech(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 response is the type that we expect. + assert isinstance(response, cloud_tts.SynthesizeSpeechResponse) + assert response.audio_content == b"audio_content_blob" + + +def test_synthesize_speech_flattened(): + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._transport.synthesize_speech), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = cloud_tts.SynthesizeSpeechResponse() + + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = client.synthesize_speech( + input=cloud_tts.SynthesisInput(text="text_value"), + voice=cloud_tts.VoiceSelectionParams(language_code="language_code_value"), + audio_config=cloud_tts.AudioConfig( + audio_encoding=cloud_tts.AudioEncoding.LINEAR16 + ), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].input == cloud_tts.SynthesisInput(text="text_value") + assert args[0].voice == cloud_tts.VoiceSelectionParams( + language_code="language_code_value" + ) + assert args[0].audio_config == cloud_tts.AudioConfig( + audio_encoding=cloud_tts.AudioEncoding.LINEAR16 + ) + + +def test_synthesize_speech_flattened_error(): + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.synthesize_speech( + cloud_tts.SynthesizeSpeechRequest(), + input=cloud_tts.SynthesisInput(text="text_value"), + voice=cloud_tts.VoiceSelectionParams(language_code="language_code_value"), + audio_config=cloud_tts.AudioConfig( + audio_encoding=cloud_tts.AudioEncoding.LINEAR16 + ), + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.TextToSpeechGrpcTransport( + credentials=credentials.AnonymousCredentials() + ) + with pytest.raises(ValueError): + client = TextToSpeechClient( + credentials=credentials.AnonymousCredentials(), transport=transport + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.TextToSpeechGrpcTransport( + credentials=credentials.AnonymousCredentials() + ) + client = TextToSpeechClient(transport=transport) + assert client._transport is transport + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + assert isinstance(client._transport, transports.TextToSpeechGrpcTransport) + + +def test_text_to_speech_base_transport(): + # Instantiate the base transport. + transport = transports.TextToSpeechTransport( + credentials=credentials.AnonymousCredentials() + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ("list_voices", "synthesize_speech") + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + +def test_text_to_speech_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + TextToSpeechClient() + adc.assert_called_once_with( + scopes=("https://www.googleapis.com/auth/cloud-platform",) + ) + + +def test_text_to_speech_host_no_port(): + client = TextToSpeechClient( + credentials=credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="texttospeech.googleapis.com" + ), + transport="grpc", + ) + assert client._transport._host == "texttospeech.googleapis.com:443" + + +def test_text_to_speech_host_with_port(): + client = TextToSpeechClient( + credentials=credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="texttospeech.googleapis.com:8000" + ), + transport="grpc", + ) + assert client._transport._host == "texttospeech.googleapis.com:8000" + + +def test_text_to_speech_grpc_transport_channel(): + channel = grpc.insecure_channel("http://localhost/") + + # Check that if channel is provided, mtls endpoint and client_cert_source + # won't be used. + callback = mock.MagicMock() + transport = transports.TextToSpeechGrpcTransport( + host="squid.clam.whelk", + channel=channel, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=callback, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert not callback.called + + +@mock.patch("grpc.ssl_channel_credentials", autospec=True) +@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) +def test_text_to_speech_grpc_transport_channel_mtls_with_client_cert_source( + grpc_create_channel, grpc_ssl_channel_cred +): + # Check that if channel is None, but api_mtls_endpoint and client_cert_source + # are provided, then a mTLS channel will be created. + mock_cred = mock.Mock() + + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + transport = transports.TextToSpeechGrpcTransport( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + ssl_credentials=mock_ssl_cred, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ) + assert transport.grpc_channel == mock_grpc_channel + + +@pytest.mark.parametrize( + "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] +) +@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) +def test_text_to_speech_grpc_transport_channel_mtls_with_adc( + grpc_create_channel, api_mtls_endpoint +): + # Check that if channel and client_cert_source are None, but api_mtls_endpoint + # is provided, then a mTLS channel will be created with SSL ADC. + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + # Mock google.auth.transport.grpc.SslCredentials class. + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + mock_cred = mock.Mock() + transport = transports.TextToSpeechGrpcTransport( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint=api_mtls_endpoint, + client_cert_source=None, + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + ssl_credentials=mock_ssl_cred, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ) + assert transport.grpc_channel == mock_grpc_channel diff --git a/google/cloud/texttospeech_v1/gapic/transports/__init__.py b/tests/unit/texttospeech_v1beta1/__init__.py similarity index 100% rename from google/cloud/texttospeech_v1/gapic/transports/__init__.py rename to tests/unit/texttospeech_v1beta1/__init__.py diff --git a/tests/unit/texttospeech_v1beta1/test_text_to_speech.py b/tests/unit/texttospeech_v1beta1/test_text_to_speech.py new file mode 100644 index 00000000..4441be4f --- /dev/null +++ b/tests/unit/texttospeech_v1beta1/test_text_to_speech.py @@ -0,0 +1,453 @@ +# -*- 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. +# + +from unittest import mock + +import grpc +import math +import pytest + +from google import auth +from google.api_core import client_options +from google.api_core import grpc_helpers +from google.auth import credentials +from google.cloud.texttospeech_v1beta1.services.text_to_speech import TextToSpeechClient +from google.cloud.texttospeech_v1beta1.services.text_to_speech import transports +from google.cloud.texttospeech_v1beta1.types import cloud_tts +from google.oauth2 import service_account + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert TextToSpeechClient._get_default_mtls_endpoint(None) is None + assert ( + TextToSpeechClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint + ) + assert ( + TextToSpeechClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + TextToSpeechClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + TextToSpeechClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert TextToSpeechClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi + + +def test_text_to_speech_client_from_service_account_file(): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + factory.return_value = creds + client = TextToSpeechClient.from_service_account_file("dummy/file/path.json") + assert client._transport._credentials == creds + + client = TextToSpeechClient.from_service_account_json("dummy/file/path.json") + assert client._transport._credentials == creds + + assert client._transport._host == "texttospeech.googleapis.com:443" + + +def test_text_to_speech_client_client_options(): + # Check that if channel is provided we won't create a new one. + with mock.patch( + "google.cloud.texttospeech_v1beta1.services.text_to_speech.TextToSpeechClient.get_transport_class" + ) as gtc: + transport = transports.TextToSpeechGrpcTransport( + credentials=credentials.AnonymousCredentials() + ) + client = TextToSpeechClient(transport=transport) + gtc.assert_not_called() + + # Check mTLS is not triggered with empty client options. + options = client_options.ClientOptions() + with mock.patch( + "google.cloud.texttospeech_v1beta1.services.text_to_speech.TextToSpeechClient.get_transport_class" + ) as gtc: + transport = gtc.return_value = mock.MagicMock() + client = TextToSpeechClient(client_options=options) + transport.assert_called_once_with( + credentials=None, host=client.DEFAULT_ENDPOINT + ) + + # Check mTLS is not triggered if api_endpoint is provided but + # client_cert_source is None. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + with mock.patch( + "google.cloud.texttospeech_v1beta1.services.text_to_speech.transports.TextToSpeechGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = TextToSpeechClient(client_options=options) + grpc_transport.assert_called_once_with( + api_mtls_endpoint=None, + client_cert_source=None, + credentials=None, + host="squid.clam.whelk", + ) + + # Check mTLS is triggered if client_cert_source is provided. + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch( + "google.cloud.texttospeech_v1beta1.services.text_to_speech.transports.TextToSpeechGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = TextToSpeechClient(client_options=options) + grpc_transport.assert_called_once_with( + api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, + client_cert_source=client_cert_source_callback, + credentials=None, + host=client.DEFAULT_ENDPOINT, + ) + + # Check mTLS is triggered if api_endpoint and client_cert_source are provided. + options = client_options.ClientOptions( + api_endpoint="squid.clam.whelk", client_cert_source=client_cert_source_callback + ) + with mock.patch( + "google.cloud.texttospeech_v1beta1.services.text_to_speech.transports.TextToSpeechGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = TextToSpeechClient(client_options=options) + grpc_transport.assert_called_once_with( + api_mtls_endpoint="squid.clam.whelk", + client_cert_source=client_cert_source_callback, + credentials=None, + host="squid.clam.whelk", + ) + + +def test_text_to_speech_client_client_options_from_dict(): + with mock.patch( + "google.cloud.texttospeech_v1beta1.services.text_to_speech.transports.TextToSpeechGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = TextToSpeechClient(client_options={"api_endpoint": "squid.clam.whelk"}) + grpc_transport.assert_called_once_with( + api_mtls_endpoint=None, + client_cert_source=None, + credentials=None, + host="squid.clam.whelk", + ) + + +def test_list_voices(transport: str = "grpc"): + client = TextToSpeechClient( + 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 = cloud_tts.ListVoicesRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.list_voices), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = cloud_tts.ListVoicesResponse() + + response = client.list_voices(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 response is the type that we expect. + assert isinstance(response, cloud_tts.ListVoicesResponse) + + +def test_list_voices_flattened(): + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client._transport.list_voices), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = cloud_tts.ListVoicesResponse() + + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = client.list_voices(language_code="language_code_value") + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].language_code == "language_code_value" + + +def test_list_voices_flattened_error(): + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_voices( + cloud_tts.ListVoicesRequest(), language_code="language_code_value" + ) + + +def test_synthesize_speech(transport: str = "grpc"): + client = TextToSpeechClient( + 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 = cloud_tts.SynthesizeSpeechRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._transport.synthesize_speech), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = cloud_tts.SynthesizeSpeechResponse( + audio_content=b"audio_content_blob" + ) + + response = client.synthesize_speech(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 response is the type that we expect. + assert isinstance(response, cloud_tts.SynthesizeSpeechResponse) + assert response.audio_content == b"audio_content_blob" + + +def test_synthesize_speech_flattened(): + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client._transport.synthesize_speech), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = cloud_tts.SynthesizeSpeechResponse() + + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = client.synthesize_speech( + input=cloud_tts.SynthesisInput(text="text_value"), + voice=cloud_tts.VoiceSelectionParams(language_code="language_code_value"), + audio_config=cloud_tts.AudioConfig( + audio_encoding=cloud_tts.AudioEncoding.LINEAR16 + ), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].input == cloud_tts.SynthesisInput(text="text_value") + assert args[0].voice == cloud_tts.VoiceSelectionParams( + language_code="language_code_value" + ) + assert args[0].audio_config == cloud_tts.AudioConfig( + audio_encoding=cloud_tts.AudioEncoding.LINEAR16 + ) + + +def test_synthesize_speech_flattened_error(): + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.synthesize_speech( + cloud_tts.SynthesizeSpeechRequest(), + input=cloud_tts.SynthesisInput(text="text_value"), + voice=cloud_tts.VoiceSelectionParams(language_code="language_code_value"), + audio_config=cloud_tts.AudioConfig( + audio_encoding=cloud_tts.AudioEncoding.LINEAR16 + ), + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.TextToSpeechGrpcTransport( + credentials=credentials.AnonymousCredentials() + ) + with pytest.raises(ValueError): + client = TextToSpeechClient( + credentials=credentials.AnonymousCredentials(), transport=transport + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.TextToSpeechGrpcTransport( + credentials=credentials.AnonymousCredentials() + ) + client = TextToSpeechClient(transport=transport) + assert client._transport is transport + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = TextToSpeechClient(credentials=credentials.AnonymousCredentials()) + assert isinstance(client._transport, transports.TextToSpeechGrpcTransport) + + +def test_text_to_speech_base_transport(): + # Instantiate the base transport. + transport = transports.TextToSpeechTransport( + credentials=credentials.AnonymousCredentials() + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ("list_voices", "synthesize_speech") + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + +def test_text_to_speech_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + TextToSpeechClient() + adc.assert_called_once_with( + scopes=("https://www.googleapis.com/auth/cloud-platform",) + ) + + +def test_text_to_speech_host_no_port(): + client = TextToSpeechClient( + credentials=credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="texttospeech.googleapis.com" + ), + transport="grpc", + ) + assert client._transport._host == "texttospeech.googleapis.com:443" + + +def test_text_to_speech_host_with_port(): + client = TextToSpeechClient( + credentials=credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="texttospeech.googleapis.com:8000" + ), + transport="grpc", + ) + assert client._transport._host == "texttospeech.googleapis.com:8000" + + +def test_text_to_speech_grpc_transport_channel(): + channel = grpc.insecure_channel("http://localhost/") + + # Check that if channel is provided, mtls endpoint and client_cert_source + # won't be used. + callback = mock.MagicMock() + transport = transports.TextToSpeechGrpcTransport( + host="squid.clam.whelk", + channel=channel, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=callback, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert not callback.called + + +@mock.patch("grpc.ssl_channel_credentials", autospec=True) +@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) +def test_text_to_speech_grpc_transport_channel_mtls_with_client_cert_source( + grpc_create_channel, grpc_ssl_channel_cred +): + # Check that if channel is None, but api_mtls_endpoint and client_cert_source + # are provided, then a mTLS channel will be created. + mock_cred = mock.Mock() + + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + transport = transports.TextToSpeechGrpcTransport( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + ssl_credentials=mock_ssl_cred, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ) + assert transport.grpc_channel == mock_grpc_channel + + +@pytest.mark.parametrize( + "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] +) +@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) +def test_text_to_speech_grpc_transport_channel_mtls_with_adc( + grpc_create_channel, api_mtls_endpoint +): + # Check that if channel and client_cert_source are None, but api_mtls_endpoint + # is provided, then a mTLS channel will be created with SSL ADC. + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + # Mock google.auth.transport.grpc.SslCredentials class. + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + mock_cred = mock.Mock() + transport = transports.TextToSpeechGrpcTransport( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint=api_mtls_endpoint, + client_cert_source=None, + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + ssl_credentials=mock_ssl_cred, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ) + assert transport.grpc_channel == mock_grpc_channel