diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index ae6c57fad..7519fa3a2 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest - digest: sha256:82b12321da4446a73cb11bcb6812fbec8c105abda3946d46e6394e5fbfb64c0f + digest: sha256:0e18b9475fbeb12d9ad4302283171edebb6baf2dfca1bd215ee3b34ed79d95d7 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 30c3973aa..b26afefdc 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,9 +3,10 @@ # # For syntax help see: # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax +# Note: This file is autogenerated. To make changes to the codeowner team, please update .repo-metadata.json. -# The @googleapis/yoshi-python is the default owner for changes in this repo -* @googleapis/yoshi-python +# @googleapis/yoshi-python @googleapis/cdpe-cloudai are the default owners for changes in this repo +* @googleapis/yoshi-python @googleapis/cdpe-cloudai -# The python-samples-reviewers team is the default owner for samples changes -/samples/ @googleapis/python-samples-owners \ No newline at end of file +# @googleapis/python-samples-owners @googleapis/cdpe-cloudai are the default owners for samples changes +/samples/ @googleapis/python-samples-owners @googleapis/cdpe-cloudai diff --git a/.kokoro/docs/common.cfg b/.kokoro/docs/common.cfg index d03febf04..0fae31785 100644 --- a/.kokoro/docs/common.cfg +++ b/.kokoro/docs/common.cfg @@ -30,6 +30,7 @@ env_vars: { env_vars: { key: "V2_STAGING_BUCKET" + # Push google cloud library docs to the Cloud RAD bucket `docs-staging-v2` value: "docs-staging-v2" } diff --git a/.kokoro/samples/lint/common.cfg b/.kokoro/samples/lint/common.cfg index 5879caec3..ce74881d7 100644 --- a/.kokoro/samples/lint/common.cfg +++ b/.kokoro/samples/lint/common.cfg @@ -31,4 +31,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" # Use the trampoline script to run in docker. -build_file: "python-dialogflow/.kokoro/trampoline.sh" \ No newline at end of file +build_file: "python-dialogflow/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.10/common.cfg b/.kokoro/samples/python3.10/common.cfg new file mode 100644 index 000000000..6fff3d5a1 --- /dev/null +++ b/.kokoro/samples/python3.10/common.cfg @@ -0,0 +1,40 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + } +} + +# Specify which tests to run +env_vars: { + key: "RUN_TESTS_SESSION" + value: "py-3.10" +} + +# Declare build specific Cloud project. +env_vars: { + key: "BUILD_SPECIFIC_GCLOUD_PROJECT" + value: "python-docs-samples-tests-310" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-dialogflow/.kokoro/test-samples.sh" +} + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/python-samples-testing-docker" +} + +# Download secrets for samples +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "python-dialogflow/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.10/continuous.cfg b/.kokoro/samples/python3.10/continuous.cfg new file mode 100644 index 000000000..a1c8d9759 --- /dev/null +++ b/.kokoro/samples/python3.10/continuous.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} \ No newline at end of file diff --git a/.kokoro/samples/python3.10/periodic-head.cfg b/.kokoro/samples/python3.10/periodic-head.cfg new file mode 100644 index 000000000..82ba99956 --- /dev/null +++ b/.kokoro/samples/python3.10/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-dialogflow/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.10/periodic.cfg b/.kokoro/samples/python3.10/periodic.cfg new file mode 100644 index 000000000..71cd1e597 --- /dev/null +++ b/.kokoro/samples/python3.10/periodic.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "False" +} diff --git a/.kokoro/samples/python3.10/presubmit.cfg b/.kokoro/samples/python3.10/presubmit.cfg new file mode 100644 index 000000000..a1c8d9759 --- /dev/null +++ b/.kokoro/samples/python3.10/presubmit.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} \ No newline at end of file diff --git a/.kokoro/samples/python3.6/common.cfg b/.kokoro/samples/python3.6/common.cfg index e3daafd4b..26b7eaf81 100644 --- a/.kokoro/samples/python3.6/common.cfg +++ b/.kokoro/samples/python3.6/common.cfg @@ -37,4 +37,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" # Use the trampoline script to run in docker. -build_file: "python-dialogflow/.kokoro/trampoline.sh" \ No newline at end of file +build_file: "python-dialogflow/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.6/periodic.cfg b/.kokoro/samples/python3.6/periodic.cfg index 50fec9649..71cd1e597 100644 --- a/.kokoro/samples/python3.6/periodic.cfg +++ b/.kokoro/samples/python3.6/periodic.cfg @@ -3,4 +3,4 @@ env_vars: { key: "INSTALL_LIBRARY_FROM_SOURCE" value: "False" -} \ No newline at end of file +} diff --git a/.kokoro/samples/python3.7/common.cfg b/.kokoro/samples/python3.7/common.cfg index e7a49f99c..aff8e7859 100644 --- a/.kokoro/samples/python3.7/common.cfg +++ b/.kokoro/samples/python3.7/common.cfg @@ -37,4 +37,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" # Use the trampoline script to run in docker. -build_file: "python-dialogflow/.kokoro/trampoline.sh" \ No newline at end of file +build_file: "python-dialogflow/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.7/periodic.cfg b/.kokoro/samples/python3.7/periodic.cfg index 50fec9649..71cd1e597 100644 --- a/.kokoro/samples/python3.7/periodic.cfg +++ b/.kokoro/samples/python3.7/periodic.cfg @@ -3,4 +3,4 @@ env_vars: { key: "INSTALL_LIBRARY_FROM_SOURCE" value: "False" -} \ No newline at end of file +} diff --git a/.kokoro/samples/python3.8/common.cfg b/.kokoro/samples/python3.8/common.cfg index ff4f743a8..c45720f75 100644 --- a/.kokoro/samples/python3.8/common.cfg +++ b/.kokoro/samples/python3.8/common.cfg @@ -37,4 +37,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" # Use the trampoline script to run in docker. -build_file: "python-dialogflow/.kokoro/trampoline.sh" \ No newline at end of file +build_file: "python-dialogflow/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.8/periodic.cfg b/.kokoro/samples/python3.8/periodic.cfg index 50fec9649..71cd1e597 100644 --- a/.kokoro/samples/python3.8/periodic.cfg +++ b/.kokoro/samples/python3.8/periodic.cfg @@ -3,4 +3,4 @@ env_vars: { key: "INSTALL_LIBRARY_FROM_SOURCE" value: "False" -} \ No newline at end of file +} diff --git a/.kokoro/samples/python3.9/common.cfg b/.kokoro/samples/python3.9/common.cfg index f0464f72e..bb76c80fb 100644 --- a/.kokoro/samples/python3.9/common.cfg +++ b/.kokoro/samples/python3.9/common.cfg @@ -37,4 +37,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" # Use the trampoline script to run in docker. -build_file: "python-dialogflow/.kokoro/trampoline.sh" \ No newline at end of file +build_file: "python-dialogflow/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.9/periodic.cfg b/.kokoro/samples/python3.9/periodic.cfg index 50fec9649..71cd1e597 100644 --- a/.kokoro/samples/python3.9/periodic.cfg +++ b/.kokoro/samples/python3.9/periodic.cfg @@ -3,4 +3,4 @@ env_vars: { key: "INSTALL_LIBRARY_FROM_SOURCE" value: "False" -} \ No newline at end of file +} diff --git a/.kokoro/test-samples-against-head.sh b/.kokoro/test-samples-against-head.sh index 3187ad1e3..ba3a707b0 100755 --- a/.kokoro/test-samples-against-head.sh +++ b/.kokoro/test-samples-against-head.sh @@ -23,6 +23,4 @@ set -eo pipefail # Enables `**` to include files nested inside sub-folders shopt -s globstar -cd github/python-dialogflow - exec .kokoro/test-samples-impl.sh diff --git a/.kokoro/test-samples.sh b/.kokoro/test-samples.sh index 7f72ef5d1..11c042d34 100755 --- a/.kokoro/test-samples.sh +++ b/.kokoro/test-samples.sh @@ -24,8 +24,6 @@ set -eo pipefail # Enables `**` to include files nested inside sub-folders shopt -s globstar -cd github/python-dialogflow - # Run periodic samples tests at latest release if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then # preserving the test runner implementation. diff --git a/.repo-metadata.json b/.repo-metadata.json index e224ee80a..b8b9fc04a 100644 --- a/.repo-metadata.json +++ b/.repo-metadata.json @@ -1,14 +1,16 @@ { - "name": "dialogflow", - "name_pretty": "Dialogflow", - "product_documentation": "https://www.dialogflow.com/", - "client_documentation": "https://googleapis.dev/python/dialogflow/latest", - "issue_tracker": "https://issuetracker.google.com/savedsearches/5300385", - "release_level": "ga", - "language": "python", - "library_type": "GAPIC_AUTO", - "repo": "googleapis/python-dialogflow", - "distribution_name": "google-cloud-dialogflow", - "api_id": "dialogflow.googleapis.com", - "requires_billing": true -} \ No newline at end of file + "name": "dialogflow", + "name_pretty": "Dialogflow", + "product_documentation": "https://www.dialogflow.com/", + "client_documentation": "https://googleapis.dev/python/dialogflow/latest", + "issue_tracker": "https://issuetracker.google.com/savedsearches/5300385", + "release_level": "ga", + "language": "python", + "library_type": "GAPIC_AUTO", + "repo": "googleapis/python-dialogflow", + "distribution_name": "google-cloud-dialogflow", + "api_id": "dialogflow.googleapis.com", + "requires_billing": true, + "default_version": "v2", + "codeowner_team": "@googleapis/cdpe-cloudai" +} diff --git a/.trampolinerc b/.trampolinerc index 383b6ec89..0eee72ab6 100644 --- a/.trampolinerc +++ b/.trampolinerc @@ -16,15 +16,26 @@ # Add required env vars here. required_envvars+=( - "STAGING_BUCKET" - "V2_STAGING_BUCKET" ) # Add env vars which are passed down into the container here. pass_down_envvars+=( + "NOX_SESSION" + ############### + # Docs builds + ############### "STAGING_BUCKET" "V2_STAGING_BUCKET" - "NOX_SESSION" + ################## + # Samples builds + ################## + "INSTALL_LIBRARY_FROM_SOURCE" + "RUN_TESTS_SESSION" + "BUILD_SPECIFIC_GCLOUD_PROJECT" + # Target directories. + "RUN_TESTS_DIRS" + # The nox session to run. + "RUN_TESTS_SESSION" ) # Prevent unintentional override on the default image. diff --git a/CHANGELOG.md b/CHANGELOG.md index 795396198..dc51f8285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,35 @@ [1]: https://pypi.org/project/dialogflow/#history +## [2.10.0](https://www.github.com/googleapis/python-dialogflow/compare/v2.9.1...v2.10.0) (2021-11-12) + + +### Features + +* add context manager support in client ([#416](https://www.github.com/googleapis/python-dialogflow/issues/416)) ([317187c](https://www.github.com/googleapis/python-dialogflow/commit/317187cbaacc6889d6fff5d7ea483fe1bc2cd9ee)) +* add document metadata filter in article suggestion ([#437](https://www.github.com/googleapis/python-dialogflow/issues/437)) ([56a6e11](https://www.github.com/googleapis/python-dialogflow/commit/56a6e11622f73c6d302a5f43142ceb289b334fd1)) +* add smart reply model in human agent assistant ([56a6e11](https://www.github.com/googleapis/python-dialogflow/commit/56a6e11622f73c6d302a5f43142ceb289b334fd1)) +* add support for python 3.10 ([#422](https://www.github.com/googleapis/python-dialogflow/issues/422)) ([652e2e8](https://www.github.com/googleapis/python-dialogflow/commit/652e2e8d860f369b62e7866d6cf220204740ade8)) +* **v2:** added support to configure security settings, language code and time zone on conversation profile ([#431](https://www.github.com/googleapis/python-dialogflow/issues/431)) ([6296673](https://www.github.com/googleapis/python-dialogflow/commit/629667367d7098cfb62bae1b6e48cc11a72b9fbc)) + + +### Bug Fixes + +* **deps:** drop packaging dependency ([fd06e9f](https://www.github.com/googleapis/python-dialogflow/commit/fd06e9fe8626ac3d86175518c52ff14efebc0f7b)) +* **deps:** require google-api-core >= 1.28.0 ([fd06e9f](https://www.github.com/googleapis/python-dialogflow/commit/fd06e9fe8626ac3d86175518c52ff14efebc0f7b)) + + +### Documentation + +* clarified meaning of the legacy editions ([#426](https://www.github.com/googleapis/python-dialogflow/issues/426)) ([d7a7544](https://www.github.com/googleapis/python-dialogflow/commit/d7a7544ce69cb357d7cad13e9a44afe26c6d3cf5)) +* clarified semantic of the streaming APIs ([d7a7544](https://www.github.com/googleapis/python-dialogflow/commit/d7a7544ce69cb357d7cad13e9a44afe26c6d3cf5)) +* list oneofs in docstring ([fd06e9f](https://www.github.com/googleapis/python-dialogflow/commit/fd06e9fe8626ac3d86175518c52ff14efebc0f7b)) +* **samples:** Added comments ([#425](https://www.github.com/googleapis/python-dialogflow/issues/425)) ([f5d40dc](https://www.github.com/googleapis/python-dialogflow/commit/f5d40dc9b4bb57b8830dcd6541a2a1189a6c9780)) +* **v2beta1:** clarified meaning of the legacy editions ([fd06e9f](https://www.github.com/googleapis/python-dialogflow/commit/fd06e9fe8626ac3d86175518c52ff14efebc0f7b)) +* **v2beta1:** clarified semantic of the streaming APIs ([fd06e9f](https://www.github.com/googleapis/python-dialogflow/commit/fd06e9fe8626ac3d86175518c52ff14efebc0f7b)) +* **v2beta1:** recommend AnalyzeContent for future users ([#420](https://www.github.com/googleapis/python-dialogflow/issues/420)) ([1afdab3](https://www.github.com/googleapis/python-dialogflow/commit/1afdab3b50c98cc082b150ff408d0f07f11f9cf3)) +* **v2:** recommend AnalyzeContent for future users ([#421](https://www.github.com/googleapis/python-dialogflow/issues/421)) ([c6940a9](https://www.github.com/googleapis/python-dialogflow/commit/c6940a9f974af95037616bd1affb34d8db4405c9)) + ### [2.9.1](https://www.github.com/googleapis/python-dialogflow/compare/v2.9.0...v2.9.1) (2021-10-04) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c6926e34e..26073bcf7 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -22,7 +22,7 @@ In order to add a feature: documentation. - The feature must work fully on the following CPython versions: - 3.6, 3.7, 3.8 and 3.9 on both UNIX and Windows. + 3.6, 3.7, 3.8, 3.9 and 3.10 on both UNIX and Windows. - The feature must not add unnecessary dependencies (where "unnecessary" is of course subjective, but new dependencies should @@ -72,7 +72,7 @@ We use `nox `__ to instrument our tests. - To run a single unit test:: - $ nox -s unit-3.9 -- -k + $ nox -s unit-3.10 -- -k .. note:: @@ -225,11 +225,13 @@ We support: - `Python 3.7`_ - `Python 3.8`_ - `Python 3.9`_ +- `Python 3.10`_ .. _Python 3.6: https://docs.python.org/3.6/ .. _Python 3.7: https://docs.python.org/3.7/ .. _Python 3.8: https://docs.python.org/3.8/ .. _Python 3.9: https://docs.python.org/3.9/ +.. _Python 3.10: https://docs.python.org/3.10/ Supported versions can be found in our ``noxfile.py`` `config`_. diff --git a/google/cloud/dialogflow/__init__.py b/google/cloud/dialogflow/__init__.py index 2e7f45779..cfb1e351a 100644 --- a/google/cloud/dialogflow/__init__.py +++ b/google/cloud/dialogflow/__init__.py @@ -218,6 +218,7 @@ from google.cloud.dialogflow_v2.types.participant import AnalyzeContentResponse from google.cloud.dialogflow_v2.types.participant import AnnotatedMessagePart from google.cloud.dialogflow_v2.types.participant import ArticleAnswer +from google.cloud.dialogflow_v2.types.participant import AssistQueryParameters from google.cloud.dialogflow_v2.types.participant import AutomatedAgentReply from google.cloud.dialogflow_v2.types.participant import CreateParticipantRequest from google.cloud.dialogflow_v2.types.participant import DtmfParameters @@ -432,6 +433,7 @@ "AnalyzeContentResponse", "AnnotatedMessagePart", "ArticleAnswer", + "AssistQueryParameters", "AutomatedAgentReply", "CreateParticipantRequest", "DtmfParameters", diff --git a/google/cloud/dialogflow_v2/__init__.py b/google/cloud/dialogflow_v2/__init__.py index 8d44eb9dd..5f07b5ef4 100644 --- a/google/cloud/dialogflow_v2/__init__.py +++ b/google/cloud/dialogflow_v2/__init__.py @@ -166,6 +166,7 @@ from .types.participant import AnalyzeContentResponse from .types.participant import AnnotatedMessagePart from .types.participant import ArticleAnswer +from .types.participant import AssistQueryParameters from .types.participant import AutomatedAgentReply from .types.participant import CreateParticipantRequest from .types.participant import DtmfParameters @@ -243,6 +244,7 @@ "AnswerRecord", "AnswerRecordsClient", "ArticleAnswer", + "AssistQueryParameters", "AudioEncoding", "AutomatedAgentConfig", "AutomatedAgentReply", diff --git a/google/cloud/dialogflow_v2/services/agents/async_client.py b/google/cloud/dialogflow_v2/services/agents/async_client.py index 0c6102e66..bc89a2454 100644 --- a/google/cloud/dialogflow_v2/services/agents/async_client.py +++ b/google/cloud/dialogflow_v2/services/agents/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2.services.agents import pagers @@ -159,17 +164,17 @@ def __init__( async def get_agent( self, - request: agent.GetAgentRequest = None, + request: Union[agent.GetAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> agent.Agent: r"""Retrieves the specified agent. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetAgentRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetAgentRequest, dict]): The request object. The request message for [Agents.GetAgent][google.cloud.dialogflow.v2.Agents.GetAgent]. parent (:class:`str`): @@ -239,10 +244,10 @@ async def get_agent( async def set_agent( self, - request: gcd_agent.SetAgentRequest = None, + request: Union[gcd_agent.SetAgentRequest, dict] = None, *, agent: gcd_agent.Agent = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_agent.Agent: @@ -253,7 +258,7 @@ async def set_agent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.SetAgentRequest`): + request (Union[google.cloud.dialogflow_v2.types.SetAgentRequest, dict]): The request object. The request message for [Agents.SetAgent][google.cloud.dialogflow.v2.Agents.SetAgent]. agent (:class:`google.cloud.dialogflow_v2.types.Agent`): @@ -323,17 +328,17 @@ async def set_agent( async def delete_agent( self, - request: agent.DeleteAgentRequest = None, + request: Union[agent.DeleteAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes the specified agent. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteAgentRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteAgentRequest, dict]): The request object. The request message for [Agents.DeleteAgent][google.cloud.dialogflow.v2.Agents.DeleteAgent]. parent (:class:`str`): @@ -387,10 +392,10 @@ async def delete_agent( async def search_agents( self, - request: agent.SearchAgentsRequest = None, + request: Union[agent.SearchAgentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.SearchAgentsAsyncPager: @@ -403,7 +408,7 @@ async def search_agents( Sub-Collections `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.SearchAgentsRequest`): + request (Union[google.cloud.dialogflow_v2.types.SearchAgentsRequest, dict]): The request object. The request message for [Agents.SearchAgents][google.cloud.dialogflow.v2.Agents.SearchAgents]. parent (:class:`str`): @@ -473,10 +478,10 @@ async def search_agents( async def train_agent( self, - request: agent.TrainAgentRequest = None, + request: Union[agent.TrainAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -497,7 +502,7 @@ async def train_agent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.TrainAgentRequest`): + request (Union[google.cloud.dialogflow_v2.types.TrainAgentRequest, dict]): The request object. The request message for [Agents.TrainAgent][google.cloud.dialogflow.v2.Agents.TrainAgent]. parent (:class:`str`): @@ -579,10 +584,10 @@ async def train_agent( async def export_agent( self, - request: agent.ExportAgentRequest = None, + request: Union[agent.ExportAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -599,7 +604,7 @@ async def export_agent( [ExportAgentResponse][google.cloud.dialogflow.v2.ExportAgentResponse] Args: - request (:class:`google.cloud.dialogflow_v2.types.ExportAgentRequest`): + request (Union[google.cloud.dialogflow_v2.types.ExportAgentRequest, dict]): The request object. The request message for [Agents.ExportAgent][google.cloud.dialogflow.v2.Agents.ExportAgent]. parent (:class:`str`): @@ -672,9 +677,9 @@ async def export_agent( async def import_agent( self, - request: agent.ImportAgentRequest = None, + request: Union[agent.ImportAgentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -709,7 +714,7 @@ async def import_agent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.ImportAgentRequest`): + request (Union[google.cloud.dialogflow_v2.types.ImportAgentRequest, dict]): The request object. The request message for [Agents.ImportAgent][google.cloud.dialogflow.v2.Agents.ImportAgent]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -770,9 +775,9 @@ async def import_agent( async def restore_agent( self, - request: agent.RestoreAgentRequest = None, + request: Union[agent.RestoreAgentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -805,7 +810,7 @@ async def restore_agent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.RestoreAgentRequest`): + request (Union[google.cloud.dialogflow_v2.types.RestoreAgentRequest, dict]): The request object. The request message for [Agents.RestoreAgent][google.cloud.dialogflow.v2.Agents.RestoreAgent]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -866,9 +871,9 @@ async def restore_agent( async def get_validation_result( self, - request: agent.GetValidationResultRequest = None, + request: Union[agent.GetValidationResultRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> validation_result.ValidationResult: @@ -877,7 +882,7 @@ async def get_validation_result( automatically when training is completed. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetValidationResultRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetValidationResultRequest, dict]): The request object. The request message for [Agents.GetValidationResult][google.cloud.dialogflow.v2.Agents.GetValidationResult]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -915,6 +920,12 @@ async def get_validation_result( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/agents/client.py b/google/cloud/dialogflow_v2/services/agents/client.py index d032f7d09..ace34c6d7 100644 --- a/google/cloud/dialogflow_v2/services/agents/client.py +++ b/google/cloud/dialogflow_v2/services/agents/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2.services.agents import pagers @@ -280,8 +284,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -343,10 +354,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def get_agent( @@ -354,7 +362,7 @@ def get_agent( request: Union[agent.GetAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> agent.Agent: @@ -434,7 +442,7 @@ def set_agent( request: Union[gcd_agent.SetAgentRequest, dict] = None, *, agent: gcd_agent.Agent = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_agent.Agent: @@ -518,7 +526,7 @@ def delete_agent( request: Union[agent.DeleteAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -582,7 +590,7 @@ def search_agents( request: Union[agent.SearchAgentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.SearchAgentsPager: @@ -668,7 +676,7 @@ def train_agent( request: Union[agent.TrainAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -774,7 +782,7 @@ def export_agent( request: Union[agent.ExportAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -866,7 +874,7 @@ def import_agent( self, request: Union[agent.ImportAgentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -965,7 +973,7 @@ def restore_agent( self, request: Union[agent.RestoreAgentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1062,7 +1070,7 @@ def get_validation_result( self, request: Union[agent.GetValidationResultRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> validation_result.ValidationResult: @@ -1110,6 +1118,19 @@ def get_validation_result( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/agents/transports/base.py b/google/cloud/dialogflow_v2/services/agents/transports/base.py index ee669cb6c..3438f6fda 100644 --- a/google/cloud/dialogflow_v2/services/agents/transports/base.py +++ b/google/cloud/dialogflow_v2/services/agents/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore -from google.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -42,15 +41,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class AgentsTransport(abc.ABC): """Abstract transport class for Agents.""" @@ -103,7 +93,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -136,29 +126,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -193,8 +160,17 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/dialogflow_v2/services/agents/transports/grpc.py b/google/cloud/dialogflow_v2/services/agents/transports/grpc.py index 58268d24e..bb86fb21e 100644 --- a/google/cloud/dialogflow_v2/services/agents/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/agents/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -115,7 +115,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -565,5 +565,8 @@ def get_validation_result( ) return self._stubs["get_validation_result"] + def close(self): + self.grpc_channel.close() + __all__ = ("AgentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/agents/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/agents/transports/grpc_asyncio.py index a3cb0e2f3..69c7b0590 100644 --- a/google/cloud/dialogflow_v2/services/agents/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/agents/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore -from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -162,7 +161,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -575,5 +574,8 @@ def get_validation_result( ) return self._stubs["get_validation_result"] + def close(self): + return self.grpc_channel.close() + __all__ = ("AgentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/answer_records/async_client.py b/google/cloud/dialogflow_v2/services/answer_records/async_client.py index 75452cd4f..32f379b4a 100644 --- a/google/cloud/dialogflow_v2/services/answer_records/async_client.py +++ b/google/cloud/dialogflow_v2/services/answer_records/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.answer_records import pagers from google.cloud.dialogflow_v2.types import answer_record from google.cloud.dialogflow_v2.types import answer_record as gcd_answer_record @@ -169,10 +174,10 @@ def __init__( async def list_answer_records( self, - request: answer_record.ListAnswerRecordsRequest = None, + request: Union[answer_record.ListAnswerRecordsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListAnswerRecordsAsyncPager: @@ -180,7 +185,7 @@ async def list_answer_records( specified project in reverse chronological order. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListAnswerRecordsRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListAnswerRecordsRequest, dict]): The request object. Request message for [AnswerRecords.ListAnswerRecords][google.cloud.dialogflow.v2.AnswerRecords.ListAnswerRecords]. parent (:class:`str`): @@ -251,18 +256,18 @@ async def list_answer_records( async def update_answer_record( self, - request: gcd_answer_record.UpdateAnswerRecordRequest = None, + request: Union[gcd_answer_record.UpdateAnswerRecordRequest, dict] = None, *, answer_record: gcd_answer_record.AnswerRecord = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_answer_record.AnswerRecord: r"""Updates the specified answer record. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateAnswerRecordRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateAnswerRecordRequest, dict]): The request object. Request message for [AnswerRecords.UpdateAnswerRecord][google.cloud.dialogflow.v2.AnswerRecords.UpdateAnswerRecord]. answer_record (:class:`google.cloud.dialogflow_v2.types.AnswerRecord`): @@ -361,6 +366,12 @@ async def update_answer_record( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/answer_records/client.py b/google/cloud/dialogflow_v2/services/answer_records/client.py index b14ffed51..12d5dad1e 100644 --- a/google/cloud/dialogflow_v2/services/answer_records/client.py +++ b/google/cloud/dialogflow_v2/services/answer_records/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.answer_records import pagers from google.cloud.dialogflow_v2.types import answer_record from google.cloud.dialogflow_v2.types import answer_record as gcd_answer_record @@ -282,8 +286,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -345,10 +356,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_answer_records( @@ -356,7 +364,7 @@ def list_answer_records( request: Union[answer_record.ListAnswerRecordsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListAnswerRecordsPager: @@ -439,7 +447,7 @@ def update_answer_record( *, answer_record: gcd_answer_record.AnswerRecord = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_answer_record.AnswerRecord: @@ -545,6 +553,19 @@ def update_answer_record( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/answer_records/transports/base.py b/google/cloud/dialogflow_v2/services/answer_records/transports/base.py index 07847fcac..36b297434 100644 --- a/google/cloud/dialogflow_v2/services/answer_records/transports/base.py +++ b/google/cloud/dialogflow_v2/services/answer_records/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class AnswerRecordsTransport(abc.ABC): """Abstract transport class for AnswerRecords.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -168,6 +135,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_answer_records( self, diff --git a/google/cloud/dialogflow_v2/services/answer_records/transports/grpc.py b/google/cloud/dialogflow_v2/services/answer_records/transports/grpc.py index 9d91e029b..de9f90556 100644 --- a/google/cloud/dialogflow_v2/services/answer_records/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/answer_records/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -285,5 +285,8 @@ def update_answer_record( ) return self._stubs["update_answer_record"] + def close(self): + self.grpc_channel.close() + __all__ = ("AnswerRecordsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/answer_records/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/answer_records/transports/grpc_asyncio.py index eb6474085..d049b6163 100644 --- a/google/cloud/dialogflow_v2/services/answer_records/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/answer_records/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -289,5 +288,8 @@ def update_answer_record( ) return self._stubs["update_answer_record"] + def close(self): + return self.grpc_channel.close() + __all__ = ("AnswerRecordsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/contexts/async_client.py b/google/cloud/dialogflow_v2/services/contexts/async_client.py index d2c4bcd8e..3c374337b 100644 --- a/google/cloud/dialogflow_v2/services/contexts/async_client.py +++ b/google/cloud/dialogflow_v2/services/contexts/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.contexts import pagers from google.cloud.dialogflow_v2.types import context from google.cloud.dialogflow_v2.types import context as gcd_context @@ -158,10 +163,10 @@ def __init__( async def list_contexts( self, - request: context.ListContextsRequest = None, + request: Union[context.ListContextsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListContextsAsyncPager: @@ -169,7 +174,7 @@ async def list_contexts( session. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListContextsRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListContextsRequest, dict]): The request object. The request message for [Contexts.ListContexts][google.cloud.dialogflow.v2.Contexts.ListContexts]. parent (:class:`str`): @@ -243,17 +248,17 @@ async def list_contexts( async def get_context( self, - request: context.GetContextRequest = None, + request: Union[context.GetContextRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> context.Context: r"""Retrieves the specified context. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetContextRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetContextRequest, dict]): The request object. The request message for [Contexts.GetContext][google.cloud.dialogflow.v2.Contexts.GetContext]. name (:class:`str`): @@ -336,11 +341,11 @@ async def get_context( async def create_context( self, - request: gcd_context.CreateContextRequest = None, + request: Union[gcd_context.CreateContextRequest, dict] = None, *, parent: str = None, context: gcd_context.Context = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_context.Context: @@ -349,7 +354,7 @@ async def create_context( context. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateContextRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateContextRequest, dict]): The request object. The request message for [Contexts.CreateContext][google.cloud.dialogflow.v2.Contexts.CreateContext]. parent (:class:`str`): @@ -438,18 +443,18 @@ async def create_context( async def update_context( self, - request: gcd_context.UpdateContextRequest = None, + request: Union[gcd_context.UpdateContextRequest, dict] = None, *, context: gcd_context.Context = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_context.Context: r"""Updates the specified context. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateContextRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateContextRequest, dict]): The request object. The request message for [Contexts.UpdateContext][google.cloud.dialogflow.v2.Contexts.UpdateContext]. context (:class:`google.cloud.dialogflow_v2.types.Context`): @@ -536,17 +541,17 @@ async def update_context( async def delete_context( self, - request: context.DeleteContextRequest = None, + request: Union[context.DeleteContextRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes the specified context. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteContextRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteContextRequest, dict]): The request object. The request message for [Contexts.DeleteContext][google.cloud.dialogflow.v2.Contexts.DeleteContext]. name (:class:`str`): @@ -605,17 +610,17 @@ async def delete_context( async def delete_all_contexts( self, - request: context.DeleteAllContextsRequest = None, + request: Union[context.DeleteAllContextsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes all active contexts in the specified session. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteAllContextsRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteAllContextsRequest, dict]): The request object. The request message for [Contexts.DeleteAllContexts][google.cloud.dialogflow.v2.Contexts.DeleteAllContexts]. parent (:class:`str`): @@ -672,6 +677,12 @@ async def delete_all_contexts( request, retry=retry, timeout=timeout, metadata=metadata, ) + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/contexts/client.py b/google/cloud/dialogflow_v2/services/contexts/client.py index 16f08d9eb..705ef192c 100644 --- a/google/cloud/dialogflow_v2/services/contexts/client.py +++ b/google/cloud/dialogflow_v2/services/contexts/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.contexts import pagers from google.cloud.dialogflow_v2.types import context from google.cloud.dialogflow_v2.types import context as gcd_context @@ -282,8 +286,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -345,10 +356,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_contexts( @@ -356,7 +364,7 @@ def list_contexts( request: Union[context.ListContextsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListContextsPager: @@ -441,7 +449,7 @@ def get_context( request: Union[context.GetContextRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> context.Context: @@ -535,7 +543,7 @@ def create_context( *, parent: str = None, context: gcd_context.Context = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_context.Context: @@ -637,7 +645,7 @@ def update_context( *, context: gcd_context.Context = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_context.Context: @@ -734,7 +742,7 @@ def delete_context( request: Union[context.DeleteContextRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -803,7 +811,7 @@ def delete_all_contexts( request: Union[context.DeleteAllContextsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -867,6 +875,19 @@ def delete_all_contexts( request, retry=retry, timeout=timeout, metadata=metadata, ) + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/contexts/transports/base.py b/google/cloud/dialogflow_v2/services/contexts/transports/base.py index 79ea93826..f8f6bbee6 100644 --- a/google/cloud/dialogflow_v2/services/contexts/transports/base.py +++ b/google/cloud/dialogflow_v2/services/contexts/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -39,15 +38,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class ContextsTransport(abc.ABC): """Abstract transport class for Contexts.""" @@ -100,7 +90,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -133,29 +123,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -179,6 +146,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_contexts( self, diff --git a/google/cloud/dialogflow_v2/services/contexts/transports/grpc.py b/google/cloud/dialogflow_v2/services/contexts/transports/grpc.py index 60fd684c6..0161a8a20 100644 --- a/google/cloud/dialogflow_v2/services/contexts/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/contexts/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -384,5 +384,8 @@ def delete_all_contexts( ) return self._stubs["delete_all_contexts"] + def close(self): + self.grpc_channel.close() + __all__ = ("ContextsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/contexts/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/contexts/transports/grpc_asyncio.py index 0c956b74a..16a8f4f4e 100644 --- a/google/cloud/dialogflow_v2/services/contexts/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/contexts/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -391,5 +390,8 @@ def delete_all_contexts( ) return self._stubs["delete_all_contexts"] + def close(self): + return self.grpc_channel.close() + __all__ = ("ContextsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/conversation_profiles/async_client.py b/google/cloud/dialogflow_v2/services/conversation_profiles/async_client.py index 08003bf43..2534f6952 100644 --- a/google/cloud/dialogflow_v2/services/conversation_profiles/async_client.py +++ b/google/cloud/dialogflow_v2/services/conversation_profiles/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.conversation_profiles import pagers from google.cloud.dialogflow_v2.types import audio_config from google.cloud.dialogflow_v2.types import conversation_profile @@ -63,6 +68,12 @@ class ConversationProfilesAsyncClient: parse_conversation_profile_path = staticmethod( ConversationProfilesClient.parse_conversation_profile_path ) + cx_security_settings_path = staticmethod( + ConversationProfilesClient.cx_security_settings_path + ) + parse_cx_security_settings_path = staticmethod( + ConversationProfilesClient.parse_cx_security_settings_path + ) document_path = staticmethod(ConversationProfilesClient.document_path) parse_document_path = staticmethod(ConversationProfilesClient.parse_document_path) knowledge_base_path = staticmethod(ConversationProfilesClient.knowledge_base_path) @@ -190,10 +201,12 @@ def __init__( async def list_conversation_profiles( self, - request: conversation_profile.ListConversationProfilesRequest = None, + request: Union[ + conversation_profile.ListConversationProfilesRequest, dict + ] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListConversationProfilesAsyncPager: @@ -201,7 +214,7 @@ async def list_conversation_profiles( specified project. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListConversationProfilesRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListConversationProfilesRequest, dict]): The request object. The request message for [ConversationProfiles.ListConversationProfiles][google.cloud.dialogflow.v2.ConversationProfiles.ListConversationProfiles]. parent (:class:`str`): @@ -272,17 +285,17 @@ async def list_conversation_profiles( async def get_conversation_profile( self, - request: conversation_profile.GetConversationProfileRequest = None, + request: Union[conversation_profile.GetConversationProfileRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation_profile.ConversationProfile: r"""Retrieves the specified conversation profile. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetConversationProfileRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetConversationProfileRequest, dict]): The request object. The request message for [ConversationProfiles.GetConversationProfile][google.cloud.dialogflow.v2.ConversationProfiles.GetConversationProfile]. name (:class:`str`): @@ -344,11 +357,13 @@ async def get_conversation_profile( async def create_conversation_profile( self, - request: gcd_conversation_profile.CreateConversationProfileRequest = None, + request: Union[ + gcd_conversation_profile.CreateConversationProfileRequest, dict + ] = None, *, parent: str = None, conversation_profile: gcd_conversation_profile.ConversationProfile = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation_profile.ConversationProfile: @@ -361,7 +376,7 @@ async def create_conversation_profile( API. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateConversationProfileRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateConversationProfileRequest, dict]): The request object. The request message for [ConversationProfiles.CreateConversationProfile][google.cloud.dialogflow.v2.ConversationProfiles.CreateConversationProfile]. parent (:class:`str`): @@ -432,11 +447,13 @@ async def create_conversation_profile( async def update_conversation_profile( self, - request: gcd_conversation_profile.UpdateConversationProfileRequest = None, + request: Union[ + gcd_conversation_profile.UpdateConversationProfileRequest, dict + ] = None, *, conversation_profile: gcd_conversation_profile.ConversationProfile = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation_profile.ConversationProfile: @@ -449,7 +466,7 @@ async def update_conversation_profile( API. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateConversationProfileRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateConversationProfileRequest, dict]): The request object. The request message for [ConversationProfiles.UpdateConversationProfile][google.cloud.dialogflow.v2.ConversationProfiles.UpdateConversationProfile]. conversation_profile (:class:`google.cloud.dialogflow_v2.types.ConversationProfile`): @@ -521,17 +538,19 @@ async def update_conversation_profile( async def delete_conversation_profile( self, - request: conversation_profile.DeleteConversationProfileRequest = None, + request: Union[ + conversation_profile.DeleteConversationProfileRequest, dict + ] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes the specified conversation profile. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteConversationProfileRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteConversationProfileRequest, dict]): The request object. The request message for [ConversationProfiles.DeleteConversationProfile][google.cloud.dialogflow.v2.ConversationProfiles.DeleteConversationProfile]. This operation fails if the conversation profile is @@ -586,6 +605,12 @@ async def delete_conversation_profile( request, retry=retry, timeout=timeout, metadata=metadata, ) + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/conversation_profiles/client.py b/google/cloud/dialogflow_v2/services/conversation_profiles/client.py index 91e39a7d5..626431a9a 100644 --- a/google/cloud/dialogflow_v2/services/conversation_profiles/client.py +++ b/google/cloud/dialogflow_v2/services/conversation_profiles/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.conversation_profiles import pagers from google.cloud.dialogflow_v2.types import audio_config from google.cloud.dialogflow_v2.types import conversation_profile @@ -210,6 +214,24 @@ def parse_conversation_profile_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def cx_security_settings_path( + project: str, location: str, security_settings: str, + ) -> str: + """Returns a fully-qualified cx_security_settings string.""" + return "projects/{project}/locations/{location}/securitySettings/{security_settings}".format( + project=project, location=location, security_settings=security_settings, + ) + + @staticmethod + def parse_cx_security_settings_path(path: str) -> Dict[str, str]: + """Parses a cx_security_settings path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/securitySettings/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def document_path(project: str, knowledge_base: str, document: str,) -> str: """Returns a fully-qualified document string.""" @@ -351,8 +373,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -414,10 +443,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_conversation_profiles( @@ -427,7 +453,7 @@ def list_conversation_profiles( ] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListConversationProfilesPager: @@ -513,7 +539,7 @@ def get_conversation_profile( request: Union[conversation_profile.GetConversationProfileRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation_profile.ConversationProfile: @@ -588,7 +614,7 @@ def create_conversation_profile( *, parent: str = None, conversation_profile: gcd_conversation_profile.ConversationProfile = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation_profile.ConversationProfile: @@ -682,7 +708,7 @@ def update_conversation_profile( *, conversation_profile: gcd_conversation_profile.ConversationProfile = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation_profile.ConversationProfile: @@ -776,7 +802,7 @@ def delete_conversation_profile( ] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -842,6 +868,19 @@ def delete_conversation_profile( request, retry=retry, timeout=timeout, metadata=metadata, ) + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/conversation_profiles/transports/base.py b/google/cloud/dialogflow_v2/services/conversation_profiles/transports/base.py index a06996a74..94757a92c 100644 --- a/google/cloud/dialogflow_v2/services/conversation_profiles/transports/base.py +++ b/google/cloud/dialogflow_v2/services/conversation_profiles/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -41,15 +40,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class ConversationProfilesTransport(abc.ABC): """Abstract transport class for ConversationProfiles.""" @@ -102,7 +92,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -135,29 +125,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -188,6 +155,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_conversation_profiles( self, diff --git a/google/cloud/dialogflow_v2/services/conversation_profiles/transports/grpc.py b/google/cloud/dialogflow_v2/services/conversation_profiles/transports/grpc.py index 8df0f1baa..feb0ebe95 100644 --- a/google/cloud/dialogflow_v2/services/conversation_profiles/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/conversation_profiles/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -387,5 +387,8 @@ def delete_conversation_profile( ) return self._stubs["delete_conversation_profile"] + def close(self): + self.grpc_channel.close() + __all__ = ("ConversationProfilesGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/conversation_profiles/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/conversation_profiles/transports/grpc_asyncio.py index 1a207529f..b5cac737c 100644 --- a/google/cloud/dialogflow_v2/services/conversation_profiles/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/conversation_profiles/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -391,5 +390,8 @@ def delete_conversation_profile( ) return self._stubs["delete_conversation_profile"] + def close(self): + return self.grpc_channel.close() + __all__ = ("ConversationProfilesGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/conversations/async_client.py b/google/cloud/dialogflow_v2/services/conversations/async_client.py index 3a717bc8f..68dedda1d 100644 --- a/google/cloud/dialogflow_v2/services/conversations/async_client.py +++ b/google/cloud/dialogflow_v2/services/conversations/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.conversations import pagers from google.cloud.dialogflow_v2.types import conversation from google.cloud.dialogflow_v2.types import conversation as gcd_conversation @@ -176,11 +181,11 @@ def __init__( async def create_conversation( self, - request: gcd_conversation.CreateConversationRequest = None, + request: Union[gcd_conversation.CreateConversationRequest, dict] = None, *, parent: str = None, conversation: gcd_conversation.Conversation = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation.Conversation: @@ -207,7 +212,7 @@ async def create_conversation( is triggered, conversation will transfer to Assist Stage. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateConversationRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateConversationRequest, dict]): The request object. The request message for [Conversations.CreateConversation][google.cloud.dialogflow.v2.Conversations.CreateConversation]. parent (:class:`str`): @@ -281,10 +286,10 @@ async def create_conversation( async def list_conversations( self, - request: conversation.ListConversationsRequest = None, + request: Union[conversation.ListConversationsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListConversationsAsyncPager: @@ -292,7 +297,7 @@ async def list_conversations( specified project. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListConversationsRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListConversationsRequest, dict]): The request object. The request message for [Conversations.ListConversations][google.cloud.dialogflow.v2.Conversations.ListConversations]. parent (:class:`str`): @@ -363,17 +368,17 @@ async def list_conversations( async def get_conversation( self, - request: conversation.GetConversationRequest = None, + request: Union[conversation.GetConversationRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.Conversation: r"""Retrieves the specific conversation. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetConversationRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetConversationRequest, dict]): The request object. The request message for [Conversations.GetConversation][google.cloud.dialogflow.v2.Conversations.GetConversation]. name (:class:`str`): @@ -439,10 +444,10 @@ async def get_conversation( async def complete_conversation( self, - request: conversation.CompleteConversationRequest = None, + request: Union[conversation.CompleteConversationRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.Conversation: @@ -451,7 +456,7 @@ async def complete_conversation( days. Args: - request (:class:`google.cloud.dialogflow_v2.types.CompleteConversationRequest`): + request (Union[google.cloud.dialogflow_v2.types.CompleteConversationRequest, dict]): The request object. The request message for [Conversations.CompleteConversation][google.cloud.dialogflow.v2.Conversations.CompleteConversation]. name (:class:`str`): @@ -518,10 +523,10 @@ async def complete_conversation( async def list_messages( self, - request: conversation.ListMessagesRequest = None, + request: Union[conversation.ListMessagesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListMessagesAsyncPager: @@ -532,7 +537,7 @@ async def list_messages( and empty page_token. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListMessagesRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListMessagesRequest, dict]): The request object. The request message for [Conversations.ListMessages][google.cloud.dialogflow.v2.Conversations.ListMessages]. parent (:class:`str`): @@ -601,6 +606,12 @@ async def list_messages( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/conversations/client.py b/google/cloud/dialogflow_v2/services/conversations/client.py index 3233e5909..830ab4ad3 100644 --- a/google/cloud/dialogflow_v2/services/conversations/client.py +++ b/google/cloud/dialogflow_v2/services/conversations/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.conversations import pagers from google.cloud.dialogflow_v2.types import conversation from google.cloud.dialogflow_v2.types import conversation as gcd_conversation @@ -315,8 +319,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -378,10 +389,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def create_conversation( @@ -390,7 +398,7 @@ def create_conversation( *, parent: str = None, conversation: gcd_conversation.Conversation = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation.Conversation: @@ -494,7 +502,7 @@ def list_conversations( request: Union[conversation.ListConversationsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListConversationsPager: @@ -576,7 +584,7 @@ def get_conversation( request: Union[conversation.GetConversationRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.Conversation: @@ -652,7 +660,7 @@ def complete_conversation( request: Union[conversation.CompleteConversationRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.Conversation: @@ -731,7 +739,7 @@ def list_messages( request: Union[conversation.ListMessagesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListMessagesPager: @@ -811,6 +819,19 @@ def list_messages( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/conversations/transports/base.py b/google/cloud/dialogflow_v2/services/conversations/transports/base.py index 960e154f0..4d72750f6 100644 --- a/google/cloud/dialogflow_v2/services/conversations/transports/base.py +++ b/google/cloud/dialogflow_v2/services/conversations/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class ConversationsTransport(abc.ABC): """Abstract transport class for Conversations.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -177,6 +144,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def create_conversation( self, diff --git a/google/cloud/dialogflow_v2/services/conversations/transports/grpc.py b/google/cloud/dialogflow_v2/services/conversations/transports/grpc.py index 35f8c4d3a..099f7d6e4 100644 --- a/google/cloud/dialogflow_v2/services/conversations/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/conversations/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -392,5 +392,8 @@ def list_messages( ) return self._stubs["list_messages"] + def close(self): + self.grpc_channel.close() + __all__ = ("ConversationsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/conversations/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/conversations/transports/grpc_asyncio.py index abdd8ba01..d7481b081 100644 --- a/google/cloud/dialogflow_v2/services/conversations/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/conversations/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -399,5 +398,8 @@ def list_messages( ) return self._stubs["list_messages"] + def close(self): + return self.grpc_channel.close() + __all__ = ("ConversationsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/documents/async_client.py b/google/cloud/dialogflow_v2/services/documents/async_client.py index 5290615b6..64abeb23e 100644 --- a/google/cloud/dialogflow_v2/services/documents/async_client.py +++ b/google/cloud/dialogflow_v2/services/documents/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2.services.documents import pagers @@ -164,10 +169,10 @@ def __init__( async def list_documents( self, - request: document.ListDocumentsRequest = None, + request: Union[document.ListDocumentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListDocumentsAsyncPager: @@ -175,7 +180,7 @@ async def list_documents( base. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListDocumentsRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListDocumentsRequest, dict]): The request object. Request message for [Documents.ListDocuments][google.cloud.dialogflow.v2.Documents.ListDocuments]. parent (:class:`str`): @@ -246,17 +251,17 @@ async def list_documents( async def get_document( self, - request: document.GetDocumentRequest = None, + request: Union[document.GetDocumentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document.Document: r"""Retrieves the specified document. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetDocumentRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetDocumentRequest, dict]): The request object. Request message for [Documents.GetDocument][google.cloud.dialogflow.v2.Documents.GetDocument]. name (:class:`str`): @@ -324,11 +329,11 @@ async def get_document( async def create_document( self, - request: gcd_document.CreateDocumentRequest = None, + request: Union[gcd_document.CreateDocumentRequest, dict] = None, *, parent: str = None, document: gcd_document.Document = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -344,7 +349,7 @@ async def create_document( - ``response``: [Document][google.cloud.dialogflow.v2.Document] Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateDocumentRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateDocumentRequest, dict]): The request object. Request message for [Documents.CreateDocument][google.cloud.dialogflow.v2.Documents.CreateDocument]. parent (:class:`str`): @@ -432,10 +437,10 @@ async def create_document( async def delete_document( self, - request: document.DeleteDocumentRequest = None, + request: Union[document.DeleteDocumentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -452,7 +457,7 @@ async def delete_document( message `__ Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteDocumentRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteDocumentRequest, dict]): The request object. Request message for [Documents.DeleteDocument][google.cloud.dialogflow.v2.Documents.DeleteDocument]. name (:class:`str`): @@ -534,11 +539,11 @@ async def delete_document( async def update_document( self, - request: gcd_document.UpdateDocumentRequest = None, + request: Union[gcd_document.UpdateDocumentRequest, dict] = None, *, document: gcd_document.Document = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -554,7 +559,7 @@ async def update_document( - ``response``: [Document][google.cloud.dialogflow.v2.Document] Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateDocumentRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateDocumentRequest, dict]): The request object. Request message for [Documents.UpdateDocument][google.cloud.dialogflow.v2.Documents.UpdateDocument]. document (:class:`google.cloud.dialogflow_v2.types.Document`): @@ -644,11 +649,11 @@ async def update_document( async def reload_document( self, - request: document.ReloadDocumentRequest = None, + request: Union[document.ReloadDocumentRequest, dict] = None, *, name: str = None, content_uri: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -671,7 +676,7 @@ async def reload_document( is deprecated; only use ``projects.knowledgeBases.documents``. Args: - request (:class:`google.cloud.dialogflow_v2.types.ReloadDocumentRequest`): + request (Union[google.cloud.dialogflow_v2.types.ReloadDocumentRequest, dict]): The request object. Request message for [Documents.ReloadDocument][google.cloud.dialogflow.v2.Documents.ReloadDocument]. name (:class:`str`): @@ -761,6 +766,12 @@ async def reload_document( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/documents/client.py b/google/cloud/dialogflow_v2/services/documents/client.py index c6f07bed5..74044633b 100644 --- a/google/cloud/dialogflow_v2/services/documents/client.py +++ b/google/cloud/dialogflow_v2/services/documents/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2.services.documents import pagers @@ -286,8 +290,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -349,10 +360,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_documents( @@ -360,7 +368,7 @@ def list_documents( request: Union[document.ListDocumentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListDocumentsPager: @@ -442,7 +450,7 @@ def get_document( request: Union[document.GetDocumentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document.Document: @@ -521,7 +529,7 @@ def create_document( *, parent: str = None, document: gcd_document.Document = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -628,7 +636,7 @@ def delete_document( request: Union[document.DeleteDocumentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -731,7 +739,7 @@ def update_document( *, document: gcd_document.Document = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -841,7 +849,7 @@ def reload_document( *, name: str = None, content_uri: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -954,6 +962,19 @@ def reload_document( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/documents/transports/base.py b/google/cloud/dialogflow_v2/services/documents/transports/base.py index 37cc6d0fd..1ee3d7889 100644 --- a/google/cloud/dialogflow_v2/services/documents/transports/base.py +++ b/google/cloud/dialogflow_v2/services/documents/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore -from google.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -40,15 +39,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class DocumentsTransport(abc.ABC): """Abstract transport class for Documents.""" @@ -101,7 +91,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -134,29 +124,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -180,8 +147,17 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/dialogflow_v2/services/documents/transports/grpc.py b/google/cloud/dialogflow_v2/services/documents/transports/grpc.py index 7fb63a137..c74e563b5 100644 --- a/google/cloud/dialogflow_v2/services/documents/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/documents/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -114,7 +114,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -445,5 +445,8 @@ def reload_document( ) return self._stubs["reload_document"] + def close(self): + self.grpc_channel.close() + __all__ = ("DocumentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/documents/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/documents/transports/grpc_asyncio.py index e712a9f6d..0d9de9d1e 100644 --- a/google/cloud/dialogflow_v2/services/documents/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/documents/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore -from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -161,7 +160,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -460,5 +459,8 @@ def reload_document( ) return self._stubs["reload_document"] + def close(self): + return self.grpc_channel.close() + __all__ = ("DocumentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/entity_types/async_client.py b/google/cloud/dialogflow_v2/services/entity_types/async_client.py index 3ad711d39..db171337c 100644 --- a/google/cloud/dialogflow_v2/services/entity_types/async_client.py +++ b/google/cloud/dialogflow_v2/services/entity_types/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2.services.entity_types import pagers @@ -166,11 +171,11 @@ def __init__( async def list_entity_types( self, - request: entity_type.ListEntityTypesRequest = None, + request: Union[entity_type.ListEntityTypesRequest, dict] = None, *, parent: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListEntityTypesAsyncPager: @@ -178,7 +183,7 @@ async def list_entity_types( agent. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListEntityTypesRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListEntityTypesRequest, dict]): The request object. The request message for [EntityTypes.ListEntityTypes][google.cloud.dialogflow.v2.EntityTypes.ListEntityTypes]. parent (:class:`str`): @@ -260,18 +265,18 @@ async def list_entity_types( async def get_entity_type( self, - request: entity_type.GetEntityTypeRequest = None, + request: Union[entity_type.GetEntityTypeRequest, dict] = None, *, name: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> entity_type.EntityType: r"""Retrieves the specified entity type. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetEntityTypeRequest, dict]): The request object. The request message for [EntityTypes.GetEntityType][google.cloud.dialogflow.v2.EntityTypes.GetEntityType]. name (:class:`str`): @@ -357,12 +362,12 @@ async def get_entity_type( async def create_entity_type( self, - request: gcd_entity_type.CreateEntityTypeRequest = None, + request: Union[gcd_entity_type.CreateEntityTypeRequest, dict] = None, *, parent: str = None, entity_type: gcd_entity_type.EntityType = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_entity_type.EntityType: @@ -373,7 +378,7 @@ async def create_entity_type( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateEntityTypeRequest, dict]): The request object. The request message for [EntityTypes.CreateEntityType][google.cloud.dialogflow.v2.EntityTypes.CreateEntityType]. parent (:class:`str`): @@ -466,11 +471,11 @@ async def create_entity_type( async def update_entity_type( self, - request: gcd_entity_type.UpdateEntityTypeRequest = None, + request: Union[gcd_entity_type.UpdateEntityTypeRequest, dict] = None, *, entity_type: gcd_entity_type.EntityType = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_entity_type.EntityType: @@ -481,7 +486,7 @@ async def update_entity_type( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateEntityTypeRequest, dict]): The request object. The request message for [EntityTypes.UpdateEntityType][google.cloud.dialogflow.v2.EntityTypes.UpdateEntityType]. entity_type (:class:`google.cloud.dialogflow_v2.types.EntityType`): @@ -567,10 +572,10 @@ async def update_entity_type( async def delete_entity_type( self, - request: entity_type.DeleteEntityTypeRequest = None, + request: Union[entity_type.DeleteEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -581,7 +586,7 @@ async def delete_entity_type( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteEntityTypeRequest, dict]): The request object. The request message for [EntityTypes.DeleteEntityType][google.cloud.dialogflow.v2.EntityTypes.DeleteEntityType]. name (:class:`str`): @@ -635,9 +640,9 @@ async def delete_entity_type( async def batch_update_entity_types( self, - request: entity_type.BatchUpdateEntityTypesRequest = None, + request: Union[entity_type.BatchUpdateEntityTypesRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -658,7 +663,7 @@ async def batch_update_entity_types( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.BatchUpdateEntityTypesRequest`): + request (Union[google.cloud.dialogflow_v2.types.BatchUpdateEntityTypesRequest, dict]): The request object. The request message for [EntityTypes.BatchUpdateEntityTypes][google.cloud.dialogflow.v2.EntityTypes.BatchUpdateEntityTypes]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -710,11 +715,11 @@ async def batch_update_entity_types( async def batch_delete_entity_types( self, - request: entity_type.BatchDeleteEntityTypesRequest = None, + request: Union[entity_type.BatchDeleteEntityTypesRequest, dict] = None, *, parent: str = None, entity_type_names: Sequence[str] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -735,7 +740,7 @@ async def batch_delete_entity_types( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.BatchDeleteEntityTypesRequest`): + request (Union[google.cloud.dialogflow_v2.types.BatchDeleteEntityTypesRequest, dict]): The request object. The request message for [EntityTypes.BatchDeleteEntityTypes][google.cloud.dialogflow.v2.EntityTypes.BatchDeleteEntityTypes]. parent (:class:`str`): @@ -826,12 +831,12 @@ async def batch_delete_entity_types( async def batch_create_entities( self, - request: entity_type.BatchCreateEntitiesRequest = None, + request: Union[entity_type.BatchCreateEntitiesRequest, dict] = None, *, parent: str = None, entities: Sequence[entity_type.EntityType.Entity] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -852,7 +857,7 @@ async def batch_create_entities( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.BatchCreateEntitiesRequest`): + request (Union[google.cloud.dialogflow_v2.types.BatchCreateEntitiesRequest, dict]): The request object. The request message for [EntityTypes.BatchCreateEntities][google.cloud.dialogflow.v2.EntityTypes.BatchCreateEntities]. parent (:class:`str`): @@ -954,12 +959,12 @@ async def batch_create_entities( async def batch_update_entities( self, - request: entity_type.BatchUpdateEntitiesRequest = None, + request: Union[entity_type.BatchUpdateEntitiesRequest, dict] = None, *, parent: str = None, entities: Sequence[entity_type.EntityType.Entity] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -982,7 +987,7 @@ async def batch_update_entities( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.BatchUpdateEntitiesRequest`): + request (Union[google.cloud.dialogflow_v2.types.BatchUpdateEntitiesRequest, dict]): The request object. The request message for [EntityTypes.BatchUpdateEntities][google.cloud.dialogflow.v2.EntityTypes.BatchUpdateEntities]. parent (:class:`str`): @@ -1086,12 +1091,12 @@ async def batch_update_entities( async def batch_delete_entities( self, - request: entity_type.BatchDeleteEntitiesRequest = None, + request: Union[entity_type.BatchDeleteEntitiesRequest, dict] = None, *, parent: str = None, entity_values: Sequence[str] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -1112,7 +1117,7 @@ async def batch_delete_entities( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.BatchDeleteEntitiesRequest`): + request (Union[google.cloud.dialogflow_v2.types.BatchDeleteEntitiesRequest, dict]): The request object. The request message for [EntityTypes.BatchDeleteEntities][google.cloud.dialogflow.v2.EntityTypes.BatchDeleteEntities]. parent (:class:`str`): @@ -1215,6 +1220,12 @@ async def batch_delete_entities( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/entity_types/client.py b/google/cloud/dialogflow_v2/services/entity_types/client.py index 6ef51e7f6..67d0aec8e 100644 --- a/google/cloud/dialogflow_v2/services/entity_types/client.py +++ b/google/cloud/dialogflow_v2/services/entity_types/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2.services.entity_types import pagers @@ -285,8 +289,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -348,10 +359,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_entity_types( @@ -360,7 +368,7 @@ def list_entity_types( *, parent: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListEntityTypesPager: @@ -454,7 +462,7 @@ def get_entity_type( *, name: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> entity_type.EntityType: @@ -552,7 +560,7 @@ def create_entity_type( parent: str = None, entity_type: gcd_entity_type.EntityType = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_entity_type.EntityType: @@ -660,7 +668,7 @@ def update_entity_type( *, entity_type: gcd_entity_type.EntityType = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_entity_type.EntityType: @@ -760,7 +768,7 @@ def delete_entity_type( request: Union[entity_type.DeleteEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -827,7 +835,7 @@ def batch_update_entity_types( self, request: Union[entity_type.BatchUpdateEntityTypesRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -907,7 +915,7 @@ def batch_delete_entity_types( *, parent: str = None, entity_type_names: Sequence[str] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1026,7 +1034,7 @@ def batch_create_entities( parent: str = None, entities: Sequence[entity_type.EntityType.Entity] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1154,7 +1162,7 @@ def batch_update_entities( parent: str = None, entities: Sequence[entity_type.EntityType.Entity] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1286,7 +1294,7 @@ def batch_delete_entities( parent: str = None, entity_values: Sequence[str] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1410,6 +1418,19 @@ def batch_delete_entities( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/entity_types/transports/base.py b/google/cloud/dialogflow_v2/services/entity_types/transports/base.py index 4b79a0b2a..6795abe9f 100644 --- a/google/cloud/dialogflow_v2/services/entity_types/transports/base.py +++ b/google/cloud/dialogflow_v2/services/entity_types/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore -from google.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -41,15 +40,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class EntityTypesTransport(abc.ABC): """Abstract transport class for EntityTypes.""" @@ -102,7 +92,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -135,29 +125,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -203,8 +170,17 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/dialogflow_v2/services/entity_types/transports/grpc.py b/google/cloud/dialogflow_v2/services/entity_types/transports/grpc.py index 5eaafd97e..84e8a4ee2 100644 --- a/google/cloud/dialogflow_v2/services/entity_types/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/entity_types/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -115,7 +115,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -600,5 +600,8 @@ def batch_delete_entities( ) return self._stubs["batch_delete_entities"] + def close(self): + self.grpc_channel.close() + __all__ = ("EntityTypesGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/entity_types/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/entity_types/transports/grpc_asyncio.py index 49a22ee82..cd0c64eb6 100644 --- a/google/cloud/dialogflow_v2/services/entity_types/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/entity_types/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore -from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -162,7 +161,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -614,5 +613,8 @@ def batch_delete_entities( ) return self._stubs["batch_delete_entities"] + def close(self): + return self.grpc_channel.close() + __all__ = ("EntityTypesGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/environments/async_client.py b/google/cloud/dialogflow_v2/services/environments/async_client.py index e34bde50f..a16d5e77f 100644 --- a/google/cloud/dialogflow_v2/services/environments/async_client.py +++ b/google/cloud/dialogflow_v2/services/environments/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.environments import pagers from google.cloud.dialogflow_v2.types import environment from google.cloud.dialogflow_v2.types import fulfillment @@ -167,10 +172,10 @@ def __init__( async def list_environments( self, - request: environment.ListEnvironmentsRequest = None, + request: Union[environment.ListEnvironmentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListEnvironmentsAsyncPager: @@ -178,7 +183,7 @@ async def list_environments( the specified agent. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListEnvironmentsRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListEnvironmentsRequest, dict]): The request object. The request message for [Environments.ListEnvironments][google.cloud.dialogflow.v2.Environments.ListEnvironments]. parent (:class:`str`): @@ -251,16 +256,16 @@ async def list_environments( async def get_environment( self, - request: environment.GetEnvironmentRequest = None, + request: Union[environment.GetEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: r"""Retrieves the specified agent environment. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetEnvironmentRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetEnvironmentRequest, dict]): The request object. The request message for [Environments.GetEnvironment][google.cloud.dialogflow.v2.Environments.GetEnvironment]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -319,16 +324,16 @@ async def get_environment( async def create_environment( self, - request: environment.CreateEnvironmentRequest = None, + request: Union[environment.CreateEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: r"""Creates an agent environment. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateEnvironmentRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateEnvironmentRequest, dict]): The request object. The request message for [Environments.CreateEnvironment][google.cloud.dialogflow.v2.Environments.CreateEnvironment]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -387,9 +392,9 @@ async def create_environment( async def update_environment( self, - request: environment.UpdateEnvironmentRequest = None, + request: Union[environment.UpdateEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: @@ -409,7 +414,7 @@ async def update_environment( calling this method. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateEnvironmentRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateEnvironmentRequest, dict]): The request object. The request message for [Environments.UpdateEnvironment][google.cloud.dialogflow.v2.Environments.UpdateEnvironment]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -470,16 +475,16 @@ async def update_environment( async def delete_environment( self, - request: environment.DeleteEnvironmentRequest = None, + request: Union[environment.DeleteEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes the specified agent environment. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteEnvironmentRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteEnvironmentRequest, dict]): The request object. The request message for [Environments.DeleteEnvironment][google.cloud.dialogflow.v2.Environments.DeleteEnvironment]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -512,16 +517,16 @@ async def delete_environment( async def get_environment_history( self, - request: environment.GetEnvironmentHistoryRequest = None, + request: Union[environment.GetEnvironmentHistoryRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.GetEnvironmentHistoryAsyncPager: r"""Gets the history of the specified environment. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetEnvironmentHistoryRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetEnvironmentHistoryRequest, dict]): The request object. The request message for [Environments.GetEnvironmentHistory][google.cloud.dialogflow.v2.Environments.GetEnvironmentHistory]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -568,6 +573,12 @@ async def get_environment_history( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/environments/client.py b/google/cloud/dialogflow_v2/services/environments/client.py index 7d9d1c2c0..f480dce3d 100644 --- a/google/cloud/dialogflow_v2/services/environments/client.py +++ b/google/cloud/dialogflow_v2/services/environments/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.environments import pagers from google.cloud.dialogflow_v2.types import environment from google.cloud.dialogflow_v2.types import fulfillment @@ -308,8 +312,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -371,10 +382,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_environments( @@ -382,7 +390,7 @@ def list_environments( request: Union[environment.ListEnvironmentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListEnvironmentsPager: @@ -465,7 +473,7 @@ def get_environment( self, request: Union[environment.GetEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: @@ -534,7 +542,7 @@ def create_environment( self, request: Union[environment.CreateEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: @@ -603,7 +611,7 @@ def update_environment( self, request: Union[environment.UpdateEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: @@ -687,7 +695,7 @@ def delete_environment( self, request: Union[environment.DeleteEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -730,7 +738,7 @@ def get_environment_history( self, request: Union[environment.GetEnvironmentHistoryRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.GetEnvironmentHistoryPager: @@ -785,6 +793,19 @@ def get_environment_history( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/environments/transports/base.py b/google/cloud/dialogflow_v2/services/environments/transports/base.py index 82aa2d233..cf3fd7fe4 100644 --- a/google/cloud/dialogflow_v2/services/environments/transports/base.py +++ b/google/cloud/dialogflow_v2/services/environments/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class EnvironmentsTransport(abc.ABC): """Abstract transport class for Environments.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -180,6 +147,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_environments( self, diff --git a/google/cloud/dialogflow_v2/services/environments/transports/grpc.py b/google/cloud/dialogflow_v2/services/environments/transports/grpc.py index df74ed8f8..a56396e5b 100644 --- a/google/cloud/dialogflow_v2/services/environments/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/environments/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -401,5 +401,8 @@ def get_environment_history( ) return self._stubs["get_environment_history"] + def close(self): + self.grpc_channel.close() + __all__ = ("EnvironmentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/environments/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/environments/transports/grpc_asyncio.py index a96252330..832ee8a95 100644 --- a/google/cloud/dialogflow_v2/services/environments/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/environments/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -412,5 +411,8 @@ def get_environment_history( ) return self._stubs["get_environment_history"] + def close(self): + return self.grpc_channel.close() + __all__ = ("EnvironmentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/fulfillments/async_client.py b/google/cloud/dialogflow_v2/services/fulfillments/async_client.py index 28fb7fc0b..7131874e0 100644 --- a/google/cloud/dialogflow_v2/services/fulfillments/async_client.py +++ b/google/cloud/dialogflow_v2/services/fulfillments/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.types import fulfillment from google.cloud.dialogflow_v2.types import fulfillment as gcd_fulfillment from google.protobuf import field_mask_pb2 # type: ignore @@ -162,17 +167,17 @@ def __init__( async def get_fulfillment( self, - request: fulfillment.GetFulfillmentRequest = None, + request: Union[fulfillment.GetFulfillmentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> fulfillment.Fulfillment: r"""Retrieves the fulfillment. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetFulfillmentRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetFulfillmentRequest, dict]): The request object. The request message for [Fulfillments.GetFulfillment][google.cloud.dialogflow.v2.Fulfillments.GetFulfillment]. name (:class:`str`): @@ -243,18 +248,18 @@ async def get_fulfillment( async def update_fulfillment( self, - request: gcd_fulfillment.UpdateFulfillmentRequest = None, + request: Union[gcd_fulfillment.UpdateFulfillmentRequest, dict] = None, *, fulfillment: gcd_fulfillment.Fulfillment = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_fulfillment.Fulfillment: r"""Updates the fulfillment. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateFulfillmentRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateFulfillmentRequest, dict]): The request object. The request message for [Fulfillments.UpdateFulfillment][google.cloud.dialogflow.v2.Fulfillments.UpdateFulfillment]. fulfillment (:class:`google.cloud.dialogflow_v2.types.Fulfillment`): @@ -333,6 +338,12 @@ async def update_fulfillment( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/fulfillments/client.py b/google/cloud/dialogflow_v2/services/fulfillments/client.py index fca89942b..7027e2c3f 100644 --- a/google/cloud/dialogflow_v2/services/fulfillments/client.py +++ b/google/cloud/dialogflow_v2/services/fulfillments/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.types import fulfillment from google.cloud.dialogflow_v2.types import fulfillment as gcd_fulfillment from google.protobuf import field_mask_pb2 # type: ignore @@ -277,8 +281,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -340,10 +351,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def get_fulfillment( @@ -351,7 +359,7 @@ def get_fulfillment( request: Union[fulfillment.GetFulfillmentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> fulfillment.Fulfillment: @@ -433,7 +441,7 @@ def update_fulfillment( *, fulfillment: gcd_fulfillment.Fulfillment = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_fulfillment.Fulfillment: @@ -519,6 +527,19 @@ def update_fulfillment( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/fulfillments/transports/base.py b/google/cloud/dialogflow_v2/services/fulfillments/transports/base.py index 21f130998..b4e627411 100644 --- a/google/cloud/dialogflow_v2/services/fulfillments/transports/base.py +++ b/google/cloud/dialogflow_v2/services/fulfillments/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class FulfillmentsTransport(abc.ABC): """Abstract transport class for Fulfillments.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -166,6 +133,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def get_fulfillment( self, diff --git a/google/cloud/dialogflow_v2/services/fulfillments/transports/grpc.py b/google/cloud/dialogflow_v2/services/fulfillments/transports/grpc.py index f4954a8a4..f9cbb75b7 100644 --- a/google/cloud/dialogflow_v2/services/fulfillments/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/fulfillments/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -281,5 +281,8 @@ def update_fulfillment( ) return self._stubs["update_fulfillment"] + def close(self): + self.grpc_channel.close() + __all__ = ("FulfillmentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/fulfillments/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/fulfillments/transports/grpc_asyncio.py index 867a98788..44e61ec29 100644 --- a/google/cloud/dialogflow_v2/services/fulfillments/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/fulfillments/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -287,5 +286,8 @@ def update_fulfillment( ) return self._stubs["update_fulfillment"] + def close(self): + return self.grpc_channel.close() + __all__ = ("FulfillmentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/intents/async_client.py b/google/cloud/dialogflow_v2/services/intents/async_client.py index 6f175859d..d2c45a7f1 100644 --- a/google/cloud/dialogflow_v2/services/intents/async_client.py +++ b/google/cloud/dialogflow_v2/services/intents/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2.services.intents import pagers @@ -164,11 +169,11 @@ def __init__( async def list_intents( self, - request: intent.ListIntentsRequest = None, + request: Union[intent.ListIntentsRequest, dict] = None, *, parent: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListIntentsAsyncPager: @@ -176,7 +181,7 @@ async def list_intents( agent. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListIntentsRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListIntentsRequest, dict]): The request object. The request message for [Intents.ListIntents][google.cloud.dialogflow.v2.Intents.ListIntents]. parent (:class:`str`): @@ -267,18 +272,18 @@ async def list_intents( async def get_intent( self, - request: intent.GetIntentRequest = None, + request: Union[intent.GetIntentRequest, dict] = None, *, name: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> intent.Intent: r"""Retrieves the specified intent. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetIntentRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetIntentRequest, dict]): The request object. The request message for [Intents.GetIntent][google.cloud.dialogflow.v2.Intents.GetIntent]. name (:class:`str`): @@ -360,12 +365,12 @@ async def get_intent( async def create_intent( self, - request: gcd_intent.CreateIntentRequest = None, + request: Union[gcd_intent.CreateIntentRequest, dict] = None, *, parent: str = None, intent: gcd_intent.Intent = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_intent.Intent: @@ -376,7 +381,7 @@ async def create_intent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateIntentRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateIntentRequest, dict]): The request object. The request message for [Intents.CreateIntent][google.cloud.dialogflow.v2.Intents.CreateIntent]. parent (:class:`str`): @@ -465,12 +470,12 @@ async def create_intent( async def update_intent( self, - request: gcd_intent.UpdateIntentRequest = None, + request: Union[gcd_intent.UpdateIntentRequest, dict] = None, *, intent: gcd_intent.Intent = None, language_code: str = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_intent.Intent: @@ -481,7 +486,7 @@ async def update_intent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateIntentRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateIntentRequest, dict]): The request object. The request message for [Intents.UpdateIntent][google.cloud.dialogflow.v2.Intents.UpdateIntent]. intent (:class:`google.cloud.dialogflow_v2.types.Intent`): @@ -572,10 +577,10 @@ async def update_intent( async def delete_intent( self, - request: intent.DeleteIntentRequest = None, + request: Union[intent.DeleteIntentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -587,7 +592,7 @@ async def delete_intent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteIntentRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteIntentRequest, dict]): The request object. The request message for [Intents.DeleteIntent][google.cloud.dialogflow.v2.Intents.DeleteIntent]. name (:class:`str`): @@ -643,12 +648,12 @@ async def delete_intent( async def batch_update_intents( self, - request: intent.BatchUpdateIntentsRequest = None, + request: Union[intent.BatchUpdateIntentsRequest, dict] = None, *, parent: str = None, intent_batch_uri: str = None, intent_batch_inline: intent.IntentBatch = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -669,7 +674,7 @@ async def batch_update_intents( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.BatchUpdateIntentsRequest`): + request (Union[google.cloud.dialogflow_v2.types.BatchUpdateIntentsRequest, dict]): The request object. parent (:class:`str`): Required. The name of the agent to update or create @@ -763,11 +768,11 @@ async def batch_update_intents( async def batch_delete_intents( self, - request: intent.BatchDeleteIntentsRequest = None, + request: Union[intent.BatchDeleteIntentsRequest, dict] = None, *, parent: str = None, intents: Sequence[intent.Intent] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -788,7 +793,7 @@ async def batch_delete_intents( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.BatchDeleteIntentsRequest`): + request (Union[google.cloud.dialogflow_v2.types.BatchDeleteIntentsRequest, dict]): The request object. The request message for [Intents.BatchDeleteIntents][google.cloud.dialogflow.v2.Intents.BatchDeleteIntents]. parent (:class:`str`): @@ -877,6 +882,12 @@ async def batch_delete_intents( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/intents/client.py b/google/cloud/dialogflow_v2/services/intents/client.py index f6afa3b9a..5e8172392 100644 --- a/google/cloud/dialogflow_v2/services/intents/client.py +++ b/google/cloud/dialogflow_v2/services/intents/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2.services.intents import pagers @@ -299,8 +303,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -362,10 +373,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_intents( @@ -374,7 +382,7 @@ def list_intents( *, parent: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListIntentsPager: @@ -477,7 +485,7 @@ def get_intent( *, name: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> intent.Intent: @@ -571,7 +579,7 @@ def create_intent( parent: str = None, intent: gcd_intent.Intent = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_intent.Intent: @@ -676,7 +684,7 @@ def update_intent( intent: gcd_intent.Intent = None, language_code: str = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_intent.Intent: @@ -781,7 +789,7 @@ def delete_intent( request: Union[intent.DeleteIntentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -854,7 +862,7 @@ def batch_update_intents( parent: str = None, intent_batch_uri: str = None, intent_batch_inline: intent.IntentBatch = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -973,7 +981,7 @@ def batch_delete_intents( *, parent: str = None, intents: Sequence[intent.Intent] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1083,6 +1091,19 @@ def batch_delete_intents( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/intents/transports/base.py b/google/cloud/dialogflow_v2/services/intents/transports/base.py index f2d539e30..b9c2be736 100644 --- a/google/cloud/dialogflow_v2/services/intents/transports/base.py +++ b/google/cloud/dialogflow_v2/services/intents/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore -from google.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -41,15 +40,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class IntentsTransport(abc.ABC): """Abstract transport class for Intents.""" @@ -102,7 +92,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -135,29 +125,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -188,8 +155,17 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/dialogflow_v2/services/intents/transports/grpc.py b/google/cloud/dialogflow_v2/services/intents/transports/grpc.py index d33ae9476..535d1beef 100644 --- a/google/cloud/dialogflow_v2/services/intents/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/intents/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -114,7 +114,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -464,5 +464,8 @@ def batch_delete_intents( ) return self._stubs["batch_delete_intents"] + def close(self): + self.grpc_channel.close() + __all__ = ("IntentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/intents/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/intents/transports/grpc_asyncio.py index 8d2c49c47..f00b01569 100644 --- a/google/cloud/dialogflow_v2/services/intents/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/intents/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore -from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -161,7 +160,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -477,5 +476,8 @@ def batch_delete_intents( ) return self._stubs["batch_delete_intents"] + def close(self): + return self.grpc_channel.close() + __all__ = ("IntentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/knowledge_bases/async_client.py b/google/cloud/dialogflow_v2/services/knowledge_bases/async_client.py index 3a047d909..94212ce28 100644 --- a/google/cloud/dialogflow_v2/services/knowledge_bases/async_client.py +++ b/google/cloud/dialogflow_v2/services/knowledge_bases/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.knowledge_bases import pagers from google.cloud.dialogflow_v2.types import knowledge_base from google.cloud.dialogflow_v2.types import knowledge_base as gcd_knowledge_base @@ -169,10 +174,10 @@ def __init__( async def list_knowledge_bases( self, - request: knowledge_base.ListKnowledgeBasesRequest = None, + request: Union[knowledge_base.ListKnowledgeBasesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListKnowledgeBasesAsyncPager: @@ -180,7 +185,7 @@ async def list_knowledge_bases( specified agent. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListKnowledgeBasesRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListKnowledgeBasesRequest, dict]): The request object. Request message for [KnowledgeBases.ListKnowledgeBases][google.cloud.dialogflow.v2.KnowledgeBases.ListKnowledgeBases]. parent (:class:`str`): @@ -251,17 +256,17 @@ async def list_knowledge_bases( async def get_knowledge_base( self, - request: knowledge_base.GetKnowledgeBaseRequest = None, + request: Union[knowledge_base.GetKnowledgeBaseRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> knowledge_base.KnowledgeBase: r"""Retrieves the specified knowledge base. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetKnowledgeBaseRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetKnowledgeBaseRequest, dict]): The request object. Request message for [KnowledgeBases.GetKnowledgeBase][google.cloud.dialogflow.v2.KnowledgeBases.GetKnowledgeBase]. name (:class:`str`): @@ -333,18 +338,18 @@ async def get_knowledge_base( async def create_knowledge_base( self, - request: gcd_knowledge_base.CreateKnowledgeBaseRequest = None, + request: Union[gcd_knowledge_base.CreateKnowledgeBaseRequest, dict] = None, *, parent: str = None, knowledge_base: gcd_knowledge_base.KnowledgeBase = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_knowledge_base.KnowledgeBase: r"""Creates a knowledge base. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateKnowledgeBaseRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateKnowledgeBaseRequest, dict]): The request object. Request message for [KnowledgeBases.CreateKnowledgeBase][google.cloud.dialogflow.v2.KnowledgeBases.CreateKnowledgeBase]. parent (:class:`str`): @@ -425,17 +430,17 @@ async def create_knowledge_base( async def delete_knowledge_base( self, - request: knowledge_base.DeleteKnowledgeBaseRequest = None, + request: Union[knowledge_base.DeleteKnowledgeBaseRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes the specified knowledge base. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteKnowledgeBaseRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteKnowledgeBaseRequest, dict]): The request object. Request message for [KnowledgeBases.DeleteKnowledgeBase][google.cloud.dialogflow.v2.KnowledgeBases.DeleteKnowledgeBase]. name (:class:`str`): @@ -490,18 +495,18 @@ async def delete_knowledge_base( async def update_knowledge_base( self, - request: gcd_knowledge_base.UpdateKnowledgeBaseRequest = None, + request: Union[gcd_knowledge_base.UpdateKnowledgeBaseRequest, dict] = None, *, knowledge_base: gcd_knowledge_base.KnowledgeBase = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_knowledge_base.KnowledgeBase: r"""Updates the specified knowledge base. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateKnowledgeBaseRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateKnowledgeBaseRequest, dict]): The request object. Request message for [KnowledgeBases.UpdateKnowledgeBase][google.cloud.dialogflow.v2.KnowledgeBases.UpdateKnowledgeBase]. knowledge_base (:class:`google.cloud.dialogflow_v2.types.KnowledgeBase`): @@ -582,6 +587,12 @@ async def update_knowledge_base( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/knowledge_bases/client.py b/google/cloud/dialogflow_v2/services/knowledge_bases/client.py index 3b5b0f0dd..1a55c3256 100644 --- a/google/cloud/dialogflow_v2/services/knowledge_bases/client.py +++ b/google/cloud/dialogflow_v2/services/knowledge_bases/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.knowledge_bases import pagers from google.cloud.dialogflow_v2.types import knowledge_base from google.cloud.dialogflow_v2.types import knowledge_base as gcd_knowledge_base @@ -284,8 +288,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -347,10 +358,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_knowledge_bases( @@ -358,7 +366,7 @@ def list_knowledge_bases( request: Union[knowledge_base.ListKnowledgeBasesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListKnowledgeBasesPager: @@ -440,7 +448,7 @@ def get_knowledge_base( request: Union[knowledge_base.GetKnowledgeBaseRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> knowledge_base.KnowledgeBase: @@ -523,7 +531,7 @@ def create_knowledge_base( *, parent: str = None, knowledge_base: gcd_knowledge_base.KnowledgeBase = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_knowledge_base.KnowledgeBase: @@ -614,7 +622,7 @@ def delete_knowledge_base( request: Union[knowledge_base.DeleteKnowledgeBaseRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -680,7 +688,7 @@ def update_knowledge_base( *, knowledge_base: gcd_knowledge_base.KnowledgeBase = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_knowledge_base.KnowledgeBase: @@ -768,6 +776,19 @@ def update_knowledge_base( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/knowledge_bases/transports/base.py b/google/cloud/dialogflow_v2/services/knowledge_bases/transports/base.py index 8387997bc..05e811e6b 100644 --- a/google/cloud/dialogflow_v2/services/knowledge_bases/transports/base.py +++ b/google/cloud/dialogflow_v2/services/knowledge_bases/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -39,15 +38,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class KnowledgeBasesTransport(abc.ABC): """Abstract transport class for KnowledgeBases.""" @@ -100,7 +90,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -133,29 +123,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -184,6 +151,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_knowledge_bases( self, diff --git a/google/cloud/dialogflow_v2/services/knowledge_bases/transports/grpc.py b/google/cloud/dialogflow_v2/services/knowledge_bases/transports/grpc.py index 0a4abd200..29326befd 100644 --- a/google/cloud/dialogflow_v2/services/knowledge_bases/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/knowledge_bases/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -370,5 +370,8 @@ def update_knowledge_base( ) return self._stubs["update_knowledge_base"] + def close(self): + self.grpc_channel.close() + __all__ = ("KnowledgeBasesGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/knowledge_bases/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/knowledge_bases/transports/grpc_asyncio.py index b07a712f2..ab0698590 100644 --- a/google/cloud/dialogflow_v2/services/knowledge_bases/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/knowledge_bases/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -376,5 +375,8 @@ def update_knowledge_base( ) return self._stubs["update_knowledge_base"] + def close(self): + return self.grpc_channel.close() + __all__ = ("KnowledgeBasesGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/participants/async_client.py b/google/cloud/dialogflow_v2/services/participants/async_client.py index ff13a6d05..0b1f43a3b 100644 --- a/google/cloud/dialogflow_v2/services/participants/async_client.py +++ b/google/cloud/dialogflow_v2/services/participants/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.participants import pagers from google.cloud.dialogflow_v2.types import participant from google.cloud.dialogflow_v2.types import participant as gcd_participant @@ -174,18 +179,18 @@ def __init__( async def create_participant( self, - request: gcd_participant.CreateParticipantRequest = None, + request: Union[gcd_participant.CreateParticipantRequest, dict] = None, *, parent: str = None, participant: gcd_participant.Participant = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.Participant: r"""Creates a new participant in a conversation. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateParticipantRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateParticipantRequest, dict]): The request object. The request message for [Participants.CreateParticipant][google.cloud.dialogflow.v2.Participants.CreateParticipant]. parent (:class:`str`): @@ -254,17 +259,17 @@ async def create_participant( async def get_participant( self, - request: participant.GetParticipantRequest = None, + request: Union[participant.GetParticipantRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.Participant: r"""Retrieves a conversation participant. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetParticipantRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetParticipantRequest, dict]): The request object. The request message for [Participants.GetParticipant][google.cloud.dialogflow.v2.Participants.GetParticipant]. name (:class:`str`): @@ -325,10 +330,10 @@ async def get_participant( async def list_participants( self, - request: participant.ListParticipantsRequest = None, + request: Union[participant.ListParticipantsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListParticipantsAsyncPager: @@ -336,7 +341,7 @@ async def list_participants( conversation. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListParticipantsRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListParticipantsRequest, dict]): The request object. The request message for [Participants.ListParticipants][google.cloud.dialogflow.v2.Participants.ListParticipants]. parent (:class:`str`): @@ -356,7 +361,7 @@ async def list_participants( Returns: google.cloud.dialogflow_v2.services.participants.pagers.ListParticipantsAsyncPager: The response message for - [Participants.ListParticipants][google.cloud.dialogflow.v2.Participants.ListParticipants]. + [Participants.ListParticipants][google.cloud.dialogflow.v2.Participants.ListParticipants]. Iterating over this object will yield results and resolve additional pages automatically. @@ -407,18 +412,18 @@ async def list_participants( async def update_participant( self, - request: gcd_participant.UpdateParticipantRequest = None, + request: Union[gcd_participant.UpdateParticipantRequest, dict] = None, *, participant: gcd_participant.Participant = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.Participant: r"""Updates the specified participant. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateParticipantRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateParticipantRequest, dict]): The request object. The request message for [Participants.UpdateParticipant][google.cloud.dialogflow.v2.Participants.UpdateParticipant]. participant (:class:`google.cloud.dialogflow_v2.types.Participant`): @@ -488,12 +493,12 @@ async def update_participant( async def analyze_content( self, - request: gcd_participant.AnalyzeContentRequest = None, + request: Union[gcd_participant.AnalyzeContentRequest, dict] = None, *, participant: str = None, text_input: session.TextInput = None, event_input: session.EventInput = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.AnalyzeContentResponse: @@ -505,7 +510,7 @@ async def analyze_content( environments `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.AnalyzeContentRequest`): + request (Union[google.cloud.dialogflow_v2.types.AnalyzeContentRequest, dict]): The request object. The request message for [Participants.AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent]. participant (:class:`str`): @@ -537,7 +542,7 @@ async def analyze_content( Returns: google.cloud.dialogflow_v2.types.AnalyzeContentResponse: The response message for - [Participants.AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent]. + [Participants.AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent]. """ # Create or coerce a protobuf request object. @@ -594,10 +599,10 @@ async def analyze_content( async def suggest_articles( self, - request: participant.SuggestArticlesRequest = None, + request: Union[participant.SuggestArticlesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestArticlesResponse: @@ -605,7 +610,7 @@ async def suggest_articles( specific historical messages. Args: - request (:class:`google.cloud.dialogflow_v2.types.SuggestArticlesRequest`): + request (Union[google.cloud.dialogflow_v2.types.SuggestArticlesRequest, dict]): The request object. The request message for [Participants.SuggestArticles][google.cloud.dialogflow.v2.Participants.SuggestArticles]. parent (:class:`str`): @@ -625,7 +630,7 @@ async def suggest_articles( Returns: google.cloud.dialogflow_v2.types.SuggestArticlesResponse: The response message for - [Participants.SuggestArticles][google.cloud.dialogflow.v2.Participants.SuggestArticles]. + [Participants.SuggestArticles][google.cloud.dialogflow.v2.Participants.SuggestArticles]. """ # Create or coerce a protobuf request object. @@ -667,10 +672,10 @@ async def suggest_articles( async def suggest_faq_answers( self, - request: participant.SuggestFaqAnswersRequest = None, + request: Union[participant.SuggestFaqAnswersRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestFaqAnswersResponse: @@ -678,7 +683,7 @@ async def suggest_faq_answers( specific historical messages. Args: - request (:class:`google.cloud.dialogflow_v2.types.SuggestFaqAnswersRequest`): + request (Union[google.cloud.dialogflow_v2.types.SuggestFaqAnswersRequest, dict]): The request object. The request message for [Participants.SuggestFaqAnswers][google.cloud.dialogflow.v2.Participants.SuggestFaqAnswers]. parent (:class:`str`): @@ -698,7 +703,7 @@ async def suggest_faq_answers( Returns: google.cloud.dialogflow_v2.types.SuggestFaqAnswersResponse: The request message for - [Participants.SuggestFaqAnswers][google.cloud.dialogflow.v2.Participants.SuggestFaqAnswers]. + [Participants.SuggestFaqAnswers][google.cloud.dialogflow.v2.Participants.SuggestFaqAnswers]. """ # Create or coerce a protobuf request object. @@ -738,6 +743,12 @@ async def suggest_faq_answers( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/participants/client.py b/google/cloud/dialogflow_v2/services/participants/client.py index 03d020e5e..cf3ab93ed 100644 --- a/google/cloud/dialogflow_v2/services/participants/client.py +++ b/google/cloud/dialogflow_v2/services/participants/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.participants import pagers from google.cloud.dialogflow_v2.types import participant from google.cloud.dialogflow_v2.types import participant as gcd_participant @@ -345,8 +349,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -408,10 +419,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def create_participant( @@ -420,7 +428,7 @@ def create_participant( *, parent: str = None, participant: gcd_participant.Participant = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.Participant: @@ -499,7 +507,7 @@ def get_participant( request: Union[participant.GetParticipantRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.Participant: @@ -570,7 +578,7 @@ def list_participants( request: Union[participant.ListParticipantsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListParticipantsPager: @@ -598,7 +606,7 @@ def list_participants( Returns: google.cloud.dialogflow_v2.services.participants.pagers.ListParticipantsPager: The response message for - [Participants.ListParticipants][google.cloud.dialogflow.v2.Participants.ListParticipants]. + [Participants.ListParticipants][google.cloud.dialogflow.v2.Participants.ListParticipants]. Iterating over this object will yield results and resolve additional pages automatically. @@ -653,7 +661,7 @@ def update_participant( *, participant: gcd_participant.Participant = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.Participant: @@ -735,7 +743,7 @@ def analyze_content( participant: str = None, text_input: session.TextInput = None, event_input: session.EventInput = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.AnalyzeContentResponse: @@ -779,7 +787,7 @@ def analyze_content( Returns: google.cloud.dialogflow_v2.types.AnalyzeContentResponse: The response message for - [Participants.AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent]. + [Participants.AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent]. """ # Create or coerce a protobuf request object. @@ -830,7 +838,7 @@ def suggest_articles( request: Union[participant.SuggestArticlesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestArticlesResponse: @@ -858,7 +866,7 @@ def suggest_articles( Returns: google.cloud.dialogflow_v2.types.SuggestArticlesResponse: The response message for - [Participants.SuggestArticles][google.cloud.dialogflow.v2.Participants.SuggestArticles]. + [Participants.SuggestArticles][google.cloud.dialogflow.v2.Participants.SuggestArticles]. """ # Create or coerce a protobuf request object. @@ -903,7 +911,7 @@ def suggest_faq_answers( request: Union[participant.SuggestFaqAnswersRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestFaqAnswersResponse: @@ -931,7 +939,7 @@ def suggest_faq_answers( Returns: google.cloud.dialogflow_v2.types.SuggestFaqAnswersResponse: The request message for - [Participants.SuggestFaqAnswers][google.cloud.dialogflow.v2.Participants.SuggestFaqAnswers]. + [Participants.SuggestFaqAnswers][google.cloud.dialogflow.v2.Participants.SuggestFaqAnswers]. """ # Create or coerce a protobuf request object. @@ -971,6 +979,19 @@ def suggest_faq_answers( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/participants/transports/base.py b/google/cloud/dialogflow_v2/services/participants/transports/base.py index b31b19626..da5f6cec0 100644 --- a/google/cloud/dialogflow_v2/services/participants/transports/base.py +++ b/google/cloud/dialogflow_v2/services/participants/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class ParticipantsTransport(abc.ABC): """Abstract transport class for Participants.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -192,6 +159,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def create_participant( self, diff --git a/google/cloud/dialogflow_v2/services/participants/transports/grpc.py b/google/cloud/dialogflow_v2/services/participants/transports/grpc.py index ab59e81b5..1b563c0d1 100644 --- a/google/cloud/dialogflow_v2/services/participants/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/participants/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -429,5 +429,8 @@ def suggest_faq_answers( ) return self._stubs["suggest_faq_answers"] + def close(self): + self.grpc_channel.close() + __all__ = ("ParticipantsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/participants/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/participants/transports/grpc_asyncio.py index 3b5bbf9f0..29515cfc9 100644 --- a/google/cloud/dialogflow_v2/services/participants/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/participants/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -440,5 +439,8 @@ def suggest_faq_answers( ) return self._stubs["suggest_faq_answers"] + def close(self): + return self.grpc_channel.close() + __all__ = ("ParticipantsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/session_entity_types/async_client.py b/google/cloud/dialogflow_v2/services/session_entity_types/async_client.py index 738a174d3..54724ee58 100644 --- a/google/cloud/dialogflow_v2/services/session_entity_types/async_client.py +++ b/google/cloud/dialogflow_v2/services/session_entity_types/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.session_entity_types import pagers from google.cloud.dialogflow_v2.types import entity_type from google.cloud.dialogflow_v2.types import session_entity_type @@ -175,10 +180,10 @@ def __init__( async def list_session_entity_types( self, - request: session_entity_type.ListSessionEntityTypesRequest = None, + request: Union[session_entity_type.ListSessionEntityTypesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListSessionEntityTypesAsyncPager: @@ -189,7 +194,7 @@ async def list_session_entity_types( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListSessionEntityTypesRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListSessionEntityTypesRequest, dict]): The request object. The request message for [SessionEntityTypes.ListSessionEntityTypes][google.cloud.dialogflow.v2.SessionEntityTypes.ListSessionEntityTypes]. parent (:class:`str`): @@ -264,10 +269,10 @@ async def list_session_entity_types( async def get_session_entity_type( self, - request: session_entity_type.GetSessionEntityTypeRequest = None, + request: Union[session_entity_type.GetSessionEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> session_entity_type.SessionEntityType: @@ -277,7 +282,7 @@ async def get_session_entity_type( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetSessionEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetSessionEntityTypeRequest, dict]): The request object. The request message for [SessionEntityTypes.GetSessionEntityType][google.cloud.dialogflow.v2.SessionEntityTypes.GetSessionEntityType]. name (:class:`str`): @@ -351,11 +356,13 @@ async def get_session_entity_type( async def create_session_entity_type( self, - request: gcd_session_entity_type.CreateSessionEntityTypeRequest = None, + request: Union[ + gcd_session_entity_type.CreateSessionEntityTypeRequest, dict + ] = None, *, parent: str = None, session_entity_type: gcd_session_entity_type.SessionEntityType = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session_entity_type.SessionEntityType: @@ -368,7 +375,7 @@ async def create_session_entity_type( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateSessionEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateSessionEntityTypeRequest, dict]): The request object. The request message for [SessionEntityTypes.CreateSessionEntityType][google.cloud.dialogflow.v2.SessionEntityTypes.CreateSessionEntityType]. parent (:class:`str`): @@ -451,11 +458,13 @@ async def create_session_entity_type( async def update_session_entity_type( self, - request: gcd_session_entity_type.UpdateSessionEntityTypeRequest = None, + request: Union[ + gcd_session_entity_type.UpdateSessionEntityTypeRequest, dict + ] = None, *, session_entity_type: gcd_session_entity_type.SessionEntityType = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session_entity_type.SessionEntityType: @@ -465,7 +474,7 @@ async def update_session_entity_type( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateSessionEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateSessionEntityTypeRequest, dict]): The request object. The request message for [SessionEntityTypes.UpdateSessionEntityType][google.cloud.dialogflow.v2.SessionEntityTypes.UpdateSessionEntityType]. session_entity_type (:class:`google.cloud.dialogflow_v2.types.SessionEntityType`): @@ -545,10 +554,10 @@ async def update_session_entity_type( async def delete_session_entity_type( self, - request: session_entity_type.DeleteSessionEntityTypeRequest = None, + request: Union[session_entity_type.DeleteSessionEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -558,7 +567,7 @@ async def delete_session_entity_type( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteSessionEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteSessionEntityTypeRequest, dict]): The request object. The request message for [SessionEntityTypes.DeleteSessionEntityType][google.cloud.dialogflow.v2.SessionEntityTypes.DeleteSessionEntityType]. name (:class:`str`): @@ -615,6 +624,12 @@ async def delete_session_entity_type( request, retry=retry, timeout=timeout, metadata=metadata, ) + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/session_entity_types/client.py b/google/cloud/dialogflow_v2/services/session_entity_types/client.py index 03194d780..8039cb70e 100644 --- a/google/cloud/dialogflow_v2/services/session_entity_types/client.py +++ b/google/cloud/dialogflow_v2/services/session_entity_types/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.session_entity_types import pagers from google.cloud.dialogflow_v2.types import entity_type from google.cloud.dialogflow_v2.types import session_entity_type @@ -290,8 +294,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -353,10 +364,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_session_entity_types( @@ -364,7 +372,7 @@ def list_session_entity_types( request: Union[session_entity_type.ListSessionEntityTypesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListSessionEntityTypesPager: @@ -455,7 +463,7 @@ def get_session_entity_type( request: Union[session_entity_type.GetSessionEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> session_entity_type.SessionEntityType: @@ -545,7 +553,7 @@ def create_session_entity_type( *, parent: str = None, session_entity_type: gcd_session_entity_type.SessionEntityType = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session_entity_type.SessionEntityType: @@ -651,7 +659,7 @@ def update_session_entity_type( *, session_entity_type: gcd_session_entity_type.SessionEntityType = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session_entity_type.SessionEntityType: @@ -748,7 +756,7 @@ def delete_session_entity_type( request: Union[session_entity_type.DeleteSessionEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -817,6 +825,19 @@ def delete_session_entity_type( request, retry=retry, timeout=timeout, metadata=metadata, ) + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/session_entity_types/transports/base.py b/google/cloud/dialogflow_v2/services/session_entity_types/transports/base.py index 538b8bc25..c6371b950 100644 --- a/google/cloud/dialogflow_v2/services/session_entity_types/transports/base.py +++ b/google/cloud/dialogflow_v2/services/session_entity_types/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -41,15 +40,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class SessionEntityTypesTransport(abc.ABC): """Abstract transport class for SessionEntityTypes.""" @@ -102,7 +92,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -135,29 +125,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -188,6 +155,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_session_entity_types( self, diff --git a/google/cloud/dialogflow_v2/services/session_entity_types/transports/grpc.py b/google/cloud/dialogflow_v2/services/session_entity_types/transports/grpc.py index 52f38cd97..25e66d09f 100644 --- a/google/cloud/dialogflow_v2/services/session_entity_types/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/session_entity_types/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -393,5 +393,8 @@ def delete_session_entity_type( ) return self._stubs["delete_session_entity_type"] + def close(self): + self.grpc_channel.close() + __all__ = ("SessionEntityTypesGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/session_entity_types/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/session_entity_types/transports/grpc_asyncio.py index d67638595..893df3bd2 100644 --- a/google/cloud/dialogflow_v2/services/session_entity_types/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/session_entity_types/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -396,5 +395,8 @@ def delete_session_entity_type( ) return self._stubs["delete_session_entity_type"] + def close(self): + return self.grpc_channel.close() + __all__ = ("SessionEntityTypesGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/sessions/async_client.py b/google/cloud/dialogflow_v2/services/sessions/async_client.py index dd5dca4cd..04c689479 100644 --- a/google/cloud/dialogflow_v2/services/sessions/async_client.py +++ b/google/cloud/dialogflow_v2/services/sessions/async_client.py @@ -28,13 +28,18 @@ ) import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.types import audio_config from google.cloud.dialogflow_v2.types import session from google.cloud.dialogflow_v2.types import session as gcd_session @@ -178,11 +183,11 @@ def __init__( async def detect_intent( self, - request: gcd_session.DetectIntentRequest = None, + request: Union[gcd_session.DetectIntentRequest, dict] = None, *, session: str = None, query_input: gcd_session.QueryInput = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session.DetectIntentResponse: @@ -191,12 +196,19 @@ async def detect_intent( because it may cause contexts and session entity types to be updated, which in turn might affect results of future queries. + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent] + instead of ``DetectIntent``. ``AnalyzeContent`` has additional + functionality for Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. Args: - request (:class:`google.cloud.dialogflow_v2.types.DetectIntentRequest`): + request (Union[google.cloud.dialogflow_v2.types.DetectIntentRequest, dict]): The request object. The request to detect user's intent. session (:class:`str`): Required. The name of the session this query is sent to. @@ -303,7 +315,7 @@ def streaming_detect_intent( self, requests: AsyncIterator[session.StreamingDetectIntentRequest] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> Awaitable[AsyncIterable[session.StreamingDetectIntentResponse]]: @@ -312,6 +324,14 @@ def streaming_detect_intent( result. This method is only available via the gRPC API (not REST). + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [StreamingAnalyzeContent][google.cloud.dialogflow.v2.Participants.StreamingAnalyzeContent] + instead of ``StreamingDetectIntent``. + ``StreamingAnalyzeContent`` has additional functionality for + Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -367,11 +387,12 @@ def streaming_detect_intent( Multiple response messages can be returned in order: - 1. If the input was set to streaming audio, the first - one or more messages contain recognition_result. - Each recognition_result represents a more complete - transcript of what the user said. The last - recognition_result has is_final set to true. + 1. If the StreamingDetectIntentRequest.input_audio + field was set, the recognition_result field is + populated for one or more messages. See the + [StreamingRecognitionResult][google.cloud.dialogflow.v2.StreamingRecognitionResult] + message for details about the result message + sequence. 2. The next message contains response_id, query_result and optionally webhook_status if a WebHook was called. @@ -392,6 +413,12 @@ def streaming_detect_intent( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/sessions/client.py b/google/cloud/dialogflow_v2/services/sessions/client.py index 23cba476e..c65914fe1 100644 --- a/google/cloud/dialogflow_v2/services/sessions/client.py +++ b/google/cloud/dialogflow_v2/services/sessions/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Iterable, Iterator, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.types import audio_config from google.cloud.dialogflow_v2.types import session from google.cloud.dialogflow_v2.types import session as gcd_session @@ -329,8 +333,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -392,10 +403,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def detect_intent( @@ -404,7 +412,7 @@ def detect_intent( *, session: str = None, query_input: gcd_session.QueryInput = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session.DetectIntentResponse: @@ -413,6 +421,13 @@ def detect_intent( because it may cause contexts and session entity types to be updated, which in turn might affect results of future queries. + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent] + instead of ``DetectIntent``. ``AnalyzeContent`` has additional + functionality for Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -516,7 +531,7 @@ def streaming_detect_intent( self, requests: Iterator[session.StreamingDetectIntentRequest] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> Iterable[session.StreamingDetectIntentResponse]: @@ -525,6 +540,14 @@ def streaming_detect_intent( result. This method is only available via the gRPC API (not REST). + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [StreamingAnalyzeContent][google.cloud.dialogflow.v2.Participants.StreamingAnalyzeContent] + instead of ``StreamingDetectIntent``. + ``StreamingAnalyzeContent`` has additional functionality for + Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -580,11 +603,12 @@ def streaming_detect_intent( Multiple response messages can be returned in order: - 1. If the input was set to streaming audio, the first - one or more messages contain recognition_result. - Each recognition_result represents a more complete - transcript of what the user said. The last - recognition_result has is_final set to true. + 1. If the StreamingDetectIntentRequest.input_audio + field was set, the recognition_result field is + populated for one or more messages. See the + [StreamingRecognitionResult][google.cloud.dialogflow.v2.StreamingRecognitionResult] + message for details about the result message + sequence. 2. The next message contains response_id, query_result and optionally webhook_status if a WebHook was called. @@ -601,6 +625,19 @@ def streaming_detect_intent( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/sessions/transports/base.py b/google/cloud/dialogflow_v2/services/sessions/transports/base.py index 8f7a7a2ea..51a759243 100644 --- a/google/cloud/dialogflow_v2/services/sessions/transports/base.py +++ b/google/cloud/dialogflow_v2/services/sessions/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class SessionsTransport(abc.ABC): """Abstract transport class for Sessions.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -179,6 +146,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def detect_intent( self, diff --git a/google/cloud/dialogflow_v2/services/sessions/transports/grpc.py b/google/cloud/dialogflow_v2/services/sessions/transports/grpc.py index 0f496e5a7..35cf289d1 100644 --- a/google/cloud/dialogflow_v2/services/sessions/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/sessions/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -240,6 +240,13 @@ def detect_intent( because it may cause contexts and session entity types to be updated, which in turn might affect results of future queries. + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent] + instead of ``DetectIntent``. ``AnalyzeContent`` has additional + functionality for Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -275,6 +282,14 @@ def streaming_detect_intent( result. This method is only available via the gRPC API (not REST). + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [StreamingAnalyzeContent][google.cloud.dialogflow.v2.Participants.StreamingAnalyzeContent] + instead of ``StreamingDetectIntent``. + ``StreamingAnalyzeContent`` has additional functionality for + Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -297,5 +312,8 @@ def streaming_detect_intent( ) return self._stubs["streaming_detect_intent"] + def close(self): + self.grpc_channel.close() + __all__ = ("SessionsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/sessions/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/sessions/transports/grpc_asyncio.py index e230d4965..36a81b430 100644 --- a/google/cloud/dialogflow_v2/services/sessions/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/sessions/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -245,6 +244,13 @@ def detect_intent( because it may cause contexts and session entity types to be updated, which in turn might affect results of future queries. + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent] + instead of ``DetectIntent``. ``AnalyzeContent`` has additional + functionality for Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -281,6 +287,14 @@ def streaming_detect_intent( result. This method is only available via the gRPC API (not REST). + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [StreamingAnalyzeContent][google.cloud.dialogflow.v2.Participants.StreamingAnalyzeContent] + instead of ``StreamingDetectIntent``. + ``StreamingAnalyzeContent`` has additional functionality for + Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -303,5 +317,8 @@ def streaming_detect_intent( ) return self._stubs["streaming_detect_intent"] + def close(self): + return self.grpc_channel.close() + __all__ = ("SessionsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/services/versions/async_client.py b/google/cloud/dialogflow_v2/services/versions/async_client.py index 395c6b0d4..7f54e20b0 100644 --- a/google/cloud/dialogflow_v2/services/versions/async_client.py +++ b/google/cloud/dialogflow_v2/services/versions/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.versions import pagers from google.cloud.dialogflow_v2.types import version from google.cloud.dialogflow_v2.types import version as gcd_version @@ -158,10 +163,10 @@ def __init__( async def list_versions( self, - request: version.ListVersionsRequest = None, + request: Union[version.ListVersionsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListVersionsAsyncPager: @@ -169,7 +174,7 @@ async def list_versions( agent. Args: - request (:class:`google.cloud.dialogflow_v2.types.ListVersionsRequest`): + request (Union[google.cloud.dialogflow_v2.types.ListVersionsRequest, dict]): The request object. The request message for [Versions.ListVersions][google.cloud.dialogflow.v2.Versions.ListVersions]. parent (:class:`str`): @@ -242,17 +247,17 @@ async def list_versions( async def get_version( self, - request: version.GetVersionRequest = None, + request: Union[version.GetVersionRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> version.Version: r"""Retrieves the specified agent version. Args: - request (:class:`google.cloud.dialogflow_v2.types.GetVersionRequest`): + request (Union[google.cloud.dialogflow_v2.types.GetVersionRequest, dict]): The request object. The request message for [Versions.GetVersion][google.cloud.dialogflow.v2.Versions.GetVersion]. name (:class:`str`): @@ -334,11 +339,11 @@ async def get_version( async def create_version( self, - request: gcd_version.CreateVersionRequest = None, + request: Union[gcd_version.CreateVersionRequest, dict] = None, *, parent: str = None, version: gcd_version.Version = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_version.Version: @@ -347,7 +352,7 @@ async def create_version( "default" environment. Args: - request (:class:`google.cloud.dialogflow_v2.types.CreateVersionRequest`): + request (Union[google.cloud.dialogflow_v2.types.CreateVersionRequest, dict]): The request object. The request message for [Versions.CreateVersion][google.cloud.dialogflow.v2.Versions.CreateVersion]. parent (:class:`str`): @@ -437,11 +442,11 @@ async def create_version( async def update_version( self, - request: gcd_version.UpdateVersionRequest = None, + request: Union[gcd_version.UpdateVersionRequest, dict] = None, *, version: gcd_version.Version = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_version.Version: @@ -452,7 +457,7 @@ async def update_version( version resource. Args: - request (:class:`google.cloud.dialogflow_v2.types.UpdateVersionRequest`): + request (Union[google.cloud.dialogflow_v2.types.UpdateVersionRequest, dict]): The request object. The request message for [Versions.UpdateVersion][google.cloud.dialogflow.v2.Versions.UpdateVersion]. version (:class:`google.cloud.dialogflow_v2.types.Version`): @@ -545,17 +550,17 @@ async def update_version( async def delete_version( self, - request: version.DeleteVersionRequest = None, + request: Union[version.DeleteVersionRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Delete the specified agent version. Args: - request (:class:`google.cloud.dialogflow_v2.types.DeleteVersionRequest`): + request (Union[google.cloud.dialogflow_v2.types.DeleteVersionRequest, dict]): The request object. The request message for [Versions.DeleteVersion][google.cloud.dialogflow.v2.Versions.DeleteVersion]. name (:class:`str`): @@ -610,6 +615,12 @@ async def delete_version( request, retry=retry, timeout=timeout, metadata=metadata, ) + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/versions/client.py b/google/cloud/dialogflow_v2/services/versions/client.py index ca4b4c264..90e7198dd 100644 --- a/google/cloud/dialogflow_v2/services/versions/client.py +++ b/google/cloud/dialogflow_v2/services/versions/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2.services.versions import pagers from google.cloud.dialogflow_v2.types import version from google.cloud.dialogflow_v2.types import version as gcd_version @@ -281,8 +285,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -344,10 +355,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_versions( @@ -355,7 +363,7 @@ def list_versions( request: Union[version.ListVersionsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListVersionsPager: @@ -439,7 +447,7 @@ def get_version( request: Union[version.GetVersionRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> version.Version: @@ -532,7 +540,7 @@ def create_version( *, parent: str = None, version: gcd_version.Version = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_version.Version: @@ -635,7 +643,7 @@ def update_version( *, version: gcd_version.Version = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_version.Version: @@ -742,7 +750,7 @@ def delete_version( request: Union[version.DeleteVersionRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -804,6 +812,19 @@ def delete_version( request, retry=retry, timeout=timeout, metadata=metadata, ) + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2/services/versions/transports/base.py b/google/cloud/dialogflow_v2/services/versions/transports/base.py index 94464d5cd..bb2a24d9b 100644 --- a/google/cloud/dialogflow_v2/services/versions/transports/base.py +++ b/google/cloud/dialogflow_v2/services/versions/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -39,15 +38,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class VersionsTransport(abc.ABC): """Abstract transport class for Versions.""" @@ -100,7 +90,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -133,29 +123,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -176,6 +143,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_versions( self, diff --git a/google/cloud/dialogflow_v2/services/versions/transports/grpc.py b/google/cloud/dialogflow_v2/services/versions/transports/grpc.py index 4163e690b..9a329b204 100644 --- a/google/cloud/dialogflow_v2/services/versions/transports/grpc.py +++ b/google/cloud/dialogflow_v2/services/versions/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -362,5 +362,8 @@ def delete_version( ) return self._stubs["delete_version"] + def close(self): + self.grpc_channel.close() + __all__ = ("VersionsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2/services/versions/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2/services/versions/transports/grpc_asyncio.py index 9618017e5..492f1ed54 100644 --- a/google/cloud/dialogflow_v2/services/versions/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2/services/versions/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -369,5 +368,8 @@ def delete_version( ) return self._stubs["delete_version"] + def close(self): + return self.grpc_channel.close() + __all__ = ("VersionsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2/types/__init__.py b/google/cloud/dialogflow_v2/types/__init__.py index 7426db72a..b8a99fdb8 100644 --- a/google/cloud/dialogflow_v2/types/__init__.py +++ b/google/cloud/dialogflow_v2/types/__init__.py @@ -159,6 +159,7 @@ AnalyzeContentResponse, AnnotatedMessagePart, ArticleAnswer, + AssistQueryParameters, AutomatedAgentReply, CreateParticipantRequest, DtmfParameters, @@ -342,6 +343,7 @@ "AnalyzeContentResponse", "AnnotatedMessagePart", "ArticleAnswer", + "AssistQueryParameters", "AutomatedAgentReply", "CreateParticipantRequest", "DtmfParameters", diff --git a/google/cloud/dialogflow_v2/types/agent.py b/google/cloud/dialogflow_v2/types/agent.py index 7cee91fec..049e9e28d 100644 --- a/google/cloud/dialogflow_v2/types/agent.py +++ b/google/cloud/dialogflow_v2/types/agent.py @@ -269,13 +269,24 @@ class ExportAgentResponse(proto.Message): r"""The response message for [Agents.ExportAgent][google.cloud.dialogflow.v2.Agents.ExportAgent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: agent_uri (str): The URI to a file containing the exported agent. This field is populated only if ``agent_uri`` is specified in ``ExportAgentRequest``. + + This field is a member of `oneof`_ ``agent``. agent_content (bytes): Zip compressed raw byte content for agent. + + This field is a member of `oneof`_ ``agent``. """ agent_uri = proto.Field(proto.STRING, number=1, oneof="agent",) @@ -286,6 +297,13 @@ class ImportAgentRequest(proto.Message): r"""The request message for [Agents.ImportAgent][google.cloud.dialogflow.v2.Agents.ImportAgent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: parent (str): Required. The project that the agent to import is associated @@ -294,8 +312,12 @@ class ImportAgentRequest(proto.Message): The URI to a Google Cloud Storage file containing the agent to import. Note: The URI must start with "gs://". + + This field is a member of `oneof`_ ``agent``. agent_content (bytes): Zip compressed raw byte content for agent. + + This field is a member of `oneof`_ ``agent``. """ parent = proto.Field(proto.STRING, number=1,) @@ -307,6 +329,13 @@ class RestoreAgentRequest(proto.Message): r"""The request message for [Agents.RestoreAgent][google.cloud.dialogflow.v2.Agents.RestoreAgent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: parent (str): Required. The project that the agent to restore is @@ -315,8 +344,12 @@ class RestoreAgentRequest(proto.Message): The URI to a Google Cloud Storage file containing the agent to restore. Note: The URI must start with "gs://". + + This field is a member of `oneof`_ ``agent``. agent_content (bytes): Zip compressed raw byte content for agent. + + This field is a member of `oneof`_ ``agent``. """ parent = proto.Field(proto.STRING, number=1,) diff --git a/google/cloud/dialogflow_v2/types/answer_record.py b/google/cloud/dialogflow_v2/types/answer_record.py index 92a8accd9..dc41aa89c 100644 --- a/google/cloud/dialogflow_v2/types/answer_record.py +++ b/google/cloud/dialogflow_v2/types/answer_record.py @@ -64,6 +64,9 @@ class AnswerRecord(proto.Message): to call the [UpdateAnswerRecord][] method to send feedback about a specific answer that they believe is wrong. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): The unique identifier of this answer record. Format: @@ -76,6 +79,8 @@ class AnswerRecord(proto.Message): agent_assistant_record (google.cloud.dialogflow_v2.types.AgentAssistantRecord): Output only. The record for human agent assistant. + + This field is a member of `oneof`_ ``record``. """ name = proto.Field(proto.STRING, number=1,) @@ -167,11 +172,16 @@ class AnswerFeedback(proto.Message): r"""Represents feedback the customer has about the quality & correctness of a certain answer in a conversation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: correctness_level (google.cloud.dialogflow_v2.types.AnswerFeedback.CorrectnessLevel): The correctness level of the specific answer. agent_assistant_detail_feedback (google.cloud.dialogflow_v2.types.AgentAssistantFeedback): Detail feedback of agent assist suggestions. + + This field is a member of `oneof`_ ``detail_feedback``. clicked (bool): Indicates whether the answer/item was clicked by the human agent or not. Default to false. @@ -209,6 +219,7 @@ class CorrectnessLevel(proto.Enum): class AgentAssistantFeedback(proto.Message): r"""Detail feedback of Agent Assist result. + Attributes: answer_relevance (google.cloud.dialogflow_v2.types.AgentAssistantFeedback.AnswerRelevance): Optional. Whether or not the suggested answer is relevant. @@ -267,11 +278,23 @@ class DocumentEfficiency(proto.Enum): class AgentAssistantRecord(proto.Message): r"""Represents a record of a human agent assist answer. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: article_suggestion_answer (google.cloud.dialogflow_v2.types.ArticleAnswer): Output only. The article suggestion answer. + + This field is a member of `oneof`_ ``answer``. faq_answer (google.cloud.dialogflow_v2.types.FaqAnswer): Output only. The FAQ answer. + + This field is a member of `oneof`_ ``answer``. """ article_suggestion_answer = proto.Field( diff --git a/google/cloud/dialogflow_v2/types/audio_config.py b/google/cloud/dialogflow_v2/types/audio_config.py index 5cca3a22f..d3204c5ef 100644 --- a/google/cloud/dialogflow_v2/types/audio_config.py +++ b/google/cloud/dialogflow_v2/types/audio_config.py @@ -130,6 +130,7 @@ class SpeechContext(proto.Message): class SpeechWordInfo(proto.Message): r"""Information for a word recognized by the speech recognizer. + Attributes: word (str): The word this info is for. @@ -261,6 +262,7 @@ class InputAudioConfig(proto.Message): class VoiceSelectionParams(proto.Message): r"""Description of which voice to use for speech synthesis. + Attributes: name (str): Optional. The name of the voice. If not set, the service @@ -284,6 +286,7 @@ class VoiceSelectionParams(proto.Message): class SynthesizeSpeechConfig(proto.Message): r"""Configuration of how speech should be synthesized. + Attributes: speaking_rate (float): Optional. Speaking rate/speed, in the range [0.25, 4.0]. 1.0 diff --git a/google/cloud/dialogflow_v2/types/conversation_event.py b/google/cloud/dialogflow_v2/types/conversation_event.py index 193259b4f..1cfe75115 100644 --- a/google/cloud/dialogflow_v2/types/conversation_event.py +++ b/google/cloud/dialogflow_v2/types/conversation_event.py @@ -28,6 +28,9 @@ class ConversationEvent(proto.Message): r"""Represents a notification sent to Pub/Sub subscribers for conversation lifecycle events. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: conversation (str): The unique identifier of the conversation this notification @@ -41,6 +44,8 @@ class ConversationEvent(proto.Message): UNRECOVERABLE_ERROR_IN_PHONE_CALL. new_message_payload (google.cloud.dialogflow_v2.types.Message): Payload of NEW_MESSAGE event. + + This field is a member of `oneof`_ ``payload``. """ class Type(proto.Enum): diff --git a/google/cloud/dialogflow_v2/types/conversation_profile.py b/google/cloud/dialogflow_v2/types/conversation_profile.py index b7022be1b..dc029305c 100644 --- a/google/cloud/dialogflow_v2/types/conversation_profile.py +++ b/google/cloud/dialogflow_v2/types/conversation_profile.py @@ -80,11 +80,21 @@ class ConversationProfile(proto.Message): stt_config (google.cloud.dialogflow_v2.types.SpeechToTextConfig): Settings for speech transcription. language_code (str): - Language which represents the - conversationProfile. If unspecified, the default - language code en-us applies. Users need to - create a ConversationProfile for each language - they want to support. + Language code for the conversation profile. If not + specified, the language is en-US. Language at + ConversationProfile should be set for all non en-US + languages. This should be a + `BCP-47 `__ + language tag. Example: "en-US". + time_zone (str): + The time zone of this conversational profile from the `time + zone database `__, e.g., + America/New_York, Europe/Paris. Defaults to + America/New_York. + security_settings (str): + Name of the CX SecuritySettings reference for the agent. + Format: + ``projects//locations//securitySettings/``. """ name = proto.Field(proto.STRING, number=1,) @@ -115,6 +125,8 @@ class ConversationProfile(proto.Message): proto.MESSAGE, number=9, message=audio_config.SpeechToTextConfig, ) language_code = proto.Field(proto.STRING, number=10,) + time_zone = proto.Field(proto.STRING, number=14,) + security_settings = proto.Field(proto.STRING, number=13,) class ListConversationProfilesRequest(proto.Message): @@ -235,6 +247,7 @@ class DeleteConversationProfileRequest(proto.Message): class AutomatedAgentConfig(proto.Message): r"""Defines the Automated Agent to connect to a conversation. + Attributes: agent (str): Required. ID of the Dialogflow agent environment to use. @@ -244,12 +257,17 @@ class AutomatedAgentConfig(proto.Message): ``service-@gcp-sa-dialogflow.iam.gserviceaccount.com`` the ``Dialogflow API Service Agent`` role in this project. - Format: - ``projects//locations//agent/environments/``. - If environment is not specified, the default ``draft`` - environment is used. Refer to - `DetectIntentRequest `__ - for more details. + - For ES agents, use format: + ``projects//locations//agent/environments/``. + If environment is not specified, the default ``draft`` + environment is used. Refer to + `DetectIntentRequest `__ + for more details. + + - For CX agents, use format + ``projects//locations//agents//environments/``. + If environment is not specified, the default ``draft`` + environment is used. """ agent = proto.Field(proto.STRING, number=1,) @@ -257,6 +275,7 @@ class AutomatedAgentConfig(proto.Message): class HumanAgentAssistantConfig(proto.Message): r"""Defines the Human Agent Assist to connect to a conversation. + Attributes: notification_config (google.cloud.dialogflow_v2.types.NotificationConfig): Pub/Sub topic on which to publish new agent @@ -275,6 +294,7 @@ class HumanAgentAssistantConfig(proto.Message): class SuggestionTriggerSettings(proto.Message): r"""Settings of suggestion trigger. + Attributes: no_smalltalk (bool): Do not trigger if last utterance is small @@ -289,6 +309,7 @@ class SuggestionTriggerSettings(proto.Message): class SuggestionFeatureConfig(proto.Message): r"""Config for suggestion features. + Attributes: suggestion_feature (google.cloud.dialogflow_v2.types.SuggestionFeature): The suggestion feature. @@ -331,6 +352,7 @@ class SuggestionFeatureConfig(proto.Message): class SuggestionConfig(proto.Message): r"""Detail human agent assistant config. + Attributes: feature_configs (Sequence[google.cloud.dialogflow_v2.types.HumanAgentAssistantConfig.SuggestionFeatureConfig]): Configuration of different suggestion @@ -359,16 +381,30 @@ class SuggestionConfig(proto.Message): class SuggestionQueryConfig(proto.Message): r"""Config for suggestion query. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: knowledge_base_query_source (google.cloud.dialogflow_v2.types.HumanAgentAssistantConfig.SuggestionQueryConfig.KnowledgeBaseQuerySource): Query from knowledgebase. It is used by: ARTICLE_SUGGESTION, FAQ. + + This field is a member of `oneof`_ ``query_source``. document_query_source (google.cloud.dialogflow_v2.types.HumanAgentAssistantConfig.SuggestionQueryConfig.DocumentQuerySource): Query from knowledge base document. It is used by: SMART_REPLY, SMART_COMPOSE. + + This field is a member of `oneof`_ ``query_source``. dialogflow_query_source (google.cloud.dialogflow_v2.types.HumanAgentAssistantConfig.SuggestionQueryConfig.DialogflowQuerySource): Query from Dialogflow agent. It is used by DIALOGFLOW_ASSIST. + + This field is a member of `oneof`_ ``query_source``. max_results (int): Maximum number of results to return. Currently, if unset, defaults to 10. And the max @@ -393,7 +429,8 @@ class SuggestionQueryConfig(proto.Message): If this field is not set, it defaults to 0.0, which means that all suggestions are returned. - Supported features: ARTICLE_SUGGESTION. + Supported features: ARTICLE_SUGGESTION, FAQ, SMART_REPLY, + SMART_COMPOSE. context_filter_settings (google.cloud.dialogflow_v2.types.HumanAgentAssistantConfig.SuggestionQueryConfig.ContextFilterSettings): Determines how recent conversation context is filtered when generating suggestions. If @@ -565,11 +602,22 @@ class HumanAgentHandoffConfig(proto.Message): Currently, this feature is not general available, please contact Google to get access. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: live_person_config (google.cloud.dialogflow_v2.types.HumanAgentHandoffConfig.LivePersonConfig): Uses LivePerson (https://www.liveperson.com). + + This field is a member of `oneof`_ ``agent_service``. salesforce_live_agent_config (google.cloud.dialogflow_v2.types.HumanAgentHandoffConfig.SalesforceLiveAgentConfig): Uses Salesforce Live Agent. + + This field is a member of `oneof`_ ``agent_service``. """ class LivePersonConfig(proto.Message): @@ -587,6 +635,7 @@ class LivePersonConfig(proto.Message): class SalesforceLiveAgentConfig(proto.Message): r"""Configuration specific to Salesforce Live Agent. + Attributes: organization_id (str): Required. The organization ID of the @@ -621,6 +670,7 @@ class SalesforceLiveAgentConfig(proto.Message): class NotificationConfig(proto.Message): r"""Defines notification behavior. + Attributes: topic (str): Name of the Pub/Sub topic to publish conversation events @@ -653,6 +703,7 @@ class MessageFormat(proto.Enum): class LoggingConfig(proto.Message): r"""Defines logging behavior for conversation lifecycle events. + Attributes: enable_stackdriver_logging (bool): Whether to log conversation events like @@ -681,6 +732,7 @@ class Type(proto.Enum): TYPE_UNSPECIFIED = 0 ARTICLE_SUGGESTION = 1 FAQ = 2 + SMART_REPLY = 3 type_ = proto.Field(proto.ENUM, number=1, enum=Type,) diff --git a/google/cloud/dialogflow_v2/types/document.py b/google/cloud/dialogflow_v2/types/document.py index c65907b64..7c82e11b3 100644 --- a/google/cloud/dialogflow_v2/types/document.py +++ b/google/cloud/dialogflow_v2/types/document.py @@ -46,6 +46,13 @@ class Document(proto.Message): Note: The ``projects.agent.knowledgeBases.documents`` resource is deprecated; only use ``projects.knowledgeBases.documents``. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): Optional. The document resource name. The name must be empty @@ -71,9 +78,13 @@ class Document(proto.Message): URLs for showing documents in Google Cloud Storage (i.e. the URL in your browser) are not supported. Instead use the ``gs://`` format URI described above. + + This field is a member of `oneof`_ ``source``. raw_content (bytes): The raw content of the document. This field is only permitted for EXTRACTIVE_QA and FAQ knowledge types. + + This field is a member of `oneof`_ ``source``. enable_auto_reload (bool): Optional. If true, we try to automatically reload the document every day (at a time picked by the system). If @@ -115,6 +126,7 @@ class KnowledgeType(proto.Enum): class ReloadStatus(proto.Message): r"""The status of a reload attempt. + Attributes: time (google.protobuf.timestamp_pb2.Timestamp): The time of a reload attempt. @@ -249,6 +261,9 @@ class ReloadDocumentRequest(proto.Message): r"""Request message for [Documents.ReloadDocument][google.cloud.dialogflow.v2.Documents.ReloadDocument]. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): Required. The name of the document to reload. Format: @@ -259,6 +274,8 @@ class ReloadDocumentRequest(proto.Message): For documents stored in Google Cloud Storage, these URIs must have the form ``gs:///``. + + This field is a member of `oneof`_ ``source``. """ name = proto.Field(proto.STRING, number=1,) diff --git a/google/cloud/dialogflow_v2/types/entity_type.py b/google/cloud/dialogflow_v2/types/entity_type.py index acb5cece1..7b5edaa63 100644 --- a/google/cloud/dialogflow_v2/types/entity_type.py +++ b/google/cloud/dialogflow_v2/types/entity_type.py @@ -95,6 +95,7 @@ class AutoExpansionMode(proto.Enum): class Entity(proto.Message): r"""An **entity entry** for an associated entity type. + Attributes: value (str): Required. The primary value associated with this entity @@ -268,6 +269,13 @@ class BatchUpdateEntityTypesRequest(proto.Message): r"""The request message for [EntityTypes.BatchUpdateEntityTypes][google.cloud.dialogflow.v2.EntityTypes.BatchUpdateEntityTypes]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: parent (str): Required. The name of the agent to update or create entity @@ -278,9 +286,13 @@ class BatchUpdateEntityTypesRequest(proto.Message): file format can either be a serialized proto (of EntityBatch type) or a JSON object. Note: The URI must start with "gs://". + + This field is a member of `oneof`_ ``entity_type_batch``. entity_type_batch_inline (google.cloud.dialogflow_v2.types.EntityTypeBatch): The collection of entity types to update or create. + + This field is a member of `oneof`_ ``entity_type_batch``. language_code (str): Optional. The language used to access language-specific data. If not specified, the agent's default language is diff --git a/google/cloud/dialogflow_v2/types/environment.py b/google/cloud/dialogflow_v2/types/environment.py index 1beb7ed50..63b3872aa 100644 --- a/google/cloud/dialogflow_v2/types/environment.py +++ b/google/cloud/dialogflow_v2/types/environment.py @@ -343,6 +343,7 @@ class EnvironmentHistory(proto.Message): class Entry(proto.Message): r"""Represents an environment history entry. + Attributes: agent_version (str): The agent version loaded into this diff --git a/google/cloud/dialogflow_v2/types/fulfillment.py b/google/cloud/dialogflow_v2/types/fulfillment.py index c867a5c3f..8a40dc83b 100644 --- a/google/cloud/dialogflow_v2/types/fulfillment.py +++ b/google/cloud/dialogflow_v2/types/fulfillment.py @@ -36,6 +36,9 @@ class Fulfillment(proto.Message): For more information, see the `fulfillment guide `__. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): Required. The unique identifier of the fulfillment. @@ -52,6 +55,8 @@ class Fulfillment(proto.Message): Environment. generic_web_service (google.cloud.dialogflow_v2.types.Fulfillment.GenericWebService): Configuration for a generic web service. + + This field is a member of `oneof`_ ``fulfillment``. enabled (bool): Optional. Whether fulfillment is enabled. features (Sequence[google.cloud.dialogflow_v2.types.Fulfillment.Feature]): @@ -96,6 +101,7 @@ class GenericWebService(proto.Message): class Feature(proto.Message): r"""Whether fulfillment is enabled for the specific feature. + Attributes: type_ (google.cloud.dialogflow_v2.types.Fulfillment.Feature.Type): The type of the feature that enabled for diff --git a/google/cloud/dialogflow_v2/types/intent.py b/google/cloud/dialogflow_v2/types/intent.py index a71b07449..aafe6ca9d 100644 --- a/google/cloud/dialogflow_v2/types/intent.py +++ b/google/cloud/dialogflow_v2/types/intent.py @@ -175,6 +175,7 @@ class WebhookState(proto.Enum): class TrainingPhrase(proto.Message): r"""Represents an example that the agent is trained on. + Attributes: name (str): Output only. The unique identifier of this @@ -221,6 +222,7 @@ class Type(proto.Enum): class Part(proto.Message): r"""Represents a part of a training phrase. + Attributes: text (str): Required. The text for this part. @@ -255,6 +257,7 @@ class Part(proto.Message): class Parameter(proto.Message): r"""Represents intent parameters. + Attributes: name (str): The unique identifier of this parameter. @@ -307,39 +310,74 @@ class Message(proto.Message): response messages `__. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: text (google.cloud.dialogflow_v2.types.Intent.Message.Text): The text response. + + This field is a member of `oneof`_ ``message``. image (google.cloud.dialogflow_v2.types.Intent.Message.Image): The image response. + + This field is a member of `oneof`_ ``message``. quick_replies (google.cloud.dialogflow_v2.types.Intent.Message.QuickReplies): The quick replies response. + + This field is a member of `oneof`_ ``message``. card (google.cloud.dialogflow_v2.types.Intent.Message.Card): The card response. + + This field is a member of `oneof`_ ``message``. payload (google.protobuf.struct_pb2.Struct): A custom platform-specific response. + + This field is a member of `oneof`_ ``message``. simple_responses (google.cloud.dialogflow_v2.types.Intent.Message.SimpleResponses): The voice and text-only responses for Actions on Google. + + This field is a member of `oneof`_ ``message``. basic_card (google.cloud.dialogflow_v2.types.Intent.Message.BasicCard): The basic card response for Actions on Google. + + This field is a member of `oneof`_ ``message``. suggestions (google.cloud.dialogflow_v2.types.Intent.Message.Suggestions): The suggestion chips for Actions on Google. + + This field is a member of `oneof`_ ``message``. link_out_suggestion (google.cloud.dialogflow_v2.types.Intent.Message.LinkOutSuggestion): The link out suggestion chip for Actions on Google. + + This field is a member of `oneof`_ ``message``. list_select (google.cloud.dialogflow_v2.types.Intent.Message.ListSelect): The list card response for Actions on Google. + + This field is a member of `oneof`_ ``message``. carousel_select (google.cloud.dialogflow_v2.types.Intent.Message.CarouselSelect): The carousel card response for Actions on Google. + + This field is a member of `oneof`_ ``message``. browse_carousel_card (google.cloud.dialogflow_v2.types.Intent.Message.BrowseCarouselCard): Browse carousel card for Actions on Google. + + This field is a member of `oneof`_ ``message``. table_card (google.cloud.dialogflow_v2.types.Intent.Message.TableCard): Table card for Actions on Google. + + This field is a member of `oneof`_ ``message``. media_content (google.cloud.dialogflow_v2.types.Intent.Message.MediaContent): The media content card for Actions on Google. + + This field is a member of `oneof`_ ``message``. platform (google.cloud.dialogflow_v2.types.Intent.Message.Platform): Optional. The platform that this message is intended for. @@ -362,6 +400,7 @@ class Platform(proto.Enum): class Text(proto.Message): r"""The text response message. + Attributes: text (Sequence[str]): Optional. The collection of the agent's @@ -372,6 +411,7 @@ class Text(proto.Message): class Image(proto.Message): r"""The image response message. + Attributes: image_uri (str): Optional. The public URI to an image file. @@ -385,6 +425,7 @@ class Image(proto.Message): class QuickReplies(proto.Message): r"""The quick replies response message. + Attributes: title (str): Optional. The title of the collection of @@ -398,6 +439,7 @@ class QuickReplies(proto.Message): class Card(proto.Message): r"""The card response message. + Attributes: title (str): Optional. The title of the card. @@ -412,6 +454,7 @@ class Card(proto.Message): class Button(proto.Message): r"""Contains information about a button. + Attributes: text (str): Optional. The text to show on the button. @@ -432,6 +475,7 @@ class Button(proto.Message): class SimpleResponse(proto.Message): r"""The simple response message containing speech or text. + Attributes: text_to_speech (str): One of text_to_speech or ssml must be provided. The plain @@ -465,6 +509,7 @@ class SimpleResponses(proto.Message): class BasicCard(proto.Message): r"""The basic card message. Useful for displaying information. + Attributes: title (str): Optional. The title of the card. @@ -481,6 +526,7 @@ class BasicCard(proto.Message): class Button(proto.Message): r"""The button object that appears at the bottom of a card. + Attributes: title (str): Required. The title of the button. @@ -491,6 +537,7 @@ class Button(proto.Message): class OpenUriAction(proto.Message): r"""Opens the given URI. + Attributes: uri (str): Required. The HTTP or HTTPS scheme URI. @@ -529,6 +576,7 @@ class Suggestion(proto.Message): class Suggestions(proto.Message): r"""The collection of suggestions. + Attributes: suggestions (Sequence[google.cloud.dialogflow_v2.types.Intent.Message.Suggestion]): Required. The list of suggested replies. @@ -556,6 +604,7 @@ class LinkOutSuggestion(proto.Message): class ListSelect(proto.Message): r"""The card for presenting a list of options to select from. + Attributes: title (str): Optional. The overall title of the list. @@ -567,6 +616,7 @@ class ListSelect(proto.Message): class Item(proto.Message): r"""An item in the list. + Attributes: info (google.cloud.dialogflow_v2.types.Intent.Message.SelectItemInfo): Required. Additional information about this @@ -596,6 +646,7 @@ class Item(proto.Message): class CarouselSelect(proto.Message): r"""The card for presenting a carousel of options to select from. + Attributes: items (Sequence[google.cloud.dialogflow_v2.types.Intent.Message.CarouselSelect.Item]): Required. Carousel items. @@ -603,6 +654,7 @@ class CarouselSelect(proto.Message): class Item(proto.Message): r"""An item in the carousel. + Attributes: info (google.cloud.dialogflow_v2.types.Intent.Message.SelectItemInfo): Required. Additional info about the option @@ -646,6 +698,7 @@ class SelectItemInfo(proto.Message): class MediaContent(proto.Message): r"""The media content card for Actions on Google. + Attributes: media_type (google.cloud.dialogflow_v2.types.Intent.Message.MediaContent.ResponseMediaType): Optional. What type of media is the content @@ -661,6 +714,14 @@ class ResponseMediaType(proto.Enum): class ResponseMediaObject(proto.Message): r"""Response media object for media content card. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): Required. Name of media card. @@ -669,9 +730,13 @@ class ResponseMediaObject(proto.Message): large_image (google.cloud.dialogflow_v2.types.Intent.Message.Image): Optional. Image to display above media content. + + This field is a member of `oneof`_ ``image``. icon (google.cloud.dialogflow_v2.types.Intent.Message.Image): Optional. Icon to display above media content. + + This field is a member of `oneof`_ ``image``. content_url (str): Required. Url where the media is stored. """ @@ -731,6 +796,7 @@ class ImageDisplayOptions(proto.Enum): class BrowseCarouselCardItem(proto.Message): r"""Browsing carousel tile + Attributes: open_uri_action (google.cloud.dialogflow_v2.types.Intent.Message.BrowseCarouselCard.BrowseCarouselCardItem.OpenUrlAction): Required. Action to present to the user. @@ -750,6 +816,7 @@ class BrowseCarouselCardItem(proto.Message): class OpenUrlAction(proto.Message): r"""Actions on Google action to open a given url. + Attributes: url (str): Required. URL @@ -797,6 +864,7 @@ class UrlTypeHint(proto.Enum): class TableCard(proto.Message): r"""Table card for Actions on Google. + Attributes: title (str): Required. Title of the card. @@ -960,6 +1028,7 @@ class TableCardCell(proto.Message): class FollowupIntentInfo(proto.Message): r"""Represents a single followup intent in the chain. + Attributes: followup_intent_name (str): The unique identifier of the followup intent. Format: @@ -1163,6 +1232,14 @@ class DeleteIntentRequest(proto.Message): class BatchUpdateIntentsRequest(proto.Message): r""" + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: parent (str): Required. The name of the agent to update or create intents @@ -1173,9 +1250,13 @@ class BatchUpdateIntentsRequest(proto.Message): format can either be a serialized proto (of IntentBatch type) or JSON object. Note: The URI must start with "gs://". + + This field is a member of `oneof`_ ``intent_batch``. intent_batch_inline (google.cloud.dialogflow_v2.types.IntentBatch): The collection of intents to update or create. + + This field is a member of `oneof`_ ``intent_batch``. language_code (str): Optional. The language used to access language-specific data. If not specified, the agent's default language is @@ -1233,6 +1314,7 @@ class BatchDeleteIntentsRequest(proto.Message): class IntentBatch(proto.Message): r"""This message is a wrapper around a collection of intents. + Attributes: intents (Sequence[google.cloud.dialogflow_v2.types.Intent]): A collection of intents. diff --git a/google/cloud/dialogflow_v2/types/participant.py b/google/cloud/dialogflow_v2/types/participant.py index bbc03af91..5b29ba6b2 100644 --- a/google/cloud/dialogflow_v2/types/participant.py +++ b/google/cloud/dialogflow_v2/types/participant.py @@ -47,6 +47,7 @@ "SuggestionResult", "AnnotatedMessagePart", "MessageAnnotation", + "AssistQueryParameters", }, ) @@ -69,6 +70,27 @@ class Participant(proto.Message): metadata and SDP. This is used to assign transcriptions from that media stream to this participant. This field can be updated. + documents_metadata_filters (Sequence[google.cloud.dialogflow_v2.types.Participant.DocumentsMetadataFiltersEntry]): + Optional. Key-value filters on the metadata of documents + returned by article suggestion. If specified, article + suggestion only returns suggested documents that match all + filters in their + [Document.metadata][google.cloud.dialogflow.v2.Document.metadata]. + Multiple values for a metadata key should be concatenated by + comma. For example, filters to match all documents that have + 'US' or 'CA' in their market metadata values and 'agent' in + their user metadata values will be + + :: + + documents_metadata_filters { + key: "market" + value: "US,CA" + } + documents_metadata_filters { + key: "user" + value: "agent" + } """ class Role(proto.Enum): @@ -83,10 +105,12 @@ class Role(proto.Enum): name = proto.Field(proto.STRING, number=1,) role = proto.Field(proto.ENUM, number=2, enum=Role,) sip_recording_media_label = proto.Field(proto.STRING, number=6,) + documents_metadata_filters = proto.MapField(proto.STRING, proto.STRING, number=8,) class Message(proto.Message): r"""Represents a message posted into a conversation. + Attributes: name (str): The unique identifier of the message. Format: @@ -216,6 +240,13 @@ class AnalyzeContentRequest(proto.Message): r"""The request message for [Participants.AnalyzeContent][google.cloud.dialogflow.v2.Participants.AnalyzeContent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: participant (str): Required. The name of the participant this text comes from. @@ -223,8 +254,12 @@ class AnalyzeContentRequest(proto.Message): ``projects//locations//conversations//participants/``. text_input (google.cloud.dialogflow_v2.types.TextInput): The natural language text to be processed. + + This field is a member of `oneof`_ ``input``. event_input (google.cloud.dialogflow_v2.types.EventInput): An input event to send to Dialogflow. + + This field is a member of `oneof`_ ``input``. reply_audio_config (google.cloud.dialogflow_v2.types.OutputAudioConfig): Speech synthesis configuration. The speech synthesis settings for a virtual @@ -235,6 +270,8 @@ class AnalyzeContentRequest(proto.Message): query_params (google.cloud.dialogflow_v2.types.QueryParameters): Parameters for a Dialogflow virtual-agent query. + assist_query_params (google.cloud.dialogflow_v2.types.AssistQueryParameters): + Parameters for a human assist query. request_id (str): A unique identifier for this request. Restricted to 36 ASCII characters. A random UUID is recommended. This request is @@ -254,6 +291,9 @@ class AnalyzeContentRequest(proto.Message): query_params = proto.Field( proto.MESSAGE, number=9, message=session.QueryParameters, ) + assist_query_params = proto.Field( + proto.MESSAGE, number=14, message="AssistQueryParameters", + ) request_id = proto.Field(proto.STRING, number=11,) @@ -353,11 +393,16 @@ class SuggestArticlesRequest(proto.Message): [latest_message][google.cloud.dialogflow.v2.SuggestArticlesRequest.latest_message] to use as context when compiling the suggestion. By default 20 and at most 50. + assist_query_params (google.cloud.dialogflow_v2.types.AssistQueryParameters): + Parameters for a human assist query. """ parent = proto.Field(proto.STRING, number=1,) latest_message = proto.Field(proto.STRING, number=2,) context_size = proto.Field(proto.INT32, number=3,) + assist_query_params = proto.Field( + proto.MESSAGE, number=4, message="AssistQueryParameters", + ) class SuggestArticlesResponse(proto.Message): @@ -410,11 +455,16 @@ class SuggestFaqAnswersRequest(proto.Message): Max number of messages prior to and including [latest_message] to use as context when compiling the suggestion. By default 20 and at most 50. + assist_query_params (google.cloud.dialogflow_v2.types.AssistQueryParameters): + Parameters for a human assist query. """ parent = proto.Field(proto.STRING, number=1,) latest_message = proto.Field(proto.STRING, number=2,) context_size = proto.Field(proto.INT32, number=3,) + assist_query_params = proto.Field( + proto.MESSAGE, number=4, message="AssistQueryParameters", + ) class SuggestFaqAnswersResponse(proto.Message): @@ -464,6 +514,7 @@ class OutputAudio(proto.Message): class AutomatedAgentReply(proto.Message): r"""Represents a response from an automated agent. + Attributes: detect_intent_response (google.cloud.dialogflow_v2.types.DetectIntentResponse): Response of the Dialogflow @@ -496,6 +547,7 @@ class AutomatedAgentReplyType(proto.Enum): class ArticleAnswer(proto.Message): r"""Represents article answer. + Attributes: title (str): The article title. @@ -528,6 +580,7 @@ class ArticleAnswer(proto.Message): class FaqAnswer(proto.Message): r"""Represents answer from "frequently asked questions". + Attributes: answer (str): The piece of text from the ``source`` knowledge base @@ -569,14 +622,27 @@ class SuggestionResult(proto.Message): as well as [HumanAgentAssistantEvent][google.cloud.dialogflow.v2.HumanAgentAssistantEvent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: error (google.rpc.status_pb2.Status): Error status if the request failed. + + This field is a member of `oneof`_ ``suggestion_response``. suggest_articles_response (google.cloud.dialogflow_v2.types.SuggestArticlesResponse): SuggestArticlesResponse if request is for ARTICLE_SUGGESTION. + + This field is a member of `oneof`_ ``suggestion_response``. suggest_faq_answers_response (google.cloud.dialogflow_v2.types.SuggestFaqAnswersResponse): SuggestFaqAnswersResponse if request is for FAQ_ANSWER. + + This field is a member of `oneof`_ ``suggestion_response``. """ error = proto.Field( @@ -633,6 +699,7 @@ class AnnotatedMessagePart(proto.Message): class MessageAnnotation(proto.Message): r"""Represents the result of annotation for the message. + Attributes: parts (Sequence[google.cloud.dialogflow_v2.types.AnnotatedMessagePart]): The collection of annotated message parts ordered by their @@ -649,4 +716,24 @@ class MessageAnnotation(proto.Message): contain_entities = proto.Field(proto.BOOL, number=2,) +class AssistQueryParameters(proto.Message): + r"""Represents the parameters of human assist query. + + Attributes: + documents_metadata_filters (Sequence[google.cloud.dialogflow_v2.types.AssistQueryParameters.DocumentsMetadataFiltersEntry]): + Key-value filters on the metadata of documents returned by + article suggestion. If specified, article suggestion only + returns suggested documents that match all filters in their + [Document.metadata][google.cloud.dialogflow.v2.Document.metadata]. + Multiple values for a metadata key should be concatenated by + comma. For example, filters to match all documents that have + 'US' or 'CA' in their market metadata values and 'agent' in + their user metadata values will be + documents_metadata_filters { key: "market" value: "US,CA" } + documents_metadata_filters { key: "user" value: "agent" } + """ + + documents_metadata_filters = proto.MapField(proto.STRING, proto.STRING, number=1,) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/dialogflow_v2/types/session.py b/google/cloud/dialogflow_v2/types/session.py index 17289a15e..febc8b92a 100644 --- a/google/cloud/dialogflow_v2/types/session.py +++ b/google/cloud/dialogflow_v2/types/session.py @@ -48,6 +48,7 @@ class DetectIntentRequest(proto.Message): r"""The request to detect user's intent. + Attributes: session (str): Required. The name of the session this query is sent to. @@ -118,6 +119,7 @@ class DetectIntentRequest(proto.Message): class DetectIntentResponse(proto.Message): r"""The message returned from the DetectIntent method. + Attributes: response_id (str): The unique identifier of the response. It can @@ -157,6 +159,7 @@ class DetectIntentResponse(proto.Message): class QueryParameters(proto.Message): r"""Represents the parameters of the conversational query. + Attributes: time_zone (str): The time zone of this conversational query from the `time @@ -226,14 +229,27 @@ class QueryInput(proto.Message): 3. An event that specifies which intent to trigger. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: audio_config (google.cloud.dialogflow_v2.types.InputAudioConfig): Instructs the speech recognizer how to process the speech audio. + + This field is a member of `oneof`_ ``input``. text (google.cloud.dialogflow_v2.types.TextInput): The natural language text to be processed. + + This field is a member of `oneof`_ ``input``. event (google.cloud.dialogflow_v2.types.EventInput): The event to be processed. + + This field is a member of `oneof`_ ``input``. """ audio_config = proto.Field( @@ -512,11 +528,11 @@ class StreamingDetectIntentResponse(proto.Message): Multiple response messages can be returned in order: - 1. If the input was set to streaming audio, the first one or more - messages contain ``recognition_result``. Each - ``recognition_result`` represents a more complete transcript of - what the user said. The last ``recognition_result`` has - ``is_final`` set to ``true``. + 1. If the ``StreamingDetectIntentRequest.input_audio`` field was + set, the ``recognition_result`` field is populated for one or + more messages. See the + [StreamingRecognitionResult][google.cloud.dialogflow.v2.StreamingRecognitionResult] + message for details about the result message sequence. 2. The next message contains ``response_id``, ``query_result`` and optionally ``webhook_status`` if a WebHook was called. @@ -567,33 +583,42 @@ class StreamingRecognitionResult(proto.Message): the audio that is currently being processed or an indication that this is the end of the single requested utterance. - Example: - - 1. transcript: "tube" - - 2. transcript: "to be a" - - 3. transcript: "to be" - - 4. transcript: "to be or not to be" is_final: true - - 5. transcript: " that's" - - 6. transcript: " that is" - - 7. message_type: ``END_OF_SINGLE_UTTERANCE`` - - 8. transcript: " that is the question" is_final: true - - Only two of the responses contain final results (#4 and #8 indicated - by ``is_final: true``). Concatenating these generates the full - transcript: "to be or not to be that is the question". - - In each response we populate: - - - for ``TRANSCRIPT``: ``transcript`` and possibly ``is_final``. - - - for ``END_OF_SINGLE_UTTERANCE``: only ``message_type``. + While end-user audio is being processed, Dialogflow sends a series + of results. Each result may contain a ``transcript`` value. A + transcript represents a portion of the utterance. While the + recognizer is processing audio, transcript values may be interim + values or finalized values. Once a transcript is finalized, the + ``is_final`` value is set to true and processing continues for the + next transcript. + + If + ``StreamingDetectIntentRequest.query_input.audio_config.single_utterance`` + was true, and the recognizer has completed processing audio, the + ``message_type`` value is set to \`END_OF_SINGLE_UTTERANCE and the + following (last) result contains the last finalized transcript. + + The complete end-user utterance is determined by concatenating the + finalized transcript values received for the series of results. + + In the following example, single utterance is enabled. In the case + where single utterance is not enabled, result 7 would not occur. + + :: + + Num | transcript | message_type | is_final + --- | ----------------------- | ----------------------- | -------- + 1 | "tube" | TRANSCRIPT | false + 2 | "to be a" | TRANSCRIPT | false + 3 | "to be" | TRANSCRIPT | false + 4 | "to be or not to be" | TRANSCRIPT | true + 5 | "that's" | TRANSCRIPT | false + 6 | "that is | TRANSCRIPT | false + 7 | unset | END_OF_SINGLE_UTTERANCE | unset + 8 | " that is the question" | TRANSCRIPT | true + + Concatenating the finalized transcripts with ``is_final`` set to + true, the complete utterance becomes "to be or not to be that is the + question". Attributes: message_type (google.cloud.dialogflow_v2.types.StreamingRecognitionResult.MessageType): @@ -652,6 +677,7 @@ class MessageType(proto.Enum): class TextInput(proto.Message): r"""Represents the natural language text to be processed. + Attributes: text (str): Required. The UTF-8 encoded natural language @@ -716,6 +742,7 @@ class EventInput(proto.Message): class SentimentAnalysisRequestConfig(proto.Message): r"""Configures the types of sentiment analysis to perform. + Attributes: analyze_query_text_sentiment (bool): Instructs the service to perform sentiment analysis on diff --git a/google/cloud/dialogflow_v2/types/validation_result.py b/google/cloud/dialogflow_v2/types/validation_result.py index b1008264b..e065363b7 100644 --- a/google/cloud/dialogflow_v2/types/validation_result.py +++ b/google/cloud/dialogflow_v2/types/validation_result.py @@ -24,6 +24,7 @@ class ValidationError(proto.Message): r"""Represents a single validation error. + Attributes: severity (google.cloud.dialogflow_v2.types.ValidationError.Severity): The severity of the error. @@ -66,6 +67,7 @@ class Severity(proto.Enum): class ValidationResult(proto.Message): r"""Represents the output of agent validation. + Attributes: validation_errors (Sequence[google.cloud.dialogflow_v2.types.ValidationError]): Contains all validation errors. diff --git a/google/cloud/dialogflow_v2/types/webhook.py b/google/cloud/dialogflow_v2/types/webhook.py index 8c96b6676..6dd218aa5 100644 --- a/google/cloud/dialogflow_v2/types/webhook.py +++ b/google/cloud/dialogflow_v2/types/webhook.py @@ -30,6 +30,7 @@ class WebhookRequest(proto.Message): r"""The request message for a webhook call. + Attributes: session (str): The unique identifier of detectIntent request session. Can diff --git a/google/cloud/dialogflow_v2beta1/services/agents/async_client.py b/google/cloud/dialogflow_v2beta1/services/agents/async_client.py index af66e7981..6407ec366 100644 --- a/google/cloud/dialogflow_v2beta1/services/agents/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/agents/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2beta1.services.agents import pagers @@ -161,17 +166,17 @@ def __init__( async def get_agent( self, - request: agent.GetAgentRequest = None, + request: Union[agent.GetAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> agent.Agent: r"""Retrieves the specified agent. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetAgentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetAgentRequest, dict]): The request object. The request message for [Agents.GetAgent][google.cloud.dialogflow.v2beta1.Agents.GetAgent]. parent (:class:`str`): @@ -242,10 +247,10 @@ async def get_agent( async def set_agent( self, - request: gcd_agent.SetAgentRequest = None, + request: Union[gcd_agent.SetAgentRequest, dict] = None, *, agent: gcd_agent.Agent = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_agent.Agent: @@ -256,7 +261,7 @@ async def set_agent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.SetAgentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.SetAgentRequest, dict]): The request object. The request message for [Agents.SetAgent][google.cloud.dialogflow.v2beta1.Agents.SetAgent]. agent (:class:`google.cloud.dialogflow_v2beta1.types.Agent`): @@ -326,17 +331,17 @@ async def set_agent( async def delete_agent( self, - request: agent.DeleteAgentRequest = None, + request: Union[agent.DeleteAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes the specified agent. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteAgentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteAgentRequest, dict]): The request object. The request message for [Agents.DeleteAgent][google.cloud.dialogflow.v2beta1.Agents.DeleteAgent]. parent (:class:`str`): @@ -391,10 +396,10 @@ async def delete_agent( async def search_agents( self, - request: agent.SearchAgentsRequest = None, + request: Union[agent.SearchAgentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.SearchAgentsAsyncPager: @@ -406,7 +411,7 @@ async def search_agents( Sub-Collections `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.SearchAgentsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.SearchAgentsRequest, dict]): The request object. The request message for [Agents.SearchAgents][google.cloud.dialogflow.v2beta1.Agents.SearchAgents]. parent (:class:`str`): @@ -477,10 +482,10 @@ async def search_agents( async def train_agent( self, - request: agent.TrainAgentRequest = None, + request: Union[agent.TrainAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -501,7 +506,7 @@ async def train_agent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.TrainAgentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.TrainAgentRequest, dict]): The request object. The request message for [Agents.TrainAgent][google.cloud.dialogflow.v2beta1.Agents.TrainAgent]. parent (:class:`str`): @@ -584,10 +589,10 @@ async def train_agent( async def export_agent( self, - request: agent.ExportAgentRequest = None, + request: Union[agent.ExportAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -604,7 +609,7 @@ async def export_agent( [ExportAgentResponse][google.cloud.dialogflow.v2beta1.ExportAgentResponse] Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ExportAgentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ExportAgentRequest, dict]): The request object. The request message for [Agents.ExportAgent][google.cloud.dialogflow.v2beta1.Agents.ExportAgent]. parent (:class:`str`): @@ -678,9 +683,9 @@ async def export_agent( async def import_agent( self, - request: agent.ImportAgentRequest = None, + request: Union[agent.ImportAgentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -716,7 +721,7 @@ async def import_agent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ImportAgentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ImportAgentRequest, dict]): The request object. The request message for [Agents.ImportAgent][google.cloud.dialogflow.v2beta1.Agents.ImportAgent]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -777,9 +782,9 @@ async def import_agent( async def restore_agent( self, - request: agent.RestoreAgentRequest = None, + request: Union[agent.RestoreAgentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -813,7 +818,7 @@ async def restore_agent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.RestoreAgentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.RestoreAgentRequest, dict]): The request object. The request message for [Agents.RestoreAgent][google.cloud.dialogflow.v2beta1.Agents.RestoreAgent]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -874,9 +879,9 @@ async def restore_agent( async def get_validation_result( self, - request: agent.GetValidationResultRequest = None, + request: Union[agent.GetValidationResultRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> validation_result.ValidationResult: @@ -885,7 +890,7 @@ async def get_validation_result( automatically when training is completed. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetValidationResultRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetValidationResultRequest, dict]): The request object. The request message for [Agents.GetValidationResult][google.cloud.dialogflow.v2beta1.Agents.GetValidationResult]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -923,6 +928,12 @@ async def get_validation_result( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/agents/client.py b/google/cloud/dialogflow_v2beta1/services/agents/client.py index d0f5f44a6..115888981 100644 --- a/google/cloud/dialogflow_v2beta1/services/agents/client.py +++ b/google/cloud/dialogflow_v2beta1/services/agents/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2beta1.services.agents import pagers @@ -282,8 +286,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -345,10 +356,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def get_agent( @@ -356,7 +364,7 @@ def get_agent( request: Union[agent.GetAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> agent.Agent: @@ -437,7 +445,7 @@ def set_agent( request: Union[gcd_agent.SetAgentRequest, dict] = None, *, agent: gcd_agent.Agent = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_agent.Agent: @@ -521,7 +529,7 @@ def delete_agent( request: Union[agent.DeleteAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -586,7 +594,7 @@ def search_agents( request: Union[agent.SearchAgentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.SearchAgentsPager: @@ -672,7 +680,7 @@ def train_agent( request: Union[agent.TrainAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -779,7 +787,7 @@ def export_agent( request: Union[agent.ExportAgentRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -872,7 +880,7 @@ def import_agent( self, request: Union[agent.ImportAgentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -972,7 +980,7 @@ def restore_agent( self, request: Union[agent.RestoreAgentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1070,7 +1078,7 @@ def get_validation_result( self, request: Union[agent.GetValidationResultRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> validation_result.ValidationResult: @@ -1118,6 +1126,19 @@ def get_validation_result( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/agents/transports/base.py b/google/cloud/dialogflow_v2beta1/services/agents/transports/base.py index 698507989..0435903ca 100644 --- a/google/cloud/dialogflow_v2beta1/services/agents/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/agents/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore -from google.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -42,15 +41,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class AgentsTransport(abc.ABC): """Abstract transport class for Agents.""" @@ -103,7 +93,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -136,29 +126,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -193,8 +160,17 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/dialogflow_v2beta1/services/agents/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/agents/transports/grpc.py index 98f4eb5e9..5e6e8ef35 100644 --- a/google/cloud/dialogflow_v2beta1/services/agents/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/agents/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -116,7 +116,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -567,5 +567,8 @@ def get_validation_result( ) return self._stubs["get_validation_result"] + def close(self): + self.grpc_channel.close() + __all__ = ("AgentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/agents/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/agents/transports/grpc_asyncio.py index 4a88d1d43..192fb297f 100644 --- a/google/cloud/dialogflow_v2beta1/services/agents/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/agents/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore -from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -163,7 +162,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -577,5 +576,8 @@ def get_validation_result( ) return self._stubs["get_validation_result"] + def close(self): + return self.grpc_channel.close() + __all__ = ("AgentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/answer_records/async_client.py b/google/cloud/dialogflow_v2beta1/services/answer_records/async_client.py index 93c491233..806569d75 100644 --- a/google/cloud/dialogflow_v2beta1/services/answer_records/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/answer_records/async_client.py @@ -20,13 +20,18 @@ import pkg_resources import warnings -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.answer_records import pagers from google.cloud.dialogflow_v2beta1.types import answer_record from google.cloud.dialogflow_v2beta1.types import answer_record as gcd_answer_record @@ -170,9 +175,9 @@ def __init__( async def get_answer_record( self, - request: answer_record.GetAnswerRecordRequest = None, + request: Union[answer_record.GetAnswerRecordRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> answer_record.AnswerRecord: @@ -180,7 +185,7 @@ async def get_answer_record( Retrieves a specific answer record. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetAnswerRecordRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetAnswerRecordRequest, dict]): The request object. Request message for [AnswerRecords.GetAnswerRecord][google.cloud.dialogflow.v2beta1.AnswerRecords.GetAnswerRecord]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -256,10 +261,10 @@ async def get_answer_record( async def list_answer_records( self, - request: answer_record.ListAnswerRecordsRequest = None, + request: Union[answer_record.ListAnswerRecordsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListAnswerRecordsAsyncPager: @@ -267,7 +272,7 @@ async def list_answer_records( specified project in reverse chronological order. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListAnswerRecordsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListAnswerRecordsRequest, dict]): The request object. Request message for [AnswerRecords.ListAnswerRecords][google.cloud.dialogflow.v2beta1.AnswerRecords.ListAnswerRecords]. parent (:class:`str`): @@ -338,18 +343,18 @@ async def list_answer_records( async def update_answer_record( self, - request: gcd_answer_record.UpdateAnswerRecordRequest = None, + request: Union[gcd_answer_record.UpdateAnswerRecordRequest, dict] = None, *, answer_record: gcd_answer_record.AnswerRecord = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_answer_record.AnswerRecord: r"""Updates the specified answer record. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateAnswerRecordRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateAnswerRecordRequest, dict]): The request object. Request message for [AnswerRecords.UpdateAnswerRecord][google.cloud.dialogflow.v2beta1.AnswerRecords.UpdateAnswerRecord]. answer_record (:class:`google.cloud.dialogflow_v2beta1.types.AnswerRecord`): @@ -448,6 +453,12 @@ async def update_answer_record( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/answer_records/client.py b/google/cloud/dialogflow_v2beta1/services/answer_records/client.py index 3eb74fb44..a93a7891d 100644 --- a/google/cloud/dialogflow_v2beta1/services/answer_records/client.py +++ b/google/cloud/dialogflow_v2beta1/services/answer_records/client.py @@ -14,23 +14,27 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources import warnings -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.answer_records import pagers from google.cloud.dialogflow_v2beta1.types import answer_record from google.cloud.dialogflow_v2beta1.types import answer_record as gcd_answer_record @@ -283,8 +287,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -346,17 +357,14 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def get_answer_record( self, request: Union[answer_record.GetAnswerRecordRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> answer_record.AnswerRecord: @@ -443,7 +451,7 @@ def list_answer_records( request: Union[answer_record.ListAnswerRecordsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListAnswerRecordsPager: @@ -526,7 +534,7 @@ def update_answer_record( *, answer_record: gcd_answer_record.AnswerRecord = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_answer_record.AnswerRecord: @@ -632,6 +640,19 @@ def update_answer_record( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/answer_records/transports/base.py b/google/cloud/dialogflow_v2beta1/services/answer_records/transports/base.py index be768eb7a..1f05716c4 100644 --- a/google/cloud/dialogflow_v2beta1/services/answer_records/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/answer_records/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class AnswerRecordsTransport(abc.ABC): """Abstract transport class for AnswerRecords.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -171,6 +138,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def get_answer_record( self, diff --git a/google/cloud/dialogflow_v2beta1/services/answer_records/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/answer_records/transports/grpc.py index f4fd6f955..4f0fd13fe 100644 --- a/google/cloud/dialogflow_v2beta1/services/answer_records/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/answer_records/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -312,5 +312,8 @@ def update_answer_record( ) return self._stubs["update_answer_record"] + def close(self): + self.grpc_channel.close() + __all__ = ("AnswerRecordsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/answer_records/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/answer_records/transports/grpc_asyncio.py index 8a5dbf1b4..5c8907e53 100644 --- a/google/cloud/dialogflow_v2beta1/services/answer_records/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/answer_records/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -318,5 +317,8 @@ def update_answer_record( ) return self._stubs["update_answer_record"] + def close(self): + return self.grpc_channel.close() + __all__ = ("AnswerRecordsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/contexts/async_client.py b/google/cloud/dialogflow_v2beta1/services/contexts/async_client.py index 775dc4f81..f17b42116 100644 --- a/google/cloud/dialogflow_v2beta1/services/contexts/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/contexts/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.contexts import pagers from google.cloud.dialogflow_v2beta1.types import context from google.cloud.dialogflow_v2beta1.types import context as gcd_context @@ -160,10 +165,10 @@ def __init__( async def list_contexts( self, - request: context.ListContextsRequest = None, + request: Union[context.ListContextsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListContextsAsyncPager: @@ -171,7 +176,7 @@ async def list_contexts( session. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListContextsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListContextsRequest, dict]): The request object. The request message for [Contexts.ListContexts][google.cloud.dialogflow.v2beta1.Contexts.ListContexts]. parent (:class:`str`): @@ -251,17 +256,17 @@ async def list_contexts( async def get_context( self, - request: context.GetContextRequest = None, + request: Union[context.GetContextRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> context.Context: r"""Retrieves the specified context. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetContextRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetContextRequest, dict]): The request object. The request message for [Contexts.GetContext][google.cloud.dialogflow.v2beta1.Contexts.GetContext]. name (:class:`str`): @@ -348,11 +353,11 @@ async def get_context( async def create_context( self, - request: gcd_context.CreateContextRequest = None, + request: Union[gcd_context.CreateContextRequest, dict] = None, *, parent: str = None, context: gcd_context.Context = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_context.Context: @@ -361,7 +366,7 @@ async def create_context( context. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateContextRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateContextRequest, dict]): The request object. The request message for [Contexts.CreateContext][google.cloud.dialogflow.v2beta1.Contexts.CreateContext]. parent (:class:`str`): @@ -456,18 +461,18 @@ async def create_context( async def update_context( self, - request: gcd_context.UpdateContextRequest = None, + request: Union[gcd_context.UpdateContextRequest, dict] = None, *, context: gcd_context.Context = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_context.Context: r"""Updates the specified context. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateContextRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateContextRequest, dict]): The request object. The request message for [Contexts.UpdateContext][google.cloud.dialogflow.v2beta1.Contexts.UpdateContext]. context (:class:`google.cloud.dialogflow_v2beta1.types.Context`): @@ -554,17 +559,17 @@ async def update_context( async def delete_context( self, - request: context.DeleteContextRequest = None, + request: Union[context.DeleteContextRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes the specified context. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteContextRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteContextRequest, dict]): The request object. The request message for [Contexts.DeleteContext][google.cloud.dialogflow.v2beta1.Contexts.DeleteContext]. name (:class:`str`): @@ -628,17 +633,17 @@ async def delete_context( async def delete_all_contexts( self, - request: context.DeleteAllContextsRequest = None, + request: Union[context.DeleteAllContextsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes all active contexts in the specified session. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteAllContextsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteAllContextsRequest, dict]): The request object. The request message for [Contexts.DeleteAllContexts][google.cloud.dialogflow.v2beta1.Contexts.DeleteAllContexts]. parent (:class:`str`): @@ -700,6 +705,12 @@ async def delete_all_contexts( request, retry=retry, timeout=timeout, metadata=metadata, ) + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/contexts/client.py b/google/cloud/dialogflow_v2beta1/services/contexts/client.py index 1c91533eb..840efa645 100644 --- a/google/cloud/dialogflow_v2beta1/services/contexts/client.py +++ b/google/cloud/dialogflow_v2beta1/services/contexts/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.contexts import pagers from google.cloud.dialogflow_v2beta1.types import context from google.cloud.dialogflow_v2beta1.types import context as gcd_context @@ -284,8 +288,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -347,10 +358,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_contexts( @@ -358,7 +366,7 @@ def list_contexts( request: Union[context.ListContextsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListContextsPager: @@ -449,7 +457,7 @@ def get_context( request: Union[context.GetContextRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> context.Context: @@ -547,7 +555,7 @@ def create_context( *, parent: str = None, context: gcd_context.Context = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_context.Context: @@ -655,7 +663,7 @@ def update_context( *, context: gcd_context.Context = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_context.Context: @@ -752,7 +760,7 @@ def delete_context( request: Union[context.DeleteContextRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -826,7 +834,7 @@ def delete_all_contexts( request: Union[context.DeleteAllContextsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -895,6 +903,19 @@ def delete_all_contexts( request, retry=retry, timeout=timeout, metadata=metadata, ) + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/contexts/transports/base.py b/google/cloud/dialogflow_v2beta1/services/contexts/transports/base.py index 49b7a23b0..6e231f595 100644 --- a/google/cloud/dialogflow_v2beta1/services/contexts/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/contexts/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -39,15 +38,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class ContextsTransport(abc.ABC): """Abstract transport class for Contexts.""" @@ -100,7 +90,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -133,29 +123,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -179,6 +146,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_contexts( self, diff --git a/google/cloud/dialogflow_v2beta1/services/contexts/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/contexts/transports/grpc.py index e9956be43..94ae1f379 100644 --- a/google/cloud/dialogflow_v2beta1/services/contexts/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/contexts/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -385,5 +385,8 @@ def delete_all_contexts( ) return self._stubs["delete_all_contexts"] + def close(self): + self.grpc_channel.close() + __all__ = ("ContextsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/contexts/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/contexts/transports/grpc_asyncio.py index 8f205b5bf..103724e04 100644 --- a/google/cloud/dialogflow_v2beta1/services/contexts/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/contexts/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -392,5 +391,8 @@ def delete_all_contexts( ) return self._stubs["delete_all_contexts"] + def close(self): + return self.grpc_channel.close() + __all__ = ("ContextsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/async_client.py b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/async_client.py index fb09ac4ac..670ac645f 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.conversation_profiles import pagers from google.cloud.dialogflow_v2beta1.types import audio_config from google.cloud.dialogflow_v2beta1.types import conversation_profile @@ -196,10 +201,12 @@ def __init__( async def list_conversation_profiles( self, - request: conversation_profile.ListConversationProfilesRequest = None, + request: Union[ + conversation_profile.ListConversationProfilesRequest, dict + ] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListConversationProfilesAsyncPager: @@ -207,7 +214,7 @@ async def list_conversation_profiles( specified project. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListConversationProfilesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListConversationProfilesRequest, dict]): The request object. The request message for [ConversationProfiles.ListConversationProfiles][google.cloud.dialogflow.v2beta1.ConversationProfiles.ListConversationProfiles]. parent (:class:`str`): @@ -278,17 +285,17 @@ async def list_conversation_profiles( async def get_conversation_profile( self, - request: conversation_profile.GetConversationProfileRequest = None, + request: Union[conversation_profile.GetConversationProfileRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation_profile.ConversationProfile: r"""Retrieves the specified conversation profile. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetConversationProfileRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetConversationProfileRequest, dict]): The request object. The request message for [ConversationProfiles.GetConversationProfile][google.cloud.dialogflow.v2beta1.ConversationProfiles.GetConversationProfile]. name (:class:`str`): @@ -350,11 +357,13 @@ async def get_conversation_profile( async def create_conversation_profile( self, - request: gcd_conversation_profile.CreateConversationProfileRequest = None, + request: Union[ + gcd_conversation_profile.CreateConversationProfileRequest, dict + ] = None, *, parent: str = None, conversation_profile: gcd_conversation_profile.ConversationProfile = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation_profile.ConversationProfile: @@ -367,7 +376,7 @@ async def create_conversation_profile( API. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateConversationProfileRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateConversationProfileRequest, dict]): The request object. The request message for [ConversationProfiles.CreateConversationProfile][google.cloud.dialogflow.v2beta1.ConversationProfiles.CreateConversationProfile]. parent (:class:`str`): @@ -438,11 +447,13 @@ async def create_conversation_profile( async def update_conversation_profile( self, - request: gcd_conversation_profile.UpdateConversationProfileRequest = None, + request: Union[ + gcd_conversation_profile.UpdateConversationProfileRequest, dict + ] = None, *, conversation_profile: gcd_conversation_profile.ConversationProfile = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation_profile.ConversationProfile: @@ -455,7 +466,7 @@ async def update_conversation_profile( API. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateConversationProfileRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateConversationProfileRequest, dict]): The request object. The request message for [ConversationProfiles.UpdateConversationProfile][google.cloud.dialogflow.v2beta1.ConversationProfiles.UpdateConversationProfile]. conversation_profile (:class:`google.cloud.dialogflow_v2beta1.types.ConversationProfile`): @@ -527,17 +538,19 @@ async def update_conversation_profile( async def delete_conversation_profile( self, - request: conversation_profile.DeleteConversationProfileRequest = None, + request: Union[ + conversation_profile.DeleteConversationProfileRequest, dict + ] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes the specified conversation profile. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteConversationProfileRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteConversationProfileRequest, dict]): The request object. The request message for [ConversationProfiles.DeleteConversationProfile][google.cloud.dialogflow.v2beta1.ConversationProfiles.DeleteConversationProfile]. This operation fails if the conversation profile is @@ -592,6 +605,12 @@ async def delete_conversation_profile( request, retry=retry, timeout=timeout, metadata=metadata, ) + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/client.py b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/client.py index 86262a0af..deedc7f1e 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/client.py +++ b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.conversation_profiles import pagers from google.cloud.dialogflow_v2beta1.types import audio_config from google.cloud.dialogflow_v2beta1.types import conversation_profile @@ -369,8 +373,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -432,10 +443,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_conversation_profiles( @@ -445,7 +453,7 @@ def list_conversation_profiles( ] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListConversationProfilesPager: @@ -531,7 +539,7 @@ def get_conversation_profile( request: Union[conversation_profile.GetConversationProfileRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation_profile.ConversationProfile: @@ -606,7 +614,7 @@ def create_conversation_profile( *, parent: str = None, conversation_profile: gcd_conversation_profile.ConversationProfile = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation_profile.ConversationProfile: @@ -700,7 +708,7 @@ def update_conversation_profile( *, conversation_profile: gcd_conversation_profile.ConversationProfile = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation_profile.ConversationProfile: @@ -794,7 +802,7 @@ def delete_conversation_profile( ] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -860,6 +868,19 @@ def delete_conversation_profile( request, retry=retry, timeout=timeout, metadata=metadata, ) + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/base.py b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/base.py index 9451cf98d..8beb05077 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -41,15 +40,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class ConversationProfilesTransport(abc.ABC): """Abstract transport class for ConversationProfiles.""" @@ -102,7 +92,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -135,29 +125,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -188,6 +155,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_conversation_profiles( self, diff --git a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/grpc.py index 18fc3858d..7669daf71 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -387,5 +387,8 @@ def delete_conversation_profile( ) return self._stubs["delete_conversation_profile"] + def close(self): + self.grpc_channel.close() + __all__ = ("ConversationProfilesGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/grpc_asyncio.py index c8971022f..af48b6549 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/conversation_profiles/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -391,5 +390,8 @@ def delete_conversation_profile( ) return self._stubs["delete_conversation_profile"] + def close(self): + return self.grpc_channel.close() + __all__ = ("ConversationProfilesGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/conversations/async_client.py b/google/cloud/dialogflow_v2beta1/services/conversations/async_client.py index 37a293a49..4b4cc2c64 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversations/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/conversations/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.conversations import pagers from google.cloud.dialogflow_v2beta1.types import conversation from google.cloud.dialogflow_v2beta1.types import conversation as gcd_conversation @@ -176,11 +181,11 @@ def __init__( async def create_conversation( self, - request: gcd_conversation.CreateConversationRequest = None, + request: Union[gcd_conversation.CreateConversationRequest, dict] = None, *, parent: str = None, conversation: gcd_conversation.Conversation = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation.Conversation: @@ -207,7 +212,7 @@ async def create_conversation( is triggered, conversation will transfer to Assist Stage. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateConversationRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateConversationRequest, dict]): The request object. The request message for [Conversations.CreateConversation][google.cloud.dialogflow.v2beta1.Conversations.CreateConversation]. parent (:class:`str`): @@ -281,10 +286,10 @@ async def create_conversation( async def list_conversations( self, - request: conversation.ListConversationsRequest = None, + request: Union[conversation.ListConversationsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListConversationsAsyncPager: @@ -292,7 +297,7 @@ async def list_conversations( specified project. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListConversationsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListConversationsRequest, dict]): The request object. The request message for [Conversations.ListConversations][google.cloud.dialogflow.v2beta1.Conversations.ListConversations]. parent (:class:`str`): @@ -363,17 +368,17 @@ async def list_conversations( async def get_conversation( self, - request: conversation.GetConversationRequest = None, + request: Union[conversation.GetConversationRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.Conversation: r"""Retrieves the specific conversation. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetConversationRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetConversationRequest, dict]): The request object. The request message for [Conversations.GetConversation][google.cloud.dialogflow.v2beta1.Conversations.GetConversation]. name (:class:`str`): @@ -439,10 +444,10 @@ async def get_conversation( async def complete_conversation( self, - request: conversation.CompleteConversationRequest = None, + request: Union[conversation.CompleteConversationRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.Conversation: @@ -451,7 +456,7 @@ async def complete_conversation( days. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CompleteConversationRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CompleteConversationRequest, dict]): The request object. The request message for [Conversations.CompleteConversation][google.cloud.dialogflow.v2beta1.Conversations.CompleteConversation]. name (:class:`str`): @@ -518,10 +523,10 @@ async def complete_conversation( async def batch_create_messages( self, - request: conversation.BatchCreateMessagesRequest = None, + request: Union[conversation.BatchCreateMessagesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.BatchCreateMessagesResponse: @@ -530,7 +535,7 @@ async def batch_create_messages( conversation. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.BatchCreateMessagesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.BatchCreateMessagesRequest, dict]): The request object. The request message for [Conversations.BatchCreateMessagesRequest][]. parent (:class:`str`): @@ -592,10 +597,10 @@ async def batch_create_messages( async def list_messages( self, - request: conversation.ListMessagesRequest = None, + request: Union[conversation.ListMessagesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListMessagesAsyncPager: @@ -606,7 +611,7 @@ async def list_messages( and empty page_token. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListMessagesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListMessagesRequest, dict]): The request object. The request message for [Conversations.ListMessages][google.cloud.dialogflow.v2beta1.Conversations.ListMessages]. parent (:class:`str`): @@ -675,6 +680,12 @@ async def list_messages( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/conversations/client.py b/google/cloud/dialogflow_v2beta1/services/conversations/client.py index 9ae7303eb..45a329b32 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversations/client.py +++ b/google/cloud/dialogflow_v2beta1/services/conversations/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.conversations import pagers from google.cloud.dialogflow_v2beta1.types import conversation from google.cloud.dialogflow_v2beta1.types import conversation as gcd_conversation @@ -315,8 +319,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -378,10 +389,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def create_conversation( @@ -390,7 +398,7 @@ def create_conversation( *, parent: str = None, conversation: gcd_conversation.Conversation = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_conversation.Conversation: @@ -494,7 +502,7 @@ def list_conversations( request: Union[conversation.ListConversationsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListConversationsPager: @@ -576,7 +584,7 @@ def get_conversation( request: Union[conversation.GetConversationRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.Conversation: @@ -652,7 +660,7 @@ def complete_conversation( request: Union[conversation.CompleteConversationRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.Conversation: @@ -731,7 +739,7 @@ def batch_create_messages( request: Union[conversation.BatchCreateMessagesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> conversation.BatchCreateMessagesResponse: @@ -805,7 +813,7 @@ def list_messages( request: Union[conversation.ListMessagesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListMessagesPager: @@ -885,6 +893,19 @@ def list_messages( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/conversations/transports/base.py b/google/cloud/dialogflow_v2beta1/services/conversations/transports/base.py index ce4b549fb..608489252 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversations/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/conversations/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class ConversationsTransport(abc.ABC): """Abstract transport class for Conversations.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -182,6 +149,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def create_conversation( self, diff --git a/google/cloud/dialogflow_v2beta1/services/conversations/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/conversations/transports/grpc.py index 3b00aff3b..1ee80512e 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversations/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/conversations/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -423,5 +423,8 @@ def list_messages( ) return self._stubs["list_messages"] + def close(self): + self.grpc_channel.close() + __all__ = ("ConversationsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/conversations/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/conversations/transports/grpc_asyncio.py index d20fee018..ef12de03d 100644 --- a/google/cloud/dialogflow_v2beta1/services/conversations/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/conversations/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -430,5 +429,8 @@ def list_messages( ) return self._stubs["list_messages"] + def close(self): + return self.grpc_channel.close() + __all__ = ("ConversationsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/documents/async_client.py b/google/cloud/dialogflow_v2beta1/services/documents/async_client.py index 53e4b07d3..c182bf648 100644 --- a/google/cloud/dialogflow_v2beta1/services/documents/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/documents/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2beta1.services.documents import pagers @@ -165,10 +170,10 @@ def __init__( async def list_documents( self, - request: document.ListDocumentsRequest = None, + request: Union[document.ListDocumentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListDocumentsAsyncPager: @@ -178,7 +183,7 @@ async def list_documents( is deprecated; only use ``projects.knowledgeBases.documents``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListDocumentsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListDocumentsRequest, dict]): The request object. Request message for [Documents.ListDocuments][google.cloud.dialogflow.v2beta1.Documents.ListDocuments]. parent (:class:`str`): @@ -249,10 +254,10 @@ async def list_documents( async def get_document( self, - request: document.GetDocumentRequest = None, + request: Union[document.GetDocumentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document.Document: @@ -262,7 +267,7 @@ async def get_document( is deprecated; only use ``projects.knowledgeBases.documents``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetDocumentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetDocumentRequest, dict]): The request object. Request message for [Documents.GetDocument][google.cloud.dialogflow.v2beta1.Documents.GetDocument]. name (:class:`str`): @@ -330,11 +335,11 @@ async def get_document( async def create_document( self, - request: gcd_document.CreateDocumentRequest = None, + request: Union[gcd_document.CreateDocumentRequest, dict] = None, *, parent: str = None, document: gcd_document.Document = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -354,7 +359,7 @@ async def create_document( is deprecated; only use ``projects.knowledgeBases.documents``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateDocumentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateDocumentRequest, dict]): The request object. Request message for [Documents.CreateDocument][google.cloud.dialogflow.v2beta1.Documents.CreateDocument]. parent (:class:`str`): @@ -442,9 +447,9 @@ async def create_document( async def import_documents( self, - request: document.ImportDocumentsRequest = None, + request: Union[document.ImportDocumentsRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -463,7 +468,7 @@ async def import_documents( [ImportDocumentsResponse][google.cloud.dialogflow.v2beta1.ImportDocumentsResponse] Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ImportDocumentsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ImportDocumentsRequest, dict]): The request object. Request message for [Documents.ImportDocuments][google.cloud.dialogflow.v2beta1.Documents.ImportDocuments]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -515,10 +520,10 @@ async def import_documents( async def delete_document( self, - request: document.DeleteDocumentRequest = None, + request: Union[document.DeleteDocumentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -538,7 +543,7 @@ async def delete_document( is deprecated; only use ``projects.knowledgeBases.documents``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteDocumentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteDocumentRequest, dict]): The request object. Request message for [Documents.DeleteDocument][google.cloud.dialogflow.v2beta1.Documents.DeleteDocument]. name (:class:`str`): @@ -620,11 +625,11 @@ async def delete_document( async def update_document( self, - request: gcd_document.UpdateDocumentRequest = None, + request: Union[gcd_document.UpdateDocumentRequest, dict] = None, *, document: gcd_document.Document = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -644,7 +649,7 @@ async def update_document( is deprecated; only use ``projects.knowledgeBases.documents``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateDocumentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateDocumentRequest, dict]): The request object. Request message for [Documents.UpdateDocument][google.cloud.dialogflow.v2beta1.Documents.UpdateDocument]. document (:class:`google.cloud.dialogflow_v2beta1.types.Document`): @@ -734,11 +739,11 @@ async def update_document( async def reload_document( self, - request: document.ReloadDocumentRequest = None, + request: Union[document.ReloadDocumentRequest, dict] = None, *, name: str = None, gcs_source: gcs.GcsSource = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -766,7 +771,7 @@ async def reload_document( is deprecated; only use ``projects.knowledgeBases.documents``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ReloadDocumentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ReloadDocumentRequest, dict]): The request object. Request message for [Documents.ReloadDocument][google.cloud.dialogflow.v2beta1.Documents.ReloadDocument]. name (:class:`str`): @@ -855,6 +860,12 @@ async def reload_document( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/documents/client.py b/google/cloud/dialogflow_v2beta1/services/documents/client.py index ef24cbc5d..5708fcc1e 100644 --- a/google/cloud/dialogflow_v2beta1/services/documents/client.py +++ b/google/cloud/dialogflow_v2beta1/services/documents/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2beta1.services.documents import pagers @@ -287,8 +291,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -350,10 +361,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_documents( @@ -361,7 +369,7 @@ def list_documents( request: Union[document.ListDocumentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListDocumentsPager: @@ -445,7 +453,7 @@ def get_document( request: Union[document.GetDocumentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> document.Document: @@ -527,7 +535,7 @@ def create_document( *, parent: str = None, document: gcd_document.Document = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -637,7 +645,7 @@ def import_documents( self, request: Union[document.ImportDocumentsRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -712,7 +720,7 @@ def delete_document( request: Union[document.DeleteDocumentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -818,7 +826,7 @@ def update_document( *, document: gcd_document.Document = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -932,7 +940,7 @@ def reload_document( *, name: str = None, gcs_source: gcs.GcsSource = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1049,6 +1057,19 @@ def reload_document( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/documents/transports/base.py b/google/cloud/dialogflow_v2beta1/services/documents/transports/base.py index cfb3e2e03..8ed597481 100644 --- a/google/cloud/dialogflow_v2beta1/services/documents/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/documents/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore -from google.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -40,15 +39,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class DocumentsTransport(abc.ABC): """Abstract transport class for Documents.""" @@ -101,7 +91,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -134,29 +124,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -183,8 +150,17 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/dialogflow_v2beta1/services/documents/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/documents/transports/grpc.py index a959ca976..2c9894dfc 100644 --- a/google/cloud/dialogflow_v2beta1/services/documents/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/documents/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -114,7 +114,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -504,5 +504,8 @@ def reload_document( ) return self._stubs["reload_document"] + def close(self): + self.grpc_channel.close() + __all__ = ("DocumentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/documents/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/documents/transports/grpc_asyncio.py index 8584dbc22..3fa6caa1c 100644 --- a/google/cloud/dialogflow_v2beta1/services/documents/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/documents/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore -from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -161,7 +160,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -521,5 +520,8 @@ def reload_document( ) return self._stubs["reload_document"] + def close(self): + return self.grpc_channel.close() + __all__ = ("DocumentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/entity_types/async_client.py b/google/cloud/dialogflow_v2beta1/services/entity_types/async_client.py index 4e1f861cc..4161cdafa 100644 --- a/google/cloud/dialogflow_v2beta1/services/entity_types/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/entity_types/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2beta1.services.entity_types import pagers @@ -167,11 +172,11 @@ def __init__( async def list_entity_types( self, - request: entity_type.ListEntityTypesRequest = None, + request: Union[entity_type.ListEntityTypesRequest, dict] = None, *, parent: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListEntityTypesAsyncPager: @@ -179,7 +184,7 @@ async def list_entity_types( agent. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListEntityTypesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListEntityTypesRequest, dict]): The request object. The request message for [EntityTypes.ListEntityTypes][google.cloud.dialogflow.v2beta1.EntityTypes.ListEntityTypes]. parent (:class:`str`): @@ -264,18 +269,18 @@ async def list_entity_types( async def get_entity_type( self, - request: entity_type.GetEntityTypeRequest = None, + request: Union[entity_type.GetEntityTypeRequest, dict] = None, *, name: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> entity_type.EntityType: r"""Retrieves the specified entity type. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetEntityTypeRequest, dict]): The request object. The request message for [EntityTypes.GetEntityType][google.cloud.dialogflow.v2beta1.EntityTypes.GetEntityType]. name (:class:`str`): @@ -364,12 +369,12 @@ async def get_entity_type( async def create_entity_type( self, - request: gcd_entity_type.CreateEntityTypeRequest = None, + request: Union[gcd_entity_type.CreateEntityTypeRequest, dict] = None, *, parent: str = None, entity_type: gcd_entity_type.EntityType = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_entity_type.EntityType: @@ -380,7 +385,7 @@ async def create_entity_type( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateEntityTypeRequest, dict]): The request object. The request message for [EntityTypes.CreateEntityType][google.cloud.dialogflow.v2beta1.EntityTypes.CreateEntityType]. parent (:class:`str`): @@ -476,12 +481,12 @@ async def create_entity_type( async def update_entity_type( self, - request: gcd_entity_type.UpdateEntityTypeRequest = None, + request: Union[gcd_entity_type.UpdateEntityTypeRequest, dict] = None, *, entity_type: gcd_entity_type.EntityType = None, language_code: str = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_entity_type.EntityType: @@ -492,7 +497,7 @@ async def update_entity_type( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateEntityTypeRequest, dict]): The request object. The request message for [EntityTypes.UpdateEntityType][google.cloud.dialogflow.v2beta1.EntityTypes.UpdateEntityType]. entity_type (:class:`google.cloud.dialogflow_v2beta1.types.EntityType`): @@ -587,10 +592,10 @@ async def update_entity_type( async def delete_entity_type( self, - request: entity_type.DeleteEntityTypeRequest = None, + request: Union[entity_type.DeleteEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -601,7 +606,7 @@ async def delete_entity_type( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteEntityTypeRequest, dict]): The request object. The request message for [EntityTypes.DeleteEntityType][google.cloud.dialogflow.v2beta1.EntityTypes.DeleteEntityType]. name (:class:`str`): @@ -658,9 +663,9 @@ async def delete_entity_type( async def batch_update_entity_types( self, - request: entity_type.BatchUpdateEntityTypesRequest = None, + request: Union[entity_type.BatchUpdateEntityTypesRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -681,7 +686,7 @@ async def batch_update_entity_types( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.BatchUpdateEntityTypesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.BatchUpdateEntityTypesRequest, dict]): The request object. The request message for [EntityTypes.BatchUpdateEntityTypes][google.cloud.dialogflow.v2beta1.EntityTypes.BatchUpdateEntityTypes]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -733,11 +738,11 @@ async def batch_update_entity_types( async def batch_delete_entity_types( self, - request: entity_type.BatchDeleteEntityTypesRequest = None, + request: Union[entity_type.BatchDeleteEntityTypesRequest, dict] = None, *, parent: str = None, entity_type_names: Sequence[str] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -758,7 +763,7 @@ async def batch_delete_entity_types( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.BatchDeleteEntityTypesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.BatchDeleteEntityTypesRequest, dict]): The request object. The request message for [EntityTypes.BatchDeleteEntityTypes][google.cloud.dialogflow.v2beta1.EntityTypes.BatchDeleteEntityTypes]. parent (:class:`str`): @@ -852,12 +857,12 @@ async def batch_delete_entity_types( async def batch_create_entities( self, - request: entity_type.BatchCreateEntitiesRequest = None, + request: Union[entity_type.BatchCreateEntitiesRequest, dict] = None, *, parent: str = None, entities: Sequence[entity_type.EntityType.Entity] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -878,7 +883,7 @@ async def batch_create_entities( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.BatchCreateEntitiesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.BatchCreateEntitiesRequest, dict]): The request object. The request message for [EntityTypes.BatchCreateEntities][google.cloud.dialogflow.v2beta1.EntityTypes.BatchCreateEntities]. parent (:class:`str`): @@ -982,12 +987,12 @@ async def batch_create_entities( async def batch_update_entities( self, - request: entity_type.BatchUpdateEntitiesRequest = None, + request: Union[entity_type.BatchUpdateEntitiesRequest, dict] = None, *, parent: str = None, entities: Sequence[entity_type.EntityType.Entity] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -1010,7 +1015,7 @@ async def batch_update_entities( message `__ Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.BatchUpdateEntitiesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.BatchUpdateEntitiesRequest, dict]): The request object. The request message for [EntityTypes.BatchUpdateEntities][google.cloud.dialogflow.v2beta1.EntityTypes.BatchUpdateEntities]. parent (:class:`str`): @@ -1116,12 +1121,12 @@ async def batch_update_entities( async def batch_delete_entities( self, - request: entity_type.BatchDeleteEntitiesRequest = None, + request: Union[entity_type.BatchDeleteEntitiesRequest, dict] = None, *, parent: str = None, entity_values: Sequence[str] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -1142,7 +1147,7 @@ async def batch_delete_entities( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.BatchDeleteEntitiesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.BatchDeleteEntitiesRequest, dict]): The request object. The request message for [EntityTypes.BatchDeleteEntities][google.cloud.dialogflow.v2beta1.EntityTypes.BatchDeleteEntities]. parent (:class:`str`): @@ -1247,6 +1252,12 @@ async def batch_delete_entities( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/entity_types/client.py b/google/cloud/dialogflow_v2beta1/services/entity_types/client.py index 988c878fb..8df34db22 100644 --- a/google/cloud/dialogflow_v2beta1/services/entity_types/client.py +++ b/google/cloud/dialogflow_v2beta1/services/entity_types/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2beta1.services.entity_types import pagers @@ -286,8 +290,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -349,10 +360,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_entity_types( @@ -361,7 +369,7 @@ def list_entity_types( *, parent: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListEntityTypesPager: @@ -458,7 +466,7 @@ def get_entity_type( *, name: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> entity_type.EntityType: @@ -559,7 +567,7 @@ def create_entity_type( parent: str = None, entity_type: gcd_entity_type.EntityType = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_entity_type.EntityType: @@ -671,7 +679,7 @@ def update_entity_type( entity_type: gcd_entity_type.EntityType = None, language_code: str = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_entity_type.EntityType: @@ -780,7 +788,7 @@ def delete_entity_type( request: Union[entity_type.DeleteEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -850,7 +858,7 @@ def batch_update_entity_types( self, request: Union[entity_type.BatchUpdateEntityTypesRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -930,7 +938,7 @@ def batch_delete_entity_types( *, parent: str = None, entity_type_names: Sequence[str] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1052,7 +1060,7 @@ def batch_create_entities( parent: str = None, entities: Sequence[entity_type.EntityType.Entity] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1182,7 +1190,7 @@ def batch_update_entities( parent: str = None, entities: Sequence[entity_type.EntityType.Entity] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1316,7 +1324,7 @@ def batch_delete_entities( parent: str = None, entity_values: Sequence[str] = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1442,6 +1450,19 @@ def batch_delete_entities( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/entity_types/transports/base.py b/google/cloud/dialogflow_v2beta1/services/entity_types/transports/base.py index 8a18dff81..5aef232aa 100644 --- a/google/cloud/dialogflow_v2beta1/services/entity_types/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/entity_types/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore -from google.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -41,15 +40,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class EntityTypesTransport(abc.ABC): """Abstract transport class for EntityTypes.""" @@ -102,7 +92,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -135,29 +125,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -203,8 +170,17 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/dialogflow_v2beta1/services/entity_types/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/entity_types/transports/grpc.py index d665a461e..2d73e09f5 100644 --- a/google/cloud/dialogflow_v2beta1/services/entity_types/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/entity_types/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -115,7 +115,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -600,5 +600,8 @@ def batch_delete_entities( ) return self._stubs["batch_delete_entities"] + def close(self): + self.grpc_channel.close() + __all__ = ("EntityTypesGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/entity_types/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/entity_types/transports/grpc_asyncio.py index 474ffef0d..87a5c9ef4 100644 --- a/google/cloud/dialogflow_v2beta1/services/entity_types/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/entity_types/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore -from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -162,7 +161,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -614,5 +613,8 @@ def batch_delete_entities( ) return self._stubs["batch_delete_entities"] + def close(self): + return self.grpc_channel.close() + __all__ = ("EntityTypesGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/environments/async_client.py b/google/cloud/dialogflow_v2beta1/services/environments/async_client.py index 3fd4e5fca..6ac5c01da 100644 --- a/google/cloud/dialogflow_v2beta1/services/environments/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/environments/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.environments import pagers from google.cloud.dialogflow_v2beta1.types import environment from google.cloud.dialogflow_v2beta1.types import fulfillment @@ -167,10 +172,10 @@ def __init__( async def list_environments( self, - request: environment.ListEnvironmentsRequest = None, + request: Union[environment.ListEnvironmentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListEnvironmentsAsyncPager: @@ -178,7 +183,7 @@ async def list_environments( specified agent. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListEnvironmentsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListEnvironmentsRequest, dict]): The request object. The request message for [Environments.ListEnvironments][google.cloud.dialogflow.v2beta1.Environments.ListEnvironments]. parent (:class:`str`): @@ -251,16 +256,16 @@ async def list_environments( async def get_environment( self, - request: environment.GetEnvironmentRequest = None, + request: Union[environment.GetEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: r"""Retrieves the specified agent environment. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetEnvironmentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetEnvironmentRequest, dict]): The request object. The request message for [Environments.GetEnvironment][google.cloud.dialogflow.v2beta1.Environments.GetEnvironment]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -319,16 +324,16 @@ async def get_environment( async def create_environment( self, - request: environment.CreateEnvironmentRequest = None, + request: Union[environment.CreateEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: r"""Creates an agent environment. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateEnvironmentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateEnvironmentRequest, dict]): The request object. The request message for [Environments.CreateEnvironment][google.cloud.dialogflow.v2beta1.Environments.CreateEnvironment]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -387,9 +392,9 @@ async def create_environment( async def update_environment( self, - request: environment.UpdateEnvironmentRequest = None, + request: Union[environment.UpdateEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: @@ -408,7 +413,7 @@ async def update_environment( draft to a version before calling this function. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateEnvironmentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateEnvironmentRequest, dict]): The request object. The request message for [Environments.UpdateEnvironment][google.cloud.dialogflow.v2beta1.Environments.UpdateEnvironment]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -469,16 +474,16 @@ async def update_environment( async def delete_environment( self, - request: environment.DeleteEnvironmentRequest = None, + request: Union[environment.DeleteEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Deletes the specified agent environment. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteEnvironmentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteEnvironmentRequest, dict]): The request object. The request message for [Environments.DeleteEnvironment][google.cloud.dialogflow.v2beta1.Environments.DeleteEnvironment]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -511,16 +516,16 @@ async def delete_environment( async def get_environment_history( self, - request: environment.GetEnvironmentHistoryRequest = None, + request: Union[environment.GetEnvironmentHistoryRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.GetEnvironmentHistoryAsyncPager: r"""Gets the history of the specified environment. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetEnvironmentHistoryRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetEnvironmentHistoryRequest, dict]): The request object. The request message for [Environments.GetEnvironmentHistory][google.cloud.dialogflow.v2beta1.Environments.GetEnvironmentHistory]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -567,6 +572,12 @@ async def get_environment_history( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/environments/client.py b/google/cloud/dialogflow_v2beta1/services/environments/client.py index eb45bdf34..a6006c7b4 100644 --- a/google/cloud/dialogflow_v2beta1/services/environments/client.py +++ b/google/cloud/dialogflow_v2beta1/services/environments/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.environments import pagers from google.cloud.dialogflow_v2beta1.types import environment from google.cloud.dialogflow_v2beta1.types import fulfillment @@ -308,8 +312,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -371,10 +382,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_environments( @@ -382,7 +390,7 @@ def list_environments( request: Union[environment.ListEnvironmentsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListEnvironmentsPager: @@ -465,7 +473,7 @@ def get_environment( self, request: Union[environment.GetEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: @@ -534,7 +542,7 @@ def create_environment( self, request: Union[environment.CreateEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: @@ -603,7 +611,7 @@ def update_environment( self, request: Union[environment.UpdateEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> environment.Environment: @@ -686,7 +694,7 @@ def delete_environment( self, request: Union[environment.DeleteEnvironmentRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -729,7 +737,7 @@ def get_environment_history( self, request: Union[environment.GetEnvironmentHistoryRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.GetEnvironmentHistoryPager: @@ -784,6 +792,19 @@ def get_environment_history( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/environments/transports/base.py b/google/cloud/dialogflow_v2beta1/services/environments/transports/base.py index 66ef0e6d8..8fcbd2e06 100644 --- a/google/cloud/dialogflow_v2beta1/services/environments/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/environments/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class EnvironmentsTransport(abc.ABC): """Abstract transport class for Environments.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -180,6 +147,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_environments( self, diff --git a/google/cloud/dialogflow_v2beta1/services/environments/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/environments/transports/grpc.py index 1ba07220f..d07a46c29 100644 --- a/google/cloud/dialogflow_v2beta1/services/environments/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/environments/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -400,5 +400,8 @@ def get_environment_history( ) return self._stubs["get_environment_history"] + def close(self): + self.grpc_channel.close() + __all__ = ("EnvironmentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/environments/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/environments/transports/grpc_asyncio.py index dc3628da1..007a4521e 100644 --- a/google/cloud/dialogflow_v2beta1/services/environments/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/environments/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -411,5 +410,8 @@ def get_environment_history( ) return self._stubs["get_environment_history"] + def close(self): + return self.grpc_channel.close() + __all__ = ("EnvironmentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/fulfillments/async_client.py b/google/cloud/dialogflow_v2beta1/services/fulfillments/async_client.py index 5f2a149b4..5269ad32e 100644 --- a/google/cloud/dialogflow_v2beta1/services/fulfillments/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/fulfillments/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.types import fulfillment from google.cloud.dialogflow_v2beta1.types import fulfillment as gcd_fulfillment from google.protobuf import field_mask_pb2 # type: ignore @@ -162,17 +167,17 @@ def __init__( async def get_fulfillment( self, - request: fulfillment.GetFulfillmentRequest = None, + request: Union[fulfillment.GetFulfillmentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> fulfillment.Fulfillment: r"""Retrieves the fulfillment. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetFulfillmentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetFulfillmentRequest, dict]): The request object. The request message for [Fulfillments.GetFulfillment][google.cloud.dialogflow.v2beta1.Fulfillments.GetFulfillment]. name (:class:`str`): @@ -246,18 +251,18 @@ async def get_fulfillment( async def update_fulfillment( self, - request: gcd_fulfillment.UpdateFulfillmentRequest = None, + request: Union[gcd_fulfillment.UpdateFulfillmentRequest, dict] = None, *, fulfillment: gcd_fulfillment.Fulfillment = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_fulfillment.Fulfillment: r"""Updates the fulfillment. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateFulfillmentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateFulfillmentRequest, dict]): The request object. The request message for [Fulfillments.UpdateFulfillment][google.cloud.dialogflow.v2beta1.Fulfillments.UpdateFulfillment]. fulfillment (:class:`google.cloud.dialogflow_v2beta1.types.Fulfillment`): @@ -336,6 +341,12 @@ async def update_fulfillment( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/fulfillments/client.py b/google/cloud/dialogflow_v2beta1/services/fulfillments/client.py index b072db119..ae755b45a 100644 --- a/google/cloud/dialogflow_v2beta1/services/fulfillments/client.py +++ b/google/cloud/dialogflow_v2beta1/services/fulfillments/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.types import fulfillment from google.cloud.dialogflow_v2beta1.types import fulfillment as gcd_fulfillment from google.protobuf import field_mask_pb2 # type: ignore @@ -277,8 +281,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -340,10 +351,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def get_fulfillment( @@ -351,7 +359,7 @@ def get_fulfillment( request: Union[fulfillment.GetFulfillmentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> fulfillment.Fulfillment: @@ -436,7 +444,7 @@ def update_fulfillment( *, fulfillment: gcd_fulfillment.Fulfillment = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_fulfillment.Fulfillment: @@ -522,6 +530,19 @@ def update_fulfillment( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/base.py b/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/base.py index 82e05d968..1a44230bc 100644 --- a/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class FulfillmentsTransport(abc.ABC): """Abstract transport class for Fulfillments.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -166,6 +133,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def get_fulfillment( self, diff --git a/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/grpc.py index 85627dc90..1ff5b6ba7 100644 --- a/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -281,5 +281,8 @@ def update_fulfillment( ) return self._stubs["update_fulfillment"] + def close(self): + self.grpc_channel.close() + __all__ = ("FulfillmentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/grpc_asyncio.py index 191446b41..212856995 100644 --- a/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/fulfillments/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -287,5 +286,8 @@ def update_fulfillment( ) return self._stubs["update_fulfillment"] + def close(self): + return self.grpc_channel.close() + __all__ = ("FulfillmentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/intents/async_client.py b/google/cloud/dialogflow_v2beta1/services/intents/async_client.py index 463806566..235d22ea5 100644 --- a/google/cloud/dialogflow_v2beta1/services/intents/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/intents/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2beta1.services.intents import pagers @@ -166,11 +171,11 @@ def __init__( async def list_intents( self, - request: intent.ListIntentsRequest = None, + request: Union[intent.ListIntentsRequest, dict] = None, *, parent: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListIntentsAsyncPager: @@ -178,7 +183,7 @@ async def list_intents( agent. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListIntentsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListIntentsRequest, dict]): The request object. The request message for [Intents.ListIntents][google.cloud.dialogflow.v2beta1.Intents.ListIntents]. parent (:class:`str`): @@ -269,18 +274,18 @@ async def list_intents( async def get_intent( self, - request: intent.GetIntentRequest = None, + request: Union[intent.GetIntentRequest, dict] = None, *, name: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> intent.Intent: r"""Retrieves the specified intent. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetIntentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetIntentRequest, dict]): The request object. The request message for [Intents.GetIntent][google.cloud.dialogflow.v2beta1.Intents.GetIntent]. name (:class:`str`): @@ -364,12 +369,12 @@ async def get_intent( async def create_intent( self, - request: gcd_intent.CreateIntentRequest = None, + request: Union[gcd_intent.CreateIntentRequest, dict] = None, *, parent: str = None, intent: gcd_intent.Intent = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_intent.Intent: @@ -380,7 +385,7 @@ async def create_intent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateIntentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateIntentRequest, dict]): The request object. The request message for [Intents.CreateIntent][google.cloud.dialogflow.v2beta1.Intents.CreateIntent]. parent (:class:`str`): @@ -472,12 +477,12 @@ async def create_intent( async def update_intent( self, - request: gcd_intent.UpdateIntentRequest = None, + request: Union[gcd_intent.UpdateIntentRequest, dict] = None, *, intent: gcd_intent.Intent = None, update_mask: field_mask_pb2.FieldMask = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_intent.Intent: @@ -488,7 +493,7 @@ async def update_intent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateIntentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateIntentRequest, dict]): The request object. The request message for [Intents.UpdateIntent][google.cloud.dialogflow.v2beta1.Intents.UpdateIntent]. intent (:class:`google.cloud.dialogflow_v2beta1.types.Intent`): @@ -579,10 +584,10 @@ async def update_intent( async def delete_intent( self, - request: intent.DeleteIntentRequest = None, + request: Union[intent.DeleteIntentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -594,7 +599,7 @@ async def delete_intent( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteIntentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteIntentRequest, dict]): The request object. The request message for [Intents.DeleteIntent][google.cloud.dialogflow.v2beta1.Intents.DeleteIntent]. name (:class:`str`): @@ -654,12 +659,12 @@ async def delete_intent( async def batch_update_intents( self, - request: intent.BatchUpdateIntentsRequest = None, + request: Union[intent.BatchUpdateIntentsRequest, dict] = None, *, parent: str = None, intent_batch_uri: str = None, intent_batch_inline: intent.IntentBatch = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -680,7 +685,7 @@ async def batch_update_intents( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.BatchUpdateIntentsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.BatchUpdateIntentsRequest, dict]): The request object. The request message for [Intents.BatchUpdateIntents][google.cloud.dialogflow.v2beta1.Intents.BatchUpdateIntents]. parent (:class:`str`): @@ -778,11 +783,11 @@ async def batch_update_intents( async def batch_delete_intents( self, - request: intent.BatchDeleteIntentsRequest = None, + request: Union[intent.BatchDeleteIntentsRequest, dict] = None, *, parent: str = None, intents: Sequence[intent.Intent] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: @@ -803,7 +808,7 @@ async def batch_delete_intents( documentation `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.BatchDeleteIntentsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.BatchDeleteIntentsRequest, dict]): The request object. The request message for [Intents.BatchDeleteIntents][google.cloud.dialogflow.v2beta1.Intents.BatchDeleteIntents]. parent (:class:`str`): @@ -895,6 +900,12 @@ async def batch_delete_intents( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/intents/client.py b/google/cloud/dialogflow_v2beta1/services/intents/client.py index ecc368fbe..bc5f482c0 100644 --- a/google/cloud/dialogflow_v2beta1/services/intents/client.py +++ b/google/cloud/dialogflow_v2beta1/services/intents/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.api_core import operation # type: ignore from google.api_core import operation_async # type: ignore from google.cloud.dialogflow_v2beta1.services.intents import pagers @@ -301,8 +305,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -364,10 +375,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_intents( @@ -376,7 +384,7 @@ def list_intents( *, parent: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListIntentsPager: @@ -479,7 +487,7 @@ def get_intent( *, name: str = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> intent.Intent: @@ -575,7 +583,7 @@ def create_intent( parent: str = None, intent: gcd_intent.Intent = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_intent.Intent: @@ -683,7 +691,7 @@ def update_intent( intent: gcd_intent.Intent = None, update_mask: field_mask_pb2.FieldMask = None, language_code: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_intent.Intent: @@ -788,7 +796,7 @@ def delete_intent( request: Union[intent.DeleteIntentRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -865,7 +873,7 @@ def batch_update_intents( parent: str = None, intent_batch_uri: str = None, intent_batch_inline: intent.IntentBatch = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -988,7 +996,7 @@ def batch_delete_intents( *, parent: str = None, intents: Sequence[intent.Intent] = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: @@ -1101,6 +1109,19 @@ def batch_delete_intents( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/intents/transports/base.py b/google/cloud/dialogflow_v2beta1/services/intents/transports/base.py index 51326baa7..eb785d2c1 100644 --- a/google/cloud/dialogflow_v2beta1/services/intents/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/intents/transports/base.py @@ -15,15 +15,14 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore -from google.api_core import operations_v1 # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -41,15 +40,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class IntentsTransport(abc.ABC): """Abstract transport class for Intents.""" @@ -102,7 +92,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -135,29 +125,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -188,8 +155,17 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property - def operations_client(self) -> operations_v1.OperationsClient: + def operations_client(self): """Return the client designed to process long-running operations.""" raise NotImplementedError() diff --git a/google/cloud/dialogflow_v2beta1/services/intents/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/intents/transports/grpc.py index 4daeef6f6..ce89a9aeb 100644 --- a/google/cloud/dialogflow_v2beta1/services/intents/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/intents/transports/grpc.py @@ -16,9 +16,9 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import operations_v1 # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -115,7 +115,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -465,5 +465,8 @@ def batch_delete_intents( ) return self._stubs["batch_delete_intents"] + def close(self): + self.grpc_channel.close() + __all__ = ("IntentsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/intents/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/intents/transports/grpc_asyncio.py index 8eb39795c..e8552112d 100644 --- a/google/cloud/dialogflow_v2beta1/services/intents/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/intents/transports/grpc_asyncio.py @@ -16,12 +16,11 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore -from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -162,7 +161,7 @@ def __init__( self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials self._stubs: Dict[str, Callable] = {} - self._operations_client = None + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -478,5 +477,8 @@ def batch_delete_intents( ) return self._stubs["batch_delete_intents"] + def close(self): + return self.grpc_channel.close() + __all__ = ("IntentsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/async_client.py b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/async_client.py index b621ba17a..8e83cc0e5 100644 --- a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.knowledge_bases import pagers from google.cloud.dialogflow_v2beta1.types import knowledge_base from google.cloud.dialogflow_v2beta1.types import knowledge_base as gcd_knowledge_base @@ -169,10 +174,10 @@ def __init__( async def list_knowledge_bases( self, - request: knowledge_base.ListKnowledgeBasesRequest = None, + request: Union[knowledge_base.ListKnowledgeBasesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListKnowledgeBasesAsyncPager: @@ -182,7 +187,7 @@ async def list_knowledge_bases( deprecated; only use ``projects.knowledgeBases``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListKnowledgeBasesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListKnowledgeBasesRequest, dict]): The request object. Request message for [KnowledgeBases.ListKnowledgeBases][google.cloud.dialogflow.v2beta1.KnowledgeBases.ListKnowledgeBases]. parent (:class:`str`): @@ -253,10 +258,10 @@ async def list_knowledge_bases( async def get_knowledge_base( self, - request: knowledge_base.GetKnowledgeBaseRequest = None, + request: Union[knowledge_base.GetKnowledgeBaseRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> knowledge_base.KnowledgeBase: @@ -266,7 +271,7 @@ async def get_knowledge_base( deprecated; only use ``projects.knowledgeBases``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetKnowledgeBaseRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetKnowledgeBaseRequest, dict]): The request object. Request message for [KnowledgeBases.GetKnowledgeBase][google.cloud.dialogflow.v2beta1.KnowledgeBases.GetKnowledgeBase]. name (:class:`str`): @@ -338,11 +343,11 @@ async def get_knowledge_base( async def create_knowledge_base( self, - request: gcd_knowledge_base.CreateKnowledgeBaseRequest = None, + request: Union[gcd_knowledge_base.CreateKnowledgeBaseRequest, dict] = None, *, parent: str = None, knowledge_base: gcd_knowledge_base.KnowledgeBase = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_knowledge_base.KnowledgeBase: @@ -352,7 +357,7 @@ async def create_knowledge_base( deprecated; only use ``projects.knowledgeBases``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateKnowledgeBaseRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateKnowledgeBaseRequest, dict]): The request object. Request message for [KnowledgeBases.CreateKnowledgeBase][google.cloud.dialogflow.v2beta1.KnowledgeBases.CreateKnowledgeBase]. parent (:class:`str`): @@ -433,10 +438,10 @@ async def create_knowledge_base( async def delete_knowledge_base( self, - request: knowledge_base.DeleteKnowledgeBaseRequest = None, + request: Union[knowledge_base.DeleteKnowledgeBaseRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -446,7 +451,7 @@ async def delete_knowledge_base( deprecated; only use ``projects.knowledgeBases``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteKnowledgeBaseRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteKnowledgeBaseRequest, dict]): The request object. Request message for [KnowledgeBases.DeleteKnowledgeBase][google.cloud.dialogflow.v2beta1.KnowledgeBases.DeleteKnowledgeBase]. name (:class:`str`): @@ -501,11 +506,11 @@ async def delete_knowledge_base( async def update_knowledge_base( self, - request: gcd_knowledge_base.UpdateKnowledgeBaseRequest = None, + request: Union[gcd_knowledge_base.UpdateKnowledgeBaseRequest, dict] = None, *, knowledge_base: gcd_knowledge_base.KnowledgeBase = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_knowledge_base.KnowledgeBase: @@ -515,7 +520,7 @@ async def update_knowledge_base( deprecated; only use ``projects.knowledgeBases``. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateKnowledgeBaseRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateKnowledgeBaseRequest, dict]): The request object. Request message for [KnowledgeBases.UpdateKnowledgeBase][google.cloud.dialogflow.v2beta1.KnowledgeBases.UpdateKnowledgeBase]. knowledge_base (:class:`google.cloud.dialogflow_v2beta1.types.KnowledgeBase`): @@ -596,6 +601,12 @@ async def update_knowledge_base( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/client.py b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/client.py index c6ba32c12..0ed9d3b81 100644 --- a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/client.py +++ b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.knowledge_bases import pagers from google.cloud.dialogflow_v2beta1.types import knowledge_base from google.cloud.dialogflow_v2beta1.types import knowledge_base as gcd_knowledge_base @@ -284,8 +288,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -347,10 +358,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_knowledge_bases( @@ -358,7 +366,7 @@ def list_knowledge_bases( request: Union[knowledge_base.ListKnowledgeBasesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListKnowledgeBasesPager: @@ -442,7 +450,7 @@ def get_knowledge_base( request: Union[knowledge_base.GetKnowledgeBaseRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> knowledge_base.KnowledgeBase: @@ -528,7 +536,7 @@ def create_knowledge_base( *, parent: str = None, knowledge_base: gcd_knowledge_base.KnowledgeBase = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_knowledge_base.KnowledgeBase: @@ -622,7 +630,7 @@ def delete_knowledge_base( request: Union[knowledge_base.DeleteKnowledgeBaseRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -691,7 +699,7 @@ def update_knowledge_base( *, knowledge_base: gcd_knowledge_base.KnowledgeBase = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_knowledge_base.KnowledgeBase: @@ -782,6 +790,19 @@ def update_knowledge_base( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/base.py b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/base.py index 77e56056b..bfae48e8f 100644 --- a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -39,15 +38,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class KnowledgeBasesTransport(abc.ABC): """Abstract transport class for KnowledgeBases.""" @@ -100,7 +90,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -133,29 +123,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -184,6 +151,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_knowledge_bases( self, diff --git a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/grpc.py index e9186816d..f21716447 100644 --- a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -384,5 +384,8 @@ def update_knowledge_base( ) return self._stubs["update_knowledge_base"] + def close(self): + self.grpc_channel.close() + __all__ = ("KnowledgeBasesGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/grpc_asyncio.py index 3541a6952..da803b64f 100644 --- a/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/knowledge_bases/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -390,5 +389,8 @@ def update_knowledge_base( ) return self._stubs["update_knowledge_base"] + def close(self): + return self.grpc_channel.close() + __all__ = ("KnowledgeBasesGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/participants/async_client.py b/google/cloud/dialogflow_v2beta1/services/participants/async_client.py index 7665ce6fd..8f175cf5e 100644 --- a/google/cloud/dialogflow_v2beta1/services/participants/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/participants/async_client.py @@ -20,13 +20,18 @@ import pkg_resources import warnings -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.participants import pagers from google.cloud.dialogflow_v2beta1.types import participant from google.cloud.dialogflow_v2beta1.types import participant as gcd_participant @@ -177,18 +182,18 @@ def __init__( async def create_participant( self, - request: gcd_participant.CreateParticipantRequest = None, + request: Union[gcd_participant.CreateParticipantRequest, dict] = None, *, parent: str = None, participant: gcd_participant.Participant = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.Participant: r"""Creates a new participant in a conversation. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateParticipantRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateParticipantRequest, dict]): The request object. The request message for [Participants.CreateParticipant][google.cloud.dialogflow.v2beta1.Participants.CreateParticipant]. parent (:class:`str`): @@ -257,17 +262,17 @@ async def create_participant( async def get_participant( self, - request: participant.GetParticipantRequest = None, + request: Union[participant.GetParticipantRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.Participant: r"""Retrieves a conversation participant. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetParticipantRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetParticipantRequest, dict]): The request object. The request message for [Participants.GetParticipant][google.cloud.dialogflow.v2beta1.Participants.GetParticipant]. name (:class:`str`): @@ -328,10 +333,10 @@ async def get_participant( async def list_participants( self, - request: participant.ListParticipantsRequest = None, + request: Union[participant.ListParticipantsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListParticipantsAsyncPager: @@ -339,7 +344,7 @@ async def list_participants( conversation. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListParticipantsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListParticipantsRequest, dict]): The request object. The request message for [Participants.ListParticipants][google.cloud.dialogflow.v2beta1.Participants.ListParticipants]. parent (:class:`str`): @@ -410,18 +415,18 @@ async def list_participants( async def update_participant( self, - request: gcd_participant.UpdateParticipantRequest = None, + request: Union[gcd_participant.UpdateParticipantRequest, dict] = None, *, participant: gcd_participant.Participant = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.Participant: r"""Updates the specified participant. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateParticipantRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateParticipantRequest, dict]): The request object. The request message for [Participants.UpdateParticipant][google.cloud.dialogflow.v2beta1.Participants.UpdateParticipant]. participant (:class:`google.cloud.dialogflow_v2beta1.types.Participant`): @@ -491,12 +496,12 @@ async def update_participant( async def analyze_content( self, - request: gcd_participant.AnalyzeContentRequest = None, + request: Union[gcd_participant.AnalyzeContentRequest, dict] = None, *, participant: str = None, text_input: session.TextInput = None, event_input: session.EventInput = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.AnalyzeContentResponse: @@ -508,7 +513,7 @@ async def analyze_content( environments `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.AnalyzeContentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.AnalyzeContentRequest, dict]): The request object. The request message for [Participants.AnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.AnalyzeContent]. participant (:class:`str`): @@ -597,10 +602,10 @@ async def analyze_content( async def suggest_articles( self, - request: participant.SuggestArticlesRequest = None, + request: Union[participant.SuggestArticlesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestArticlesResponse: @@ -615,7 +620,7 @@ async def suggest_articles( conversation context in the real time. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.SuggestArticlesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.SuggestArticlesRequest, dict]): The request object. The request message for [Participants.SuggestArticles][google.cloud.dialogflow.v2beta1.Participants.SuggestArticles]. parent (:class:`str`): @@ -677,10 +682,10 @@ async def suggest_articles( async def suggest_faq_answers( self, - request: participant.SuggestFaqAnswersRequest = None, + request: Union[participant.SuggestFaqAnswersRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestFaqAnswersResponse: @@ -688,7 +693,7 @@ async def suggest_faq_answers( specific historical messages. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.SuggestFaqAnswersRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.SuggestFaqAnswersRequest, dict]): The request object. The request message for [Participants.SuggestFaqAnswers][google.cloud.dialogflow.v2beta1.Participants.SuggestFaqAnswers]. parent (:class:`str`): @@ -750,10 +755,10 @@ async def suggest_faq_answers( async def suggest_smart_replies( self, - request: participant.SuggestSmartRepliesRequest = None, + request: Union[participant.SuggestSmartRepliesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestSmartRepliesResponse: @@ -761,7 +766,7 @@ async def suggest_smart_replies( specific historical messages. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.SuggestSmartRepliesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.SuggestSmartRepliesRequest, dict]): The request object. The request message for [Participants.SuggestSmartReplies][google.cloud.dialogflow.v2beta1.Participants.SuggestSmartReplies]. parent (:class:`str`): @@ -823,9 +828,9 @@ async def suggest_smart_replies( async def list_suggestions( self, - request: participant.ListSuggestionsRequest = None, + request: Union[participant.ListSuggestionsRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListSuggestionsAsyncPager: @@ -851,7 +856,7 @@ async def list_suggestions( and empty page_token. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListSuggestionsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListSuggestionsRequest, dict]): The request object. The request message for [Participants.ListSuggestions][google.cloud.dialogflow.v2beta1.Participants.ListSuggestions]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -904,9 +909,9 @@ async def list_suggestions( async def compile_suggestion( self, - request: participant.CompileSuggestionRequest = None, + request: Union[participant.CompileSuggestionRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.CompileSuggestionResponse: @@ -927,7 +932,7 @@ async def compile_suggestion( conversation context in the real time. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CompileSuggestionRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CompileSuggestionRequest, dict]): The request object. The request message for [Participants.CompileSuggestion][google.cloud.dialogflow.v2beta1.Participants.CompileSuggestion]. retry (google.api_core.retry.Retry): Designation of what errors, if any, @@ -970,6 +975,12 @@ async def compile_suggestion( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/participants/client.py b/google/cloud/dialogflow_v2beta1/services/participants/client.py index 1e53bb3ed..ba6083695 100644 --- a/google/cloud/dialogflow_v2beta1/services/participants/client.py +++ b/google/cloud/dialogflow_v2beta1/services/participants/client.py @@ -14,23 +14,27 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources import warnings -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.participants import pagers from google.cloud.dialogflow_v2beta1.types import participant from google.cloud.dialogflow_v2beta1.types import participant as gcd_participant @@ -362,8 +366,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -425,10 +436,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def create_participant( @@ -437,7 +445,7 @@ def create_participant( *, parent: str = None, participant: gcd_participant.Participant = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.Participant: @@ -516,7 +524,7 @@ def get_participant( request: Union[participant.GetParticipantRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.Participant: @@ -587,7 +595,7 @@ def list_participants( request: Union[participant.ListParticipantsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListParticipantsPager: @@ -670,7 +678,7 @@ def update_participant( *, participant: gcd_participant.Participant = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.Participant: @@ -752,7 +760,7 @@ def analyze_content( participant: str = None, text_input: session.TextInput = None, event_input: session.EventInput = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_participant.AnalyzeContentResponse: @@ -847,7 +855,7 @@ def suggest_articles( request: Union[participant.SuggestArticlesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestArticlesResponse: @@ -927,7 +935,7 @@ def suggest_faq_answers( request: Union[participant.SuggestFaqAnswersRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestFaqAnswersResponse: @@ -1000,7 +1008,7 @@ def suggest_smart_replies( request: Union[participant.SuggestSmartRepliesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.SuggestSmartRepliesResponse: @@ -1072,7 +1080,7 @@ def list_suggestions( self, request: Union[participant.ListSuggestionsRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListSuggestionsPager: @@ -1154,7 +1162,7 @@ def compile_suggestion( self, request: Union[participant.CompileSuggestionRequest, dict] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> participant.CompileSuggestionResponse: @@ -1218,6 +1226,19 @@ def compile_suggestion( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/participants/transports/base.py b/google/cloud/dialogflow_v2beta1/services/participants/transports/base.py index 012be1e4e..3ad6eccbd 100644 --- a/google/cloud/dialogflow_v2beta1/services/participants/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/participants/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class ParticipantsTransport(abc.ABC): """Abstract transport class for Participants.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -203,6 +170,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def create_participant( self, diff --git a/google/cloud/dialogflow_v2beta1/services/participants/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/participants/transports/grpc.py index 7ea56fbc2..05528d63c 100644 --- a/google/cloud/dialogflow_v2beta1/services/participants/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/participants/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -555,5 +555,8 @@ def compile_suggestion( ) return self._stubs["compile_suggestion"] + def close(self): + self.grpc_channel.close() + __all__ = ("ParticipantsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/participants/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/participants/transports/grpc_asyncio.py index a284d77c1..77766f616 100644 --- a/google/cloud/dialogflow_v2beta1/services/participants/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/participants/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -568,5 +567,8 @@ def compile_suggestion( ) return self._stubs["compile_suggestion"] + def close(self): + return self.grpc_channel.close() + __all__ = ("ParticipantsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/session_entity_types/async_client.py b/google/cloud/dialogflow_v2beta1/services/session_entity_types/async_client.py index da8d49e7f..a0a98efdc 100644 --- a/google/cloud/dialogflow_v2beta1/services/session_entity_types/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/session_entity_types/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.session_entity_types import pagers from google.cloud.dialogflow_v2beta1.types import entity_type from google.cloud.dialogflow_v2beta1.types import session_entity_type @@ -175,10 +180,10 @@ def __init__( async def list_session_entity_types( self, - request: session_entity_type.ListSessionEntityTypesRequest = None, + request: Union[session_entity_type.ListSessionEntityTypesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListSessionEntityTypesAsyncPager: @@ -189,7 +194,7 @@ async def list_session_entity_types( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListSessionEntityTypesRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListSessionEntityTypesRequest, dict]): The request object. The request message for [SessionEntityTypes.ListSessionEntityTypes][google.cloud.dialogflow.v2beta1.SessionEntityTypes.ListSessionEntityTypes]. parent (:class:`str`): @@ -269,10 +274,10 @@ async def list_session_entity_types( async def get_session_entity_type( self, - request: session_entity_type.GetSessionEntityTypeRequest = None, + request: Union[session_entity_type.GetSessionEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> session_entity_type.SessionEntityType: @@ -282,7 +287,7 @@ async def get_session_entity_type( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetSessionEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetSessionEntityTypeRequest, dict]): The request object. The request message for [SessionEntityTypes.GetSessionEntityType][google.cloud.dialogflow.v2beta1.SessionEntityTypes.GetSessionEntityType]. name (:class:`str`): @@ -361,11 +366,13 @@ async def get_session_entity_type( async def create_session_entity_type( self, - request: gcd_session_entity_type.CreateSessionEntityTypeRequest = None, + request: Union[ + gcd_session_entity_type.CreateSessionEntityTypeRequest, dict + ] = None, *, parent: str = None, session_entity_type: gcd_session_entity_type.SessionEntityType = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session_entity_type.SessionEntityType: @@ -378,7 +385,7 @@ async def create_session_entity_type( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateSessionEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateSessionEntityTypeRequest, dict]): The request object. The request message for [SessionEntityTypes.CreateSessionEntityType][google.cloud.dialogflow.v2beta1.SessionEntityTypes.CreateSessionEntityType]. parent (:class:`str`): @@ -466,11 +473,13 @@ async def create_session_entity_type( async def update_session_entity_type( self, - request: gcd_session_entity_type.UpdateSessionEntityTypeRequest = None, + request: Union[ + gcd_session_entity_type.UpdateSessionEntityTypeRequest, dict + ] = None, *, session_entity_type: gcd_session_entity_type.SessionEntityType = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session_entity_type.SessionEntityType: @@ -480,7 +489,7 @@ async def update_session_entity_type( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateSessionEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateSessionEntityTypeRequest, dict]): The request object. The request message for [SessionEntityTypes.UpdateSessionEntityType][google.cloud.dialogflow.v2beta1.SessionEntityTypes.UpdateSessionEntityType]. session_entity_type (:class:`google.cloud.dialogflow_v2beta1.types.SessionEntityType`): @@ -560,10 +569,10 @@ async def update_session_entity_type( async def delete_session_entity_type( self, - request: session_entity_type.DeleteSessionEntityTypeRequest = None, + request: Union[session_entity_type.DeleteSessionEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -573,7 +582,7 @@ async def delete_session_entity_type( use session entities with Google Assistant integration. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteSessionEntityTypeRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteSessionEntityTypeRequest, dict]): The request object. The request message for [SessionEntityTypes.DeleteSessionEntityType][google.cloud.dialogflow.v2beta1.SessionEntityTypes.DeleteSessionEntityType]. name (:class:`str`): @@ -635,6 +644,12 @@ async def delete_session_entity_type( request, retry=retry, timeout=timeout, metadata=metadata, ) + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/session_entity_types/client.py b/google/cloud/dialogflow_v2beta1/services/session_entity_types/client.py index e898ecd4f..45fbc3173 100644 --- a/google/cloud/dialogflow_v2beta1/services/session_entity_types/client.py +++ b/google/cloud/dialogflow_v2beta1/services/session_entity_types/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.session_entity_types import pagers from google.cloud.dialogflow_v2beta1.types import entity_type from google.cloud.dialogflow_v2beta1.types import session_entity_type @@ -290,8 +294,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -353,10 +364,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_session_entity_types( @@ -364,7 +372,7 @@ def list_session_entity_types( request: Union[session_entity_type.ListSessionEntityTypesRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListSessionEntityTypesPager: @@ -460,7 +468,7 @@ def get_session_entity_type( request: Union[session_entity_type.GetSessionEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> session_entity_type.SessionEntityType: @@ -555,7 +563,7 @@ def create_session_entity_type( *, parent: str = None, session_entity_type: gcd_session_entity_type.SessionEntityType = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session_entity_type.SessionEntityType: @@ -666,7 +674,7 @@ def update_session_entity_type( *, session_entity_type: gcd_session_entity_type.SessionEntityType = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session_entity_type.SessionEntityType: @@ -763,7 +771,7 @@ def delete_session_entity_type( request: Union[session_entity_type.DeleteSessionEntityTypeRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -837,6 +845,19 @@ def delete_session_entity_type( request, retry=retry, timeout=timeout, metadata=metadata, ) + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/base.py b/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/base.py index 7f17aaf12..d2afdb66c 100644 --- a/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -41,15 +40,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class SessionEntityTypesTransport(abc.ABC): """Abstract transport class for SessionEntityTypes.""" @@ -102,7 +92,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -135,29 +125,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -188,6 +155,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_session_entity_types( self, diff --git a/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/grpc.py index af6fb4de9..42791f9e1 100644 --- a/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -393,5 +393,8 @@ def delete_session_entity_type( ) return self._stubs["delete_session_entity_type"] + def close(self): + self.grpc_channel.close() + __all__ = ("SessionEntityTypesGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/grpc_asyncio.py index ff6bb820b..18d5dd336 100644 --- a/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/session_entity_types/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -396,5 +395,8 @@ def delete_session_entity_type( ) return self._stubs["delete_session_entity_type"] + def close(self): + return self.grpc_channel.close() + __all__ = ("SessionEntityTypesGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/sessions/async_client.py b/google/cloud/dialogflow_v2beta1/services/sessions/async_client.py index 7ee96e0f1..12834906a 100644 --- a/google/cloud/dialogflow_v2beta1/services/sessions/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/sessions/async_client.py @@ -28,13 +28,18 @@ ) import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.types import audio_config from google.cloud.dialogflow_v2beta1.types import session from google.cloud.dialogflow_v2beta1.types import session as gcd_session @@ -180,11 +185,11 @@ def __init__( async def detect_intent( self, - request: gcd_session.DetectIntentRequest = None, + request: Union[gcd_session.DetectIntentRequest, dict] = None, *, session: str = None, query_input: gcd_session.QueryInput = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session.DetectIntentResponse: @@ -193,12 +198,19 @@ async def detect_intent( because it may cause contexts and session entity types to be updated, which in turn might affect results of future queries. + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [AnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.AnalyzeContent] + instead of ``DetectIntent``. ``AnalyzeContent`` has additional + functionality for Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DetectIntentRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DetectIntentRequest, dict]): The request object. The request to detect user's intent. session (:class:`str`): Required. The name of the session this query is sent to. @@ -309,7 +321,7 @@ def streaming_detect_intent( self, requests: AsyncIterator[session.StreamingDetectIntentRequest] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> Awaitable[AsyncIterable[session.StreamingDetectIntentResponse]]: @@ -318,6 +330,14 @@ def streaming_detect_intent( result. This method is only available via the gRPC API (not REST). + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [StreamingAnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.StreamingAnalyzeContent] + instead of ``StreamingDetectIntent``. + ``StreamingAnalyzeContent`` has additional functionality for + Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -373,11 +393,12 @@ def streaming_detect_intent( Multiple response messages can be returned in order: - 1. If the input was set to streaming audio, the first - one or more messages contain recognition_result. - Each recognition_result represents a more complete - transcript of what the user said. The last - recognition_result has is_final set to true. + 1. If the StreamingDetectIntentRequest.input_audio + field was set, the recognition_result field is + populated for one or more messages. See the + [StreamingRecognitionResult][google.cloud.dialogflow.v2beta1.StreamingRecognitionResult] + message for details about the result message + sequence. 2. The next message contains response_id, query_result, alternative_query_results and optionally webhook_status if a WebHook was called. @@ -402,6 +423,12 @@ def streaming_detect_intent( # Done; return the response. return response + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/sessions/client.py b/google/cloud/dialogflow_v2beta1/services/sessions/client.py index f27f16997..d7db82c7f 100644 --- a/google/cloud/dialogflow_v2beta1/services/sessions/client.py +++ b/google/cloud/dialogflow_v2beta1/services/sessions/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Iterable, Iterator, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.types import audio_config from google.cloud.dialogflow_v2beta1.types import session from google.cloud.dialogflow_v2beta1.types import session as gcd_session @@ -345,8 +349,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -408,10 +419,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def detect_intent( @@ -420,7 +428,7 @@ def detect_intent( *, session: str = None, query_input: gcd_session.QueryInput = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_session.DetectIntentResponse: @@ -429,6 +437,13 @@ def detect_intent( because it may cause contexts and session entity types to be updated, which in turn might affect results of future queries. + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [AnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.AnalyzeContent] + instead of ``DetectIntent``. ``AnalyzeContent`` has additional + functionality for Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -536,7 +551,7 @@ def streaming_detect_intent( self, requests: Iterator[session.StreamingDetectIntentRequest] = None, *, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> Iterable[session.StreamingDetectIntentResponse]: @@ -545,6 +560,14 @@ def streaming_detect_intent( result. This method is only available via the gRPC API (not REST). + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [StreamingAnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.StreamingAnalyzeContent] + instead of ``StreamingDetectIntent``. + ``StreamingAnalyzeContent`` has additional functionality for + Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -600,11 +623,12 @@ def streaming_detect_intent( Multiple response messages can be returned in order: - 1. If the input was set to streaming audio, the first - one or more messages contain recognition_result. - Each recognition_result represents a more complete - transcript of what the user said. The last - recognition_result has is_final set to true. + 1. If the StreamingDetectIntentRequest.input_audio + field was set, the recognition_result field is + populated for one or more messages. See the + [StreamingRecognitionResult][google.cloud.dialogflow.v2beta1.StreamingRecognitionResult] + message for details about the result message + sequence. 2. The next message contains response_id, query_result, alternative_query_results and optionally webhook_status if a WebHook was called. @@ -625,6 +649,19 @@ def streaming_detect_intent( # Done; return the response. return response + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/sessions/transports/base.py b/google/cloud/dialogflow_v2beta1/services/sessions/transports/base.py index eeee66bd9..110df02f0 100644 --- a/google/cloud/dialogflow_v2beta1/services/sessions/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/sessions/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -38,15 +37,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class SessionsTransport(abc.ABC): """Abstract transport class for Sessions.""" @@ -99,7 +89,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -132,29 +122,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -179,6 +146,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def detect_intent( self, diff --git a/google/cloud/dialogflow_v2beta1/services/sessions/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/sessions/transports/grpc.py index e0abc222d..47877f8d7 100644 --- a/google/cloud/dialogflow_v2beta1/services/sessions/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/sessions/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -240,6 +240,13 @@ def detect_intent( because it may cause contexts and session entity types to be updated, which in turn might affect results of future queries. + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [AnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.AnalyzeContent] + instead of ``DetectIntent``. ``AnalyzeContent`` has additional + functionality for Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -275,6 +282,14 @@ def streaming_detect_intent( result. This method is only available via the gRPC API (not REST). + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [StreamingAnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.StreamingAnalyzeContent] + instead of ``StreamingDetectIntent``. + ``StreamingAnalyzeContent`` has additional functionality for + Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -297,5 +312,8 @@ def streaming_detect_intent( ) return self._stubs["streaming_detect_intent"] + def close(self): + self.grpc_channel.close() + __all__ = ("SessionsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/sessions/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/sessions/transports/grpc_asyncio.py index 82f0f1e1b..2e65f0829 100644 --- a/google/cloud/dialogflow_v2beta1/services/sessions/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/sessions/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -245,6 +244,13 @@ def detect_intent( because it may cause contexts and session entity types to be updated, which in turn might affect results of future queries. + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [AnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.AnalyzeContent] + instead of ``DetectIntent``. ``AnalyzeContent`` has additional + functionality for Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -281,6 +287,14 @@ def streaming_detect_intent( result. This method is only available via the gRPC API (not REST). + If you might use `Agent + Assist `__ or + other CCAI products now or in the future, consider using + [StreamingAnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.StreamingAnalyzeContent] + instead of ``StreamingDetectIntent``. + ``StreamingAnalyzeContent`` has additional functionality for + Agent Assist and other CCAI products. + Note: Always use agent versions for production traffic. See `Versions and environments `__. @@ -303,5 +317,8 @@ def streaming_detect_intent( ) return self._stubs["streaming_detect_intent"] + def close(self): + return self.grpc_channel.close() + __all__ = ("SessionsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/versions/async_client.py b/google/cloud/dialogflow_v2beta1/services/versions/async_client.py index 05f84d7fa..3081dc308 100644 --- a/google/cloud/dialogflow_v2beta1/services/versions/async_client.py +++ b/google/cloud/dialogflow_v2beta1/services/versions/async_client.py @@ -19,13 +19,18 @@ from typing import Dict, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core.client_options import ClientOptions +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.versions import pagers from google.cloud.dialogflow_v2beta1.types import version from google.cloud.dialogflow_v2beta1.types import version as gcd_version @@ -160,10 +165,10 @@ def __init__( async def list_versions( self, - request: version.ListVersionsRequest = None, + request: Union[version.ListVersionsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListVersionsAsyncPager: @@ -171,7 +176,7 @@ async def list_versions( agent. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.ListVersionsRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.ListVersionsRequest, dict]): The request object. The request message for [Versions.ListVersions][google.cloud.dialogflow.v2beta1.Versions.ListVersions]. parent (:class:`str`): @@ -244,17 +249,17 @@ async def list_versions( async def get_version( self, - request: version.GetVersionRequest = None, + request: Union[version.GetVersionRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> version.Version: r"""Retrieves the specified agent version. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.GetVersionRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.GetVersionRequest, dict]): The request object. The request message for [Versions.GetVersion][google.cloud.dialogflow.v2beta1.Versions.GetVersion]. name (:class:`str`): @@ -336,11 +341,11 @@ async def get_version( async def create_version( self, - request: gcd_version.CreateVersionRequest = None, + request: Union[gcd_version.CreateVersionRequest, dict] = None, *, parent: str = None, version: gcd_version.Version = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_version.Version: @@ -349,7 +354,7 @@ async def create_version( "default" environment. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.CreateVersionRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.CreateVersionRequest, dict]): The request object. The request message for [Versions.CreateVersion][google.cloud.dialogflow.v2beta1.Versions.CreateVersion]. parent (:class:`str`): @@ -439,11 +444,11 @@ async def create_version( async def update_version( self, - request: gcd_version.UpdateVersionRequest = None, + request: Union[gcd_version.UpdateVersionRequest, dict] = None, *, version: gcd_version.Version = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_version.Version: @@ -454,7 +459,7 @@ async def update_version( version resource. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.UpdateVersionRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.UpdateVersionRequest, dict]): The request object. The request message for [Versions.UpdateVersion][google.cloud.dialogflow.v2beta1.Versions.UpdateVersion]. version (:class:`google.cloud.dialogflow_v2beta1.types.Version`): @@ -547,17 +552,17 @@ async def update_version( async def delete_version( self, - request: version.DeleteVersionRequest = None, + request: Union[version.DeleteVersionRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: r"""Delete the specified agent version. Args: - request (:class:`google.cloud.dialogflow_v2beta1.types.DeleteVersionRequest`): + request (Union[google.cloud.dialogflow_v2beta1.types.DeleteVersionRequest, dict]): The request object. The request message for [Versions.DeleteVersion][google.cloud.dialogflow.v2beta1.Versions.DeleteVersion]. name (:class:`str`): @@ -612,6 +617,12 @@ async def delete_version( request, retry=retry, timeout=timeout, metadata=metadata, ) + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/versions/client.py b/google/cloud/dialogflow_v2beta1/services/versions/client.py index 40b0118cc..de312b103 100644 --- a/google/cloud/dialogflow_v2beta1/services/versions/client.py +++ b/google/cloud/dialogflow_v2beta1/services/versions/client.py @@ -14,22 +14,26 @@ # limitations under the License. # from collections import OrderedDict -from distutils import util import os import re from typing import Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport import mtls # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + from google.cloud.dialogflow_v2beta1.services.versions import pagers from google.cloud.dialogflow_v2beta1.types import version from google.cloud.dialogflow_v2beta1.types import version as gcd_version @@ -283,8 +287,15 @@ def __init__( client_options = client_options_lib.ClientOptions() # Create SSL credentials for mutual TLS if needed. - use_client_cert = bool( - util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" ) client_cert_source_func = None @@ -346,10 +357,7 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, - always_use_jwt_access=( - Transport == type(self).get_transport_class("grpc") - or Transport == type(self).get_transport_class("grpc_asyncio") - ), + always_use_jwt_access=True, ) def list_versions( @@ -357,7 +365,7 @@ def list_versions( request: Union[version.ListVersionsRequest, dict] = None, *, parent: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListVersionsPager: @@ -441,7 +449,7 @@ def get_version( request: Union[version.GetVersionRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> version.Version: @@ -534,7 +542,7 @@ def create_version( *, parent: str = None, version: gcd_version.Version = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_version.Version: @@ -637,7 +645,7 @@ def update_version( *, version: gcd_version.Version = None, update_mask: field_mask_pb2.FieldMask = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> gcd_version.Version: @@ -744,7 +752,7 @@ def delete_version( request: Union[version.DeleteVersionRequest, dict] = None, *, name: str = None, - retry: retries.Retry = gapic_v1.method.DEFAULT, + retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> None: @@ -806,6 +814,19 @@ def delete_version( request, retry=retry, timeout=timeout, metadata=metadata, ) + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + try: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( diff --git a/google/cloud/dialogflow_v2beta1/services/versions/transports/base.py b/google/cloud/dialogflow_v2beta1/services/versions/transports/base.py index 5997854da..97b2c1c0c 100644 --- a/google/cloud/dialogflow_v2beta1/services/versions/transports/base.py +++ b/google/cloud/dialogflow_v2beta1/services/versions/transports/base.py @@ -15,14 +15,13 @@ # import abc from typing import Awaitable, Callable, Dict, Optional, Sequence, Union -import packaging.version import pkg_resources import google.auth # type: ignore -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries from google.auth import credentials as ga_credentials # type: ignore from google.oauth2 import service_account # type: ignore @@ -39,15 +38,6 @@ except pkg_resources.DistributionNotFound: DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() -try: - # google.auth.__version__ was added in 1.26.0 - _GOOGLE_AUTH_VERSION = google.auth.__version__ -except AttributeError: - try: # try pkg_resources if it is available - _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version - except pkg_resources.DistributionNotFound: # pragma: NO COVER - _GOOGLE_AUTH_VERSION = None - class VersionsTransport(abc.ABC): """Abstract transport class for Versions.""" @@ -100,7 +90,7 @@ def __init__( host += ":443" self._host = host - scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} # Save the scopes. self._scopes = scopes @@ -133,29 +123,6 @@ def __init__( # Save the credentials. self._credentials = credentials - # TODO(busunkim): This method is in the base transport - # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-auth is increased. - - # TODO: Remove this function once google-auth >= 1.25.0 is required - @classmethod - def _get_scopes_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Optional[Sequence[str]]]: - """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" - - scopes_kwargs = {} - - if _GOOGLE_AUTH_VERSION and ( - packaging.version.parse(_GOOGLE_AUTH_VERSION) - >= packaging.version.parse("1.25.0") - ): - scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} - else: - scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} - - return scopes_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -176,6 +143,15 @@ def _prep_wrapped_messages(self, client_info): ), } + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + @property def list_versions( self, diff --git a/google/cloud/dialogflow_v2beta1/services/versions/transports/grpc.py b/google/cloud/dialogflow_v2beta1/services/versions/transports/grpc.py index b63e8c128..e14f4b908 100644 --- a/google/cloud/dialogflow_v2beta1/services/versions/transports/grpc.py +++ b/google/cloud/dialogflow_v2beta1/services/versions/transports/grpc.py @@ -16,8 +16,8 @@ import warnings from typing import Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import grpc_helpers # type: ignore -from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 import google.auth # type: ignore from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -363,5 +363,8 @@ def delete_version( ) return self._stubs["delete_version"] + def close(self): + self.grpc_channel.close() + __all__ = ("VersionsGrpcTransport",) diff --git a/google/cloud/dialogflow_v2beta1/services/versions/transports/grpc_asyncio.py b/google/cloud/dialogflow_v2beta1/services/versions/transports/grpc_asyncio.py index 27e7a8e5f..e4257adbf 100644 --- a/google/cloud/dialogflow_v2beta1/services/versions/transports/grpc_asyncio.py +++ b/google/cloud/dialogflow_v2beta1/services/versions/transports/grpc_asyncio.py @@ -16,11 +16,10 @@ import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union -from google.api_core import gapic_v1 # type: ignore -from google.api_core import grpc_helpers_async # type: ignore +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async from google.auth import credentials as ga_credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore -import packaging.version import grpc # type: ignore from grpc.experimental import aio # type: ignore @@ -370,5 +369,8 @@ def delete_version( ) return self._stubs["delete_version"] + def close(self): + return self.grpc_channel.close() + __all__ = ("VersionsGrpcAsyncIOTransport",) diff --git a/google/cloud/dialogflow_v2beta1/types/agent.py b/google/cloud/dialogflow_v2beta1/types/agent.py index fc51cfd93..08b9b7a57 100644 --- a/google/cloud/dialogflow_v2beta1/types/agent.py +++ b/google/cloud/dialogflow_v2beta1/types/agent.py @@ -194,6 +194,7 @@ class DeleteAgentRequest(proto.Message): class SubAgent(proto.Message): r"""Contains basic configuration for a sub-agent. + Attributes: project (str): Required. The project of this agent. Format: @@ -293,13 +294,24 @@ class ExportAgentResponse(proto.Message): r"""The response message for [Agents.ExportAgent][google.cloud.dialogflow.v2beta1.Agents.ExportAgent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: agent_uri (str): The URI to a file containing the exported agent. This field is populated only if ``agent_uri`` is specified in ``ExportAgentRequest``. + + This field is a member of `oneof`_ ``agent``. agent_content (bytes): Zip compressed raw byte content for agent. + + This field is a member of `oneof`_ ``agent``. """ agent_uri = proto.Field(proto.STRING, number=1, oneof="agent",) @@ -310,6 +322,13 @@ class ImportAgentRequest(proto.Message): r"""The request message for [Agents.ImportAgent][google.cloud.dialogflow.v2beta1.Agents.ImportAgent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: parent (str): Required. The project that the agent to import is associated @@ -319,8 +338,12 @@ class ImportAgentRequest(proto.Message): The URI to a Google Cloud Storage file containing the agent to import. Note: The URI must start with "gs://". + + This field is a member of `oneof`_ ``agent``. agent_content (bytes): Zip compressed raw byte content for agent. + + This field is a member of `oneof`_ ``agent``. """ parent = proto.Field(proto.STRING, number=1,) @@ -332,6 +355,13 @@ class RestoreAgentRequest(proto.Message): r"""The request message for [Agents.RestoreAgent][google.cloud.dialogflow.v2beta1.Agents.RestoreAgent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: parent (str): Required. The project that the agent to restore is @@ -341,8 +371,12 @@ class RestoreAgentRequest(proto.Message): The URI to a Google Cloud Storage file containing the agent to restore. Note: The URI must start with "gs://". + + This field is a member of `oneof`_ ``agent``. agent_content (bytes): Zip compressed raw byte content for agent. + + This field is a member of `oneof`_ ``agent``. """ parent = proto.Field(proto.STRING, number=1,) diff --git a/google/cloud/dialogflow_v2beta1/types/answer_record.py b/google/cloud/dialogflow_v2beta1/types/answer_record.py index b645483eb..8d81ebef7 100644 --- a/google/cloud/dialogflow_v2beta1/types/answer_record.py +++ b/google/cloud/dialogflow_v2beta1/types/answer_record.py @@ -65,6 +65,9 @@ class AnswerRecord(proto.Message): to call the [UpdateAnswerRecord][] method to send feedback about a specific answer that they believe is wrong. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): The unique identifier of this answer record. Required for @@ -79,6 +82,8 @@ class AnswerRecord(proto.Message): agent_assistant_record (google.cloud.dialogflow_v2beta1.types.AgentAssistantRecord): Output only. The record for human agent assistant. + + This field is a member of `oneof`_ ``record``. """ name = proto.Field(proto.STRING, number=1,) @@ -90,11 +95,23 @@ class AnswerRecord(proto.Message): class AgentAssistantRecord(proto.Message): r"""Represents a record of a human agent assistant answer. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: article_suggestion_answer (google.cloud.dialogflow_v2beta1.types.ArticleAnswer): Output only. The article suggestion answer. + + This field is a member of `oneof`_ ``answer``. faq_answer (google.cloud.dialogflow_v2beta1.types.FaqAnswer): Output only. The FAQ answer. + + This field is a member of `oneof`_ ``answer``. """ article_suggestion_answer = proto.Field( @@ -109,12 +126,17 @@ class AnswerFeedback(proto.Message): r"""Represents feedback the customer has about the quality & correctness of a certain answer in a conversation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: correctness_level (google.cloud.dialogflow_v2beta1.types.AnswerFeedback.CorrectnessLevel): The correctness level of the specific answer. agent_assistant_detail_feedback (google.cloud.dialogflow_v2beta1.types.AgentAssistantFeedback): Optional. Detail feedback of agent assistant suggestions. + + This field is a member of `oneof`_ ``detail_feedback``. clicked (bool): Indicates whether the answer/item was clicked by the human agent or not. Default to false. @@ -152,6 +174,7 @@ class CorrectnessLevel(proto.Enum): class AgentAssistantFeedback(proto.Message): r"""Detail feedback of Agent Assistant result. + Attributes: answer_relevance (google.cloud.dialogflow_v2beta1.types.AgentAssistantFeedback.AnswerRelevance): Optional. Whether or not the suggested answer is relevant. @@ -207,6 +230,7 @@ class DocumentEfficiency(proto.Enum): class SummarizationFeedback(proto.Message): r"""Feedback for conversation summarization. + Attributes: start_timestamp (google.protobuf.timestamp_pb2.Timestamp): Timestamp when composing of the summary diff --git a/google/cloud/dialogflow_v2beta1/types/audio_config.py b/google/cloud/dialogflow_v2beta1/types/audio_config.py index 737f9c059..e0d0e772e 100644 --- a/google/cloud/dialogflow_v2beta1/types/audio_config.py +++ b/google/cloud/dialogflow_v2beta1/types/audio_config.py @@ -156,6 +156,7 @@ class SpeechContext(proto.Message): class SpeechWordInfo(proto.Message): r"""Information for a word recognized by the speech recognizer. + Attributes: word (str): The word this info is for. @@ -287,6 +288,7 @@ class InputAudioConfig(proto.Message): class VoiceSelectionParams(proto.Message): r"""Description of which voice to use for speech synthesis. + Attributes: name (str): Optional. The name of the voice. If not set, the service @@ -314,6 +316,7 @@ class VoiceSelectionParams(proto.Message): class SynthesizeSpeechConfig(proto.Message): r"""Configuration of how speech should be synthesized. + Attributes: speaking_rate (float): Optional. Speaking rate/speed, in the range [0.25, 4.0]. 1.0 @@ -387,6 +390,7 @@ class OutputAudioConfig(proto.Message): class TelephonyDtmfEvents(proto.Message): r"""A wrapper of repeated TelephonyDtmf digits. + Attributes: dtmf_events (Sequence[google.cloud.dialogflow_v2beta1.types.TelephonyDtmf]): A sequence of TelephonyDtmf digits. diff --git a/google/cloud/dialogflow_v2beta1/types/conversation_event.py b/google/cloud/dialogflow_v2beta1/types/conversation_event.py index dee158441..27ff0c52c 100644 --- a/google/cloud/dialogflow_v2beta1/types/conversation_event.py +++ b/google/cloud/dialogflow_v2beta1/types/conversation_event.py @@ -28,6 +28,9 @@ class ConversationEvent(proto.Message): r"""Represents a notification sent to Pub/Sub subscribers for conversation lifecycle events. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: conversation (str): Required. The unique identifier of the conversation this @@ -41,6 +44,8 @@ class ConversationEvent(proto.Message): for type UNRECOVERABLE_ERROR_IN_PHONE_CALL. new_message_payload (google.cloud.dialogflow_v2beta1.types.Message): Payload of NEW_MESSAGE event. + + This field is a member of `oneof`_ ``payload``. """ class Type(proto.Enum): diff --git a/google/cloud/dialogflow_v2beta1/types/conversation_profile.py b/google/cloud/dialogflow_v2beta1/types/conversation_profile.py index 74039c0b8..ed80a0635 100644 --- a/google/cloud/dialogflow_v2beta1/types/conversation_profile.py +++ b/google/cloud/dialogflow_v2beta1/types/conversation_profile.py @@ -131,6 +131,7 @@ class ConversationProfile(proto.Message): class AutomatedAgentConfig(proto.Message): r"""Defines the Automated Agent to connect to a conversation. + Attributes: agent (str): Required. ID of the Dialogflow agent environment to use. @@ -178,6 +179,7 @@ class HumanAgentAssistantConfig(proto.Message): class SuggestionTriggerSettings(proto.Message): r"""Settings of suggestion trigger. + Attributes: no_small_talk (bool): Do not trigger if last utterance is small @@ -192,6 +194,7 @@ class SuggestionTriggerSettings(proto.Message): class SuggestionFeatureConfig(proto.Message): r"""Config for suggestion features. + Attributes: suggestion_feature (google.cloud.dialogflow_v2beta1.types.SuggestionFeature): The suggestion feature. @@ -234,6 +237,7 @@ class SuggestionFeatureConfig(proto.Message): class SuggestionConfig(proto.Message): r"""Detail human agent assistant config. + Attributes: feature_configs (Sequence[google.cloud.dialogflow_v2beta1.types.HumanAgentAssistantConfig.SuggestionFeatureConfig]): Configuration of different suggestion @@ -262,16 +266,30 @@ class SuggestionConfig(proto.Message): class SuggestionQueryConfig(proto.Message): r"""Config for suggestion query. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: knowledge_base_query_source (google.cloud.dialogflow_v2beta1.types.HumanAgentAssistantConfig.SuggestionQueryConfig.KnowledgeBaseQuerySource): Query from knowledgebase. It is used by: ARTICLE_SUGGESTION, FAQ. + + This field is a member of `oneof`_ ``query_source``. document_query_source (google.cloud.dialogflow_v2beta1.types.HumanAgentAssistantConfig.SuggestionQueryConfig.DocumentQuerySource): Query from knowledge base document. It is used by: SMART_REPLY, SMART_COMPOSE. + + This field is a member of `oneof`_ ``query_source``. dialogflow_query_source (google.cloud.dialogflow_v2beta1.types.HumanAgentAssistantConfig.SuggestionQueryConfig.DialogflowQuerySource): Query from Dialogflow agent. It is used by DIALOGFLOW_ASSIST. + + This field is a member of `oneof`_ ``query_source``. max_results (int): Maximum number of results to return. Currently, if unset, defaults to 10. And the max @@ -469,11 +487,22 @@ class HumanAgentHandoffConfig(proto.Message): Currently, this feature is not general available, please contact Google to get access. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: live_person_config (google.cloud.dialogflow_v2beta1.types.HumanAgentHandoffConfig.LivePersonConfig): Uses LivePerson (https://www.liveperson.com). + + This field is a member of `oneof`_ ``agent_service``. salesforce_live_agent_config (google.cloud.dialogflow_v2beta1.types.HumanAgentHandoffConfig.SalesforceLiveAgentConfig): Uses Salesforce Live Agent. + + This field is a member of `oneof`_ ``agent_service``. """ class LivePersonConfig(proto.Message): @@ -491,6 +520,7 @@ class LivePersonConfig(proto.Message): class SalesforceLiveAgentConfig(proto.Message): r"""Configuration specific to Salesforce Live Agent. + Attributes: organization_id (str): Required. The organization ID of the @@ -525,6 +555,7 @@ class SalesforceLiveAgentConfig(proto.Message): class NotificationConfig(proto.Message): r"""Defines notification behavior. + Attributes: topic (str): Name of the Pub/Sub topic to publish conversation events @@ -557,6 +588,7 @@ class MessageFormat(proto.Enum): class LoggingConfig(proto.Message): r"""Defines logging behavior for conversation lifecycle events. + Attributes: enable_stackdriver_logging (bool): Whether to log conversation events like diff --git a/google/cloud/dialogflow_v2beta1/types/document.py b/google/cloud/dialogflow_v2beta1/types/document.py index 4597aeb95..e4edae621 100644 --- a/google/cloud/dialogflow_v2beta1/types/document.py +++ b/google/cloud/dialogflow_v2beta1/types/document.py @@ -50,6 +50,13 @@ class Document(proto.Message): Note: The ``projects.agent.knowledgeBases.documents`` resource is deprecated; only use ``projects.knowledgeBases.documents``. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): Optional. The document resource name. The name must be empty @@ -75,14 +82,20 @@ class Document(proto.Message): URLs for showing documents in Google Cloud Storage (i.e. the URL in your browser) are not supported. Instead use the ``gs://`` format URI described above. + + This field is a member of `oneof`_ ``source``. content (str): The raw content of the document. This field is only permitted for EXTRACTIVE_QA and FAQ knowledge types. Note: This field is in the process of being deprecated, please use raw_content instead. + + This field is a member of `oneof`_ ``source``. raw_content (bytes): The raw content of the document. This field is only permitted for EXTRACTIVE_QA and FAQ knowledge types. + + This field is a member of `oneof`_ ``source``. enable_auto_reload (bool): Optional. If true, we try to automatically reload the document every day (at a time picked by the system). If @@ -125,6 +138,7 @@ class KnowledgeType(proto.Enum): class ReloadStatus(proto.Message): r"""The status of a reload attempt. + Attributes: time (google.protobuf.timestamp_pb2.Timestamp): Output only. The time of a reload attempt. @@ -258,6 +272,9 @@ class ImportDocumentsRequest(proto.Message): r"""Request message for [Documents.ImportDocuments][google.cloud.dialogflow.v2beta1.Documents.ImportDocuments]. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: parent (str): Required. The knowledge base to import documents into. @@ -270,6 +287,8 @@ class ImportDocumentsRequest(proto.Message): These URIs may have the forms ``gs:///``. ``gs:////*.``. + + This field is a member of `oneof`_ ``source``. document_template (google.cloud.dialogflow_v2beta1.types.ImportDocumentTemplate): Required. Document template used for importing all the documents. @@ -291,6 +310,7 @@ class ImportDocumentsRequest(proto.Message): class ImportDocumentTemplate(proto.Message): r"""The template used for importing documents. + Attributes: mime_type (str): Required. The MIME type of the document. @@ -381,6 +401,9 @@ class ReloadDocumentRequest(proto.Message): r"""Request message for [Documents.ReloadDocument][google.cloud.dialogflow.v2beta1.Documents.ReloadDocument]. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): Required. The name of the document to reload. Format: @@ -389,6 +412,8 @@ class ReloadDocumentRequest(proto.Message): The path for a Cloud Storage source file for reloading document content. If not provided, the Document's existing source will be reloaded. + + This field is a member of `oneof`_ ``source``. import_gcs_custom_metadata (bool): Whether to import custom metadata from Google Cloud Storage. Only valid when the document diff --git a/google/cloud/dialogflow_v2beta1/types/entity_type.py b/google/cloud/dialogflow_v2beta1/types/entity_type.py index 1143c6b55..8eaad0152 100644 --- a/google/cloud/dialogflow_v2beta1/types/entity_type.py +++ b/google/cloud/dialogflow_v2beta1/types/entity_type.py @@ -97,6 +97,7 @@ class AutoExpansionMode(proto.Enum): class Entity(proto.Message): r"""An **entity entry** for an associated entity type. + Attributes: value (str): Required. The primary value associated with this entity @@ -281,6 +282,13 @@ class BatchUpdateEntityTypesRequest(proto.Message): r"""The request message for [EntityTypes.BatchUpdateEntityTypes][google.cloud.dialogflow.v2beta1.EntityTypes.BatchUpdateEntityTypes]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: parent (str): Required. The name of the agent to update or create entity @@ -294,9 +302,13 @@ class BatchUpdateEntityTypesRequest(proto.Message): file format can either be a serialized proto (of EntityBatch type) or a JSON object. Note: The URI must start with "gs://". + + This field is a member of `oneof`_ ``entity_type_batch``. entity_type_batch_inline (google.cloud.dialogflow_v2beta1.types.EntityTypeBatch): The collection of entity types to update or create. + + This field is a member of `oneof`_ ``entity_type_batch``. language_code (str): Optional. The language used to access language-specific data. If not specified, the agent's default language is diff --git a/google/cloud/dialogflow_v2beta1/types/environment.py b/google/cloud/dialogflow_v2beta1/types/environment.py index 5ee003e2f..f24d1e574 100644 --- a/google/cloud/dialogflow_v2beta1/types/environment.py +++ b/google/cloud/dialogflow_v2beta1/types/environment.py @@ -333,6 +333,7 @@ class EnvironmentHistory(proto.Message): class Entry(proto.Message): r"""Represents an environment history entry. + Attributes: agent_version (str): The agent version loaded into this diff --git a/google/cloud/dialogflow_v2beta1/types/fulfillment.py b/google/cloud/dialogflow_v2beta1/types/fulfillment.py index a77f89e38..206a47109 100644 --- a/google/cloud/dialogflow_v2beta1/types/fulfillment.py +++ b/google/cloud/dialogflow_v2beta1/types/fulfillment.py @@ -36,6 +36,9 @@ class Fulfillment(proto.Message): For more information, see the `fulfillment guide `__. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): Required. The unique identifier of the fulfillment. @@ -52,6 +55,8 @@ class Fulfillment(proto.Message): Environment. generic_web_service (google.cloud.dialogflow_v2beta1.types.Fulfillment.GenericWebService): Configuration for a generic web service. + + This field is a member of `oneof`_ ``fulfillment``. enabled (bool): Whether fulfillment is enabled. features (Sequence[google.cloud.dialogflow_v2beta1.types.Fulfillment.Feature]): @@ -94,6 +99,7 @@ class GenericWebService(proto.Message): class Feature(proto.Message): r"""Whether fulfillment is enabled for the specific feature. + Attributes: type_ (google.cloud.dialogflow_v2beta1.types.Fulfillment.Feature.Type): The type of the feature that enabled for diff --git a/google/cloud/dialogflow_v2beta1/types/gcs.py b/google/cloud/dialogflow_v2beta1/types/gcs.py index 6905e49cc..99cf2bad4 100644 --- a/google/cloud/dialogflow_v2beta1/types/gcs.py +++ b/google/cloud/dialogflow_v2beta1/types/gcs.py @@ -23,6 +23,7 @@ class GcsSources(proto.Message): r"""Google Cloud Storage locations for the inputs. + Attributes: uris (Sequence[str]): Required. Google Cloud Storage URIs for the @@ -37,6 +38,7 @@ class GcsSources(proto.Message): class GcsSource(proto.Message): r"""Google Cloud Storage location for single input. + Attributes: uri (str): Required. The Google Cloud Storage URIs for diff --git a/google/cloud/dialogflow_v2beta1/types/intent.py b/google/cloud/dialogflow_v2beta1/types/intent.py index 8d3245bd1..99714cb02 100644 --- a/google/cloud/dialogflow_v2beta1/types/intent.py +++ b/google/cloud/dialogflow_v2beta1/types/intent.py @@ -192,6 +192,7 @@ class WebhookState(proto.Enum): class TrainingPhrase(proto.Message): r"""Represents an example that the agent is trained on. + Attributes: name (str): Output only. The unique identifier of this @@ -238,6 +239,7 @@ class Type(proto.Enum): class Part(proto.Message): r"""Represents a part of a training phrase. + Attributes: text (str): Required. The text for this part. @@ -272,6 +274,7 @@ class Part(proto.Message): class Parameter(proto.Message): r"""Represents intent parameters. + Attributes: name (str): The unique identifier of this parameter. @@ -320,56 +323,104 @@ class Parameter(proto.Message): class Message(proto.Message): r"""Corresponds to the ``Response`` field in the Dialogflow console. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: text (google.cloud.dialogflow_v2beta1.types.Intent.Message.Text): Returns a text response. + + This field is a member of `oneof`_ ``message``. image (google.cloud.dialogflow_v2beta1.types.Intent.Message.Image): Displays an image. + + This field is a member of `oneof`_ ``message``. quick_replies (google.cloud.dialogflow_v2beta1.types.Intent.Message.QuickReplies): Displays quick replies. + + This field is a member of `oneof`_ ``message``. card (google.cloud.dialogflow_v2beta1.types.Intent.Message.Card): Displays a card. + + This field is a member of `oneof`_ ``message``. payload (google.protobuf.struct_pb2.Struct): A custom platform-specific response. + + This field is a member of `oneof`_ ``message``. simple_responses (google.cloud.dialogflow_v2beta1.types.Intent.Message.SimpleResponses): Returns a voice or text-only response for Actions on Google. + + This field is a member of `oneof`_ ``message``. basic_card (google.cloud.dialogflow_v2beta1.types.Intent.Message.BasicCard): Displays a basic card for Actions on Google. + + This field is a member of `oneof`_ ``message``. suggestions (google.cloud.dialogflow_v2beta1.types.Intent.Message.Suggestions): Displays suggestion chips for Actions on Google. + + This field is a member of `oneof`_ ``message``. link_out_suggestion (google.cloud.dialogflow_v2beta1.types.Intent.Message.LinkOutSuggestion): Displays a link out suggestion chip for Actions on Google. + + This field is a member of `oneof`_ ``message``. list_select (google.cloud.dialogflow_v2beta1.types.Intent.Message.ListSelect): Displays a list card for Actions on Google. + + This field is a member of `oneof`_ ``message``. carousel_select (google.cloud.dialogflow_v2beta1.types.Intent.Message.CarouselSelect): Displays a carousel card for Actions on Google. + + This field is a member of `oneof`_ ``message``. telephony_play_audio (google.cloud.dialogflow_v2beta1.types.Intent.Message.TelephonyPlayAudio): Plays audio from a file in Telephony Gateway. + + This field is a member of `oneof`_ ``message``. telephony_synthesize_speech (google.cloud.dialogflow_v2beta1.types.Intent.Message.TelephonySynthesizeSpeech): Synthesizes speech in Telephony Gateway. + + This field is a member of `oneof`_ ``message``. telephony_transfer_call (google.cloud.dialogflow_v2beta1.types.Intent.Message.TelephonyTransferCall): Transfers the call in Telephony Gateway. + + This field is a member of `oneof`_ ``message``. rbm_text (google.cloud.dialogflow_v2beta1.types.Intent.Message.RbmText): Rich Business Messaging (RBM) text response. RBM allows businesses to send enriched and branded versions of SMS. See https://jibe.google.com/business-messaging. + + This field is a member of `oneof`_ ``message``. rbm_standalone_rich_card (google.cloud.dialogflow_v2beta1.types.Intent.Message.RbmStandaloneCard): Standalone Rich Business Messaging (RBM) rich card response. + + This field is a member of `oneof`_ ``message``. rbm_carousel_rich_card (google.cloud.dialogflow_v2beta1.types.Intent.Message.RbmCarouselCard): Rich Business Messaging (RBM) carousel rich card response. + + This field is a member of `oneof`_ ``message``. browse_carousel_card (google.cloud.dialogflow_v2beta1.types.Intent.Message.BrowseCarouselCard): Browse carousel card for Actions on Google. + + This field is a member of `oneof`_ ``message``. table_card (google.cloud.dialogflow_v2beta1.types.Intent.Message.TableCard): Table card for Actions on Google. + + This field is a member of `oneof`_ ``message``. media_content (google.cloud.dialogflow_v2beta1.types.Intent.Message.MediaContent): The media content card for Actions on Google. + + This field is a member of `oneof`_ ``message``. platform (google.cloud.dialogflow_v2beta1.types.Intent.Message.Platform): Optional. The platform that this message is intended for. @@ -393,6 +444,7 @@ class Platform(proto.Enum): class Text(proto.Message): r"""The text response message. + Attributes: text (Sequence[str]): Optional. The collection of the agent's @@ -403,6 +455,7 @@ class Text(proto.Message): class Image(proto.Message): r"""The image response message. + Attributes: image_uri (str): Optional. The public URI to an image file. @@ -417,6 +470,7 @@ class Image(proto.Message): class QuickReplies(proto.Message): r"""The quick replies response message. + Attributes: title (str): Optional. The title of the collection of @@ -430,6 +484,7 @@ class QuickReplies(proto.Message): class Card(proto.Message): r"""The card response message. + Attributes: title (str): Optional. The title of the card. @@ -444,6 +499,7 @@ class Card(proto.Message): class Button(proto.Message): r"""Optional. Contains information about a button. + Attributes: text (str): Optional. The text to show on the button. @@ -464,6 +520,7 @@ class Button(proto.Message): class SimpleResponse(proto.Message): r"""The simple response message containing speech or text. + Attributes: text_to_speech (str): One of text_to_speech or ssml must be provided. The plain @@ -497,6 +554,7 @@ class SimpleResponses(proto.Message): class BasicCard(proto.Message): r"""The basic card message. Useful for displaying information. + Attributes: title (str): Optional. The title of the card. @@ -513,6 +571,7 @@ class BasicCard(proto.Message): class Button(proto.Message): r"""The button object that appears at the bottom of a card. + Attributes: title (str): Required. The title of the button. @@ -523,6 +582,7 @@ class Button(proto.Message): class OpenUriAction(proto.Message): r"""Opens the given URI. + Attributes: uri (str): Required. The HTTP or HTTPS scheme URI. @@ -561,6 +621,7 @@ class Suggestion(proto.Message): class Suggestions(proto.Message): r"""The collection of suggestions. + Attributes: suggestions (Sequence[google.cloud.dialogflow_v2beta1.types.Intent.Message.Suggestion]): Required. The list of suggested replies. @@ -588,6 +649,7 @@ class LinkOutSuggestion(proto.Message): class ListSelect(proto.Message): r"""The card for presenting a list of options to select from. + Attributes: title (str): Optional. The overall title of the list. @@ -599,6 +661,7 @@ class ListSelect(proto.Message): class Item(proto.Message): r"""An item in the list. + Attributes: info (google.cloud.dialogflow_v2beta1.types.Intent.Message.SelectItemInfo): Required. Additional information about this @@ -628,6 +691,7 @@ class Item(proto.Message): class CarouselSelect(proto.Message): r"""The card for presenting a carousel of options to select from. + Attributes: items (Sequence[google.cloud.dialogflow_v2beta1.types.Intent.Message.CarouselSelect.Item]): Required. Carousel items. @@ -635,6 +699,7 @@ class CarouselSelect(proto.Message): class Item(proto.Message): r"""An item in the carousel. + Attributes: info (google.cloud.dialogflow_v2beta1.types.Intent.Message.SelectItemInfo): Required. Additional info about the option @@ -678,6 +743,7 @@ class SelectItemInfo(proto.Message): class TelephonyPlayAudio(proto.Message): r"""Plays audio from a file in Telephony Gateway. + Attributes: audio_uri (str): Required. URI to a Google Cloud Storage object containing @@ -708,12 +774,23 @@ class TelephonySynthesizeSpeech(proto.Message): at request-level or can come from the agent-level synthesizer config. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: text (str): The raw text to be synthesized. + + This field is a member of `oneof`_ ``source``. ssml (str): The SSML to be synthesized. For more information, see `SSML `__. + + This field is a member of `oneof`_ ``source``. """ text = proto.Field(proto.STRING, number=1, oneof="source",) @@ -721,6 +798,7 @@ class TelephonySynthesizeSpeech(proto.Message): class TelephonyTransferCall(proto.Message): r"""Transfers the call in Telephony Gateway. + Attributes: phone_number (str): Required. The phone number to transfer the call to in `E.164 @@ -734,6 +812,7 @@ class TelephonyTransferCall(proto.Message): class RbmText(proto.Message): r"""Rich Business Messaging (RBM) text response with suggestions. + Attributes: text (str): Required. Text sent and displayed to the @@ -833,6 +912,7 @@ class ThumbnailImageAlignment(proto.Enum): class RbmCardContent(proto.Message): r"""Rich Business Messaging (RBM) Card content + Attributes: title (str): Optional. Title of the card (at most 200 @@ -928,13 +1008,24 @@ class RbmSuggestion(proto.Message): user to easily select/click a predefined response or perform an action (like opening a web uri). + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: reply (google.cloud.dialogflow_v2beta1.types.Intent.Message.RbmSuggestedReply): Predefined replies for user to select instead of typing + + This field is a member of `oneof`_ ``suggestion``. action (google.cloud.dialogflow_v2beta1.types.Intent.Message.RbmSuggestedAction): Predefined client side actions that user can choose + + This field is a member of `oneof`_ ``suggestion``. """ reply = proto.Field( @@ -972,6 +1063,13 @@ class RbmSuggestedAction(proto.Message): r"""Rich Business Messaging (RBM) suggested client-side action that the user can choose from the card. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: text (str): Text to display alongside the action. @@ -984,12 +1082,18 @@ class RbmSuggestedAction(proto.Message): dial (google.cloud.dialogflow_v2beta1.types.Intent.Message.RbmSuggestedAction.RbmSuggestedActionDial): Suggested client side action: Dial a phone number + + This field is a member of `oneof`_ ``action``. open_url (google.cloud.dialogflow_v2beta1.types.Intent.Message.RbmSuggestedAction.RbmSuggestedActionOpenUri): Suggested client side action: Open a URI on device + + This field is a member of `oneof`_ ``action``. share_location (google.cloud.dialogflow_v2beta1.types.Intent.Message.RbmSuggestedAction.RbmSuggestedActionShareLocation): Suggested client side action: Share user location + + This field is a member of `oneof`_ ``action``. """ class RbmSuggestedActionDial(proto.Message): @@ -1023,7 +1127,8 @@ class RbmSuggestedActionOpenUri(proto.Message): class RbmSuggestedActionShareLocation(proto.Message): r"""Opens the device's location chooser so the user can pick a location to send back to the agent. - """ + + """ text = proto.Field(proto.STRING, number=1,) postback_data = proto.Field(proto.STRING, number=2,) @@ -1048,6 +1153,7 @@ class RbmSuggestedActionShareLocation(proto.Message): class MediaContent(proto.Message): r"""The media content card for Actions on Google. + Attributes: media_type (google.cloud.dialogflow_v2beta1.types.Intent.Message.MediaContent.ResponseMediaType): Optional. What type of media is the content @@ -1063,6 +1169,14 @@ class ResponseMediaType(proto.Enum): class ResponseMediaObject(proto.Message): r"""Response media object for media content card. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: name (str): Required. Name of media card. @@ -1071,9 +1185,13 @@ class ResponseMediaObject(proto.Message): large_image (google.cloud.dialogflow_v2beta1.types.Intent.Message.Image): Optional. Image to display above media content. + + This field is a member of `oneof`_ ``image``. icon (google.cloud.dialogflow_v2beta1.types.Intent.Message.Image): Optional. Icon to display above media content. + + This field is a member of `oneof`_ ``image``. content_url (str): Required. Url where the media is stored. """ @@ -1133,6 +1251,7 @@ class ImageDisplayOptions(proto.Enum): class BrowseCarouselCardItem(proto.Message): r"""Browsing carousel tile + Attributes: open_uri_action (google.cloud.dialogflow_v2beta1.types.Intent.Message.BrowseCarouselCard.BrowseCarouselCardItem.OpenUrlAction): Required. Action to present to the user. @@ -1152,6 +1271,7 @@ class BrowseCarouselCardItem(proto.Message): class OpenUrlAction(proto.Message): r"""Actions on Google action to open a given url. + Attributes: url (str): Required. URL @@ -1199,6 +1319,7 @@ class UrlTypeHint(proto.Enum): class TableCard(proto.Message): r"""Table card for Actions on Google. + Attributes: title (str): Required. Title of the card. @@ -1395,6 +1516,7 @@ class TableCardCell(proto.Message): class FollowupIntentInfo(proto.Message): r"""Represents a single followup intent in the chain. + Attributes: followup_intent_name (str): The unique identifier of the followup intent. Format: @@ -1610,6 +1732,13 @@ class BatchUpdateIntentsRequest(proto.Message): r"""The request message for [Intents.BatchUpdateIntents][google.cloud.dialogflow.v2beta1.Intents.BatchUpdateIntents]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: parent (str): Required. The name of the agent to update or create intents @@ -1623,9 +1752,13 @@ class BatchUpdateIntentsRequest(proto.Message): format can either be a serialized proto (of IntentBatch type) or JSON object. Note: The URI must start with "gs://". + + This field is a member of `oneof`_ ``intent_batch``. intent_batch_inline (google.cloud.dialogflow_v2beta1.types.IntentBatch): The collection of intents to update or create. + + This field is a member of `oneof`_ ``intent_batch``. language_code (str): Optional. The language used to access language-specific data. If not specified, the agent's default language is @@ -1686,6 +1819,7 @@ class BatchDeleteIntentsRequest(proto.Message): class IntentBatch(proto.Message): r"""This message is a wrapper around a collection of intents. + Attributes: intents (Sequence[google.cloud.dialogflow_v2beta1.types.Intent]): A collection of intents. diff --git a/google/cloud/dialogflow_v2beta1/types/participant.py b/google/cloud/dialogflow_v2beta1/types/participant.py index 0f3e087b5..b2185dfb9 100644 --- a/google/cloud/dialogflow_v2beta1/types/participant.py +++ b/google/cloud/dialogflow_v2beta1/types/participant.py @@ -127,6 +127,7 @@ class Role(proto.Enum): class Message(proto.Message): r"""Represents a message posted into a conversation. + Attributes: name (str): Optional. The unique identifier of the message. Format: @@ -281,11 +282,21 @@ class OutputAudio(proto.Message): class AutomatedAgentReply(proto.Message): r"""Represents a response from an automated agent. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: detect_intent_response (google.cloud.dialogflow_v2beta1.types.DetectIntentResponse): Response of the Dialogflow [Sessions.DetectIntent][google.cloud.dialogflow.v2beta1.Sessions.DetectIntent] call. + + This field is a member of `oneof`_ ``response``. response_messages (Sequence[google.cloud.dialogflow_v2beta1.types.ResponseMessage]): Response messages from the automated agent. intent (str): @@ -294,9 +305,13 @@ class AutomatedAgentReply(proto.Message): ``projects//locations/ /agent/intents/``. For a V3 query, the value format is ``projects//locations/ /agents//intents/``. + + This field is a member of `oneof`_ ``match``. event (str): Event name if an event is triggered for the query. + + This field is a member of `oneof`_ ``match``. match_confidence (float): The confidence of the match. Values range from 0.0 (completely uncertain) to 1.0 @@ -374,6 +389,13 @@ class AnalyzeContentRequest(proto.Message): r"""The request message for [Participants.AnalyzeContent][google.cloud.dialogflow.v2beta1.Participants.AnalyzeContent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: participant (str): Required. The name of the participant this text comes from. @@ -381,8 +403,12 @@ class AnalyzeContentRequest(proto.Message): ``projects//locations//conversations//participants/``. text_input (google.cloud.dialogflow_v2beta1.types.TextInput): The natural language text to be processed. + + This field is a member of `oneof`_ ``input``. event_input (google.cloud.dialogflow_v2beta1.types.EventInput): An input event to send to Dialogflow. + + This field is a member of `oneof`_ ``input``. reply_audio_config (google.cloud.dialogflow_v2beta1.types.OutputAudioConfig): Speech synthesis configuration. The speech synthesis settings for a virtual @@ -548,6 +574,7 @@ class AnnotatedMessagePart(proto.Message): class MessageAnnotation(proto.Message): r"""Represents the result of annotation for the message. + Attributes: parts (Sequence[google.cloud.dialogflow_v2beta1.types.AnnotatedMessagePart]): Optional. The collection of annotated message parts ordered @@ -567,6 +594,7 @@ class MessageAnnotation(proto.Message): class ArticleAnswer(proto.Message): r"""Represents article answer. + Attributes: title (str): The article title. @@ -592,6 +620,7 @@ class ArticleAnswer(proto.Message): class FaqAnswer(proto.Message): r"""Represents answer from "frequently asked questions". + Attributes: answer (str): The piece of text from the ``source`` knowledge base @@ -626,6 +655,7 @@ class FaqAnswer(proto.Message): class SmartReplyAnswer(proto.Message): r"""Represents a smart reply answer. + Attributes: reply (str): The content of the reply. @@ -655,16 +685,31 @@ class SuggestionResult(proto.Message): as well as [HumanAgentAssistantEvent][google.cloud.dialogflow.v2beta1.HumanAgentAssistantEvent]. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: error (google.rpc.status_pb2.Status): Error status if the request failed. + + This field is a member of `oneof`_ ``suggestion_response``. suggest_articles_response (google.cloud.dialogflow_v2beta1.types.SuggestArticlesResponse): SuggestArticlesResponse if request is for ARTICLE_SUGGESTION. + + This field is a member of `oneof`_ ``suggestion_response``. suggest_faq_answers_response (google.cloud.dialogflow_v2beta1.types.SuggestFaqAnswersResponse): SuggestFaqAnswersResponse if request is for FAQ_ANSWER. + + This field is a member of `oneof`_ ``suggestion_response``. suggest_smart_replies_response (google.cloud.dialogflow_v2beta1.types.SuggestSmartRepliesResponse): SuggestSmartRepliesResponse if request is for SMART_REPLY. + + This field is a member of `oneof`_ ``suggestion_response``. """ error = proto.Field( @@ -874,6 +919,7 @@ class SuggestSmartRepliesResponse(proto.Message): class Suggestion(proto.Message): r"""Represents a suggestion for a human agent. + Attributes: name (str): Output only. The name of this suggestion. Format: @@ -897,6 +943,7 @@ class Suggestion(proto.Message): class Article(proto.Message): r"""Represents suggested article. + Attributes: title (str): Output only. The article title. @@ -1079,25 +1126,44 @@ class CompileSuggestionResponse(proto.Message): class ResponseMessage(proto.Message): r"""Response messages from an automated agent. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: text (google.cloud.dialogflow_v2beta1.types.ResponseMessage.Text): Returns a text response. + + This field is a member of `oneof`_ ``message``. payload (google.protobuf.struct_pb2.Struct): Returns a response containing a custom, platform-specific payload. + + This field is a member of `oneof`_ ``message``. live_agent_handoff (google.cloud.dialogflow_v2beta1.types.ResponseMessage.LiveAgentHandoff): Hands off conversation to a live agent. + + This field is a member of `oneof`_ ``message``. end_interaction (google.cloud.dialogflow_v2beta1.types.ResponseMessage.EndInteraction): A signal that indicates the interaction with the Dialogflow agent has ended. + + This field is a member of `oneof`_ ``message``. telephony_transfer_call (google.cloud.dialogflow_v2beta1.types.ResponseMessage.TelephonyTransferCall): A signal that the client should transfer the phone call connected to this agent to a third- party endpoint. + + This field is a member of `oneof`_ ``message``. """ class Text(proto.Message): r"""The text response message. + Attributes: text (Sequence[str]): A collection of text responses. @@ -1131,18 +1197,30 @@ class LiveAgentHandoff(proto.Message): class EndInteraction(proto.Message): r"""Indicates that interaction with the Dialogflow agent has ended. - """ + + """ class TelephonyTransferCall(proto.Message): r"""Represents the signal that telles the client to transfer the phone call connected to the agent to a third-party endpoint. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: phone_number (str): Transfer the call to a phone number in `E.164 format `__. + + This field is a member of `oneof`_ ``endpoint``. sip_uri (str): Transfer the call to a SIP endpoint. + + This field is a member of `oneof`_ ``endpoint``. """ phone_number = proto.Field(proto.STRING, number=1, oneof="endpoint",) diff --git a/google/cloud/dialogflow_v2beta1/types/session.py b/google/cloud/dialogflow_v2beta1/types/session.py index e84afb1e0..c857cb966 100644 --- a/google/cloud/dialogflow_v2beta1/types/session.py +++ b/google/cloud/dialogflow_v2beta1/types/session.py @@ -50,6 +50,7 @@ class DetectIntentRequest(proto.Message): r"""The request to detect user's intent. + Attributes: session (str): Required. The name of the session this query is sent to. @@ -123,6 +124,7 @@ class DetectIntentRequest(proto.Message): class DetectIntentResponse(proto.Message): r"""The message returned from the DetectIntent method. + Attributes: response_id (str): The unique identifier of the response. It can @@ -175,6 +177,7 @@ class DetectIntentResponse(proto.Message): class QueryParameters(proto.Message): r"""Represents the parameters of the conversational query. + Attributes: time_zone (str): The time zone of this conversational query from the `time @@ -260,17 +263,32 @@ class QueryInput(proto.Message): 3. An event that specifies which intent to trigger. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: audio_config (google.cloud.dialogflow_v2beta1.types.InputAudioConfig): Instructs the speech recognizer how to process the speech audio. + + This field is a member of `oneof`_ ``input``. text (google.cloud.dialogflow_v2beta1.types.TextInput): The natural language text to be processed. + + This field is a member of `oneof`_ ``input``. event (google.cloud.dialogflow_v2beta1.types.EventInput): The event to be processed. + + This field is a member of `oneof`_ ``input``. dtmf (google.cloud.dialogflow_v2beta1.types.TelephonyDtmfEvents): The DTMF digits used to invoke intent and fill in parameter value. + + This field is a member of `oneof`_ ``input``. """ audio_config = proto.Field( @@ -440,6 +458,7 @@ class QueryResult(proto.Message): class KnowledgeAnswers(proto.Message): r"""Represents the result of querying a Knowledge base. + Attributes: answers (Sequence[google.cloud.dialogflow_v2beta1.types.KnowledgeAnswers.Answer]): A list of answers from Knowledge Connector. @@ -447,6 +466,7 @@ class KnowledgeAnswers(proto.Message): class Answer(proto.Message): r"""An answer from Knowledge Connector. + Attributes: source (str): Indicates which Knowledge Document this answer was extracted @@ -627,11 +647,11 @@ class StreamingDetectIntentResponse(proto.Message): Multiple response messages can be returned in order: - 1. If the input was set to streaming audio, the first one or more - messages contain ``recognition_result``. Each - ``recognition_result`` represents a more complete transcript of - what the user said. The last ``recognition_result`` has - ``is_final`` set to ``true``. + 1. If the ``StreamingDetectIntentRequest.input_audio`` field was + set, the ``recognition_result`` field is populated for one or + more messages. See the + [StreamingRecognitionResult][google.cloud.dialogflow.v2beta1.StreamingRecognitionResult] + message for details about the result message sequence. 2. The next message contains ``response_id``, ``query_result``, ``alternative_query_results`` and optionally ``webhook_status`` @@ -701,33 +721,42 @@ class StreamingRecognitionResult(proto.Message): the audio that is currently being processed or an indication that this is the end of the single requested utterance. - Example: - - 1. transcript: "tube" - - 2. transcript: "to be a" - - 3. transcript: "to be" - - 4. transcript: "to be or not to be" is_final: true - - 5. transcript: " that's" - - 6. transcript: " that is" - - 7. message_type: ``END_OF_SINGLE_UTTERANCE`` - - 8. transcript: " that is the question" is_final: true - - Only two of the responses contain final results (#4 and #8 indicated - by ``is_final: true``). Concatenating these generates the full - transcript: "to be or not to be that is the question". - - In each response we populate: - - - for ``TRANSCRIPT``: ``transcript`` and possibly ``is_final``. - - - for ``END_OF_SINGLE_UTTERANCE``: only ``message_type``. + While end-user audio is being processed, Dialogflow sends a series + of results. Each result may contain a ``transcript`` value. A + transcript represents a portion of the utterance. While the + recognizer is processing audio, transcript values may be interim + values or finalized values. Once a transcript is finalized, the + ``is_final`` value is set to true and processing continues for the + next transcript. + + If + ``StreamingDetectIntentRequest.query_input.audio_config.single_utterance`` + was true, and the recognizer has completed processing audio, the + ``message_type`` value is set to \`END_OF_SINGLE_UTTERANCE and the + following (last) result contains the last finalized transcript. + + The complete end-user utterance is determined by concatenating the + finalized transcript values received for the series of results. + + In the following example, single utterance is enabled. In the case + where single utterance is not enabled, result 7 would not occur. + + :: + + Num | transcript | message_type | is_final + --- | ----------------------- | ----------------------- | -------- + 1 | "tube" | TRANSCRIPT | false + 2 | "to be a" | TRANSCRIPT | false + 3 | "to be" | TRANSCRIPT | false + 4 | "to be or not to be" | TRANSCRIPT | true + 5 | "that's" | TRANSCRIPT | false + 6 | "that is | TRANSCRIPT | false + 7 | unset | END_OF_SINGLE_UTTERANCE | unset + 8 | " that is the question" | TRANSCRIPT | true + + Concatenating the finalized transcripts with ``is_final`` set to + true, the complete utterance becomes "to be or not to be that is the + question". Attributes: message_type (google.cloud.dialogflow_v2beta1.types.StreamingRecognitionResult.MessageType): @@ -806,6 +835,7 @@ class MessageType(proto.Enum): class TextInput(proto.Message): r"""Represents the natural language text to be processed. + Attributes: text (str): Required. The UTF-8 encoded natural language @@ -870,6 +900,7 @@ class EventInput(proto.Message): class SentimentAnalysisRequestConfig(proto.Message): r"""Configures the types of sentiment analysis to perform. + Attributes: analyze_query_text_sentiment (bool): Instructs the service to perform sentiment analysis on diff --git a/google/cloud/dialogflow_v2beta1/types/validation_result.py b/google/cloud/dialogflow_v2beta1/types/validation_result.py index 292857fc7..05c1cd38e 100644 --- a/google/cloud/dialogflow_v2beta1/types/validation_result.py +++ b/google/cloud/dialogflow_v2beta1/types/validation_result.py @@ -24,6 +24,7 @@ class ValidationError(proto.Message): r"""Represents a single validation error. + Attributes: severity (google.cloud.dialogflow_v2beta1.types.ValidationError.Severity): The severity of the error. @@ -66,6 +67,7 @@ class Severity(proto.Enum): class ValidationResult(proto.Message): r"""Represents the output of agent validation. + Attributes: validation_errors (Sequence[google.cloud.dialogflow_v2beta1.types.ValidationError]): Contains all validation errors. diff --git a/google/cloud/dialogflow_v2beta1/types/webhook.py b/google/cloud/dialogflow_v2beta1/types/webhook.py index cc7911ca4..b494938f2 100644 --- a/google/cloud/dialogflow_v2beta1/types/webhook.py +++ b/google/cloud/dialogflow_v2beta1/types/webhook.py @@ -30,6 +30,7 @@ class WebhookRequest(proto.Message): r"""The request message for a webhook call. + Attributes: session (str): The unique identifier of detectIntent request session. Can diff --git a/noxfile.py b/noxfile.py index 4e2427c8b..a16c00e09 100644 --- a/noxfile.py +++ b/noxfile.py @@ -29,7 +29,7 @@ DEFAULT_PYTHON_VERSION = "3.8" SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"] -UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10"] CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() @@ -101,7 +101,7 @@ def default(session): "py.test", "--quiet", f"--junitxml=unit_{session.python}_sponge_log.xml", - "--cov=google/cloud", + "--cov=google", "--cov=tests/unit", "--cov-append", "--cov-config=.coveragerc", diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py index 1fd8956fb..93a9122cc 100644 --- a/samples/snippets/noxfile.py +++ b/samples/snippets/noxfile.py @@ -87,7 +87,7 @@ def get_pytest_env_vars() -> Dict[str, str]: # DO NOT EDIT - automatically generated. # All versions used to test samples. -ALL_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +ALL_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10"] # Any default versions that should be ignored. IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt index 580ea880d..97568eeb3 100644 --- a/samples/snippets/requirements.txt +++ b/samples/snippets/requirements.txt @@ -1,2 +1,2 @@ -google-cloud-dialogflow==2.9.0 -Flask==2.0.1 +google-cloud-dialogflow==2.9.1 +Flask==2.0.2 diff --git a/samples/snippets/webhook.py b/samples/snippets/webhook.py index 2a3b00be3..0299170ca 100644 --- a/samples/snippets/webhook.py +++ b/samples/snippets/webhook.py @@ -14,6 +14,9 @@ # returns fullfillment response for dialogflow detect_intent call # [START dialogflow_webhook] + +# TODO: change the default Entry Point text to handleWebhook + def handleWebhook(request): req = request.get_json() diff --git a/scripts/fixup_dialogflow_v2_keywords.py b/scripts/fixup_dialogflow_v2_keywords.py index 499bd93a7..6af3adf69 100644 --- a/scripts/fixup_dialogflow_v2_keywords.py +++ b/scripts/fixup_dialogflow_v2_keywords.py @@ -39,7 +39,7 @@ def partition( class dialogflowCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { - 'analyze_content': ('participant', 'text_input', 'event_input', 'reply_audio_config', 'query_params', 'request_id', ), + 'analyze_content': ('participant', 'text_input', 'event_input', 'reply_audio_config', 'query_params', 'assist_query_params', 'request_id', ), 'batch_create_entities': ('parent', 'entities', 'language_code', ), 'batch_delete_entities': ('parent', 'entity_values', 'language_code', ), 'batch_delete_entity_types': ('parent', 'entity_type_names', ), @@ -106,8 +106,8 @@ class dialogflowCallTransformer(cst.CSTTransformer): 'search_agents': ('parent', 'page_size', 'page_token', ), 'set_agent': ('agent', 'update_mask', ), 'streaming_detect_intent': ('session', 'query_input', 'query_params', 'single_utterance', 'output_audio_config', 'output_audio_config_mask', 'input_audio', ), - 'suggest_articles': ('parent', 'latest_message', 'context_size', ), - 'suggest_faq_answers': ('parent', 'latest_message', 'context_size', ), + 'suggest_articles': ('parent', 'latest_message', 'context_size', 'assist_query_params', ), + 'suggest_faq_answers': ('parent', 'latest_message', 'context_size', 'assist_query_params', ), 'train_agent': ('parent', ), 'update_answer_record': ('answer_record', 'update_mask', ), 'update_context': ('context', 'update_mask', ), diff --git a/setup.py b/setup.py index c70613aa6..5666b53c0 100644 --- a/setup.py +++ b/setup.py @@ -19,15 +19,14 @@ name = "dialogflow" description = "Client library for the Dialogflow API" -version = "2.9.1" +version = "2.10.0" release_status = "Development Status :: 5 - Production/Stable" dependencies = [ # NOTE: Maintainers, please do not require google-api-core>=2.x.x # Until this issue is closed # https://github.com/googleapis/google-cloud-python/issues/10566 - "google-api-core[grpc] >= 1.26.0, <3.0.0dev", + "google-api-core[grpc] >= 1.28.0, <3.0.0dev", "proto-plus >= 1.10.0", - "packaging >= 14.3", ] package_root = os.path.abspath(os.path.dirname(__file__)) @@ -56,6 +55,8 @@ "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Programming Language :: Python :: Implementation :: CPython", ], platforms="Posix; MacOS X; Windows", diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt index fcce18a22..30a8ed74a 100644 --- a/testing/constraints-3.6.txt +++ b/testing/constraints-3.6.txt @@ -2,9 +2,7 @@ # are correct in setup.py # List all library dependencies and extras in this file. # Pin the version to the lower bound. - # e.g., if setup.py has "google-cloud-foo >= 1.14.0, < 2.0.0dev", # Then this file should have google-cloud-foo==1.14.0 -google-api-core==1.26.0 +google-api-core==1.28.0 proto-plus==1.10.0 -packaging==14.3 diff --git a/tests/unit/gapic/dialogflow_v2/test_agents.py b/tests/unit/gapic/dialogflow_v2/test_agents.py index fa1c841dd..4c262a183 100644 --- a/tests/unit/gapic/dialogflow_v2/test_agents.py +++ b/tests/unit/gapic/dialogflow_v2/test_agents.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -32,15 +31,13 @@ from google.api_core import grpc_helpers_async from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.agents import AgentsAsyncClient from google.cloud.dialogflow_v2.services.agents import AgentsClient from google.cloud.dialogflow_v2.services.agents import pagers from google.cloud.dialogflow_v2.services.agents import transports -from google.cloud.dialogflow_v2.services.agents.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import agent from google.cloud.dialogflow_v2.types import agent as gcd_agent from google.cloud.dialogflow_v2.types import validation_result @@ -51,20 +48,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -199,7 +182,7 @@ def test_agents_client_client_options(client_class, transport_class, transport_n options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -216,7 +199,7 @@ def test_agents_client_client_options(client_class, transport_class, transport_n with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -233,7 +216,7 @@ def test_agents_client_client_options(client_class, transport_class, transport_n with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +245,7 @@ def test_agents_client_client_options(client_class, transport_class, transport_n options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -317,7 +300,7 @@ def test_agents_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -359,7 +342,7 @@ def test_agents_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -381,7 +364,7 @@ def test_agents_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -408,7 +391,7 @@ def test_agents_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -435,7 +418,7 @@ def test_agents_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -661,7 +644,9 @@ def test_get_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_get_agent_flattened_error(): @@ -693,7 +678,9 @@ async def test_get_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -907,7 +894,9 @@ def test_set_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].agent == gcd_agent.Agent(parent="parent_value") + arg = args[0].agent + mock_val = gcd_agent.Agent(parent="parent_value") + assert arg == mock_val def test_set_agent_flattened_error(): @@ -939,7 +928,9 @@ async def test_set_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].agent == gcd_agent.Agent(parent="parent_value") + arg = args[0].agent + mock_val = gcd_agent.Agent(parent="parent_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1093,7 +1084,9 @@ def test_delete_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_delete_agent_flattened_error(): @@ -1125,7 +1118,9 @@ async def test_delete_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1287,7 +1282,9 @@ def test_search_agents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_search_agents_flattened_error(): @@ -1321,7 +1318,9 @@ async def test_search_agents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1585,7 +1584,9 @@ def test_train_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_train_agent_flattened_error(): @@ -1619,7 +1620,9 @@ async def test_train_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1777,7 +1780,9 @@ def test_export_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_export_agent_flattened_error(): @@ -1811,7 +1816,9 @@ async def test_export_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2330,13 +2337,15 @@ def test_agents_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + # Additionally, the LRO client (a property) should # also raise NotImplementedError with pytest.raises(NotImplementedError): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_agents_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2360,29 +2369,6 @@ def test_agents_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_agents_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.agents.transports.AgentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.AgentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_agents_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2394,7 +2380,6 @@ def test_agents_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_agents_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2410,26 +2395,10 @@ def test_agents_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_agents_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - AgentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.AgentsGrpcTransport, transports.AgentsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_agents_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2446,26 +2415,6 @@ def test_agents_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.AgentsGrpcTransport, transports.AgentsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_agents_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2841,3 +2790,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = AgentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = AgentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = AgentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_answer_records.py b/tests/unit/gapic/dialogflow_v2/test_answer_records.py index 18afa50dd..1f9a031f2 100644 --- a/tests/unit/gapic/dialogflow_v2/test_answer_records.py +++ b/tests/unit/gapic/dialogflow_v2/test_answer_records.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,15 +28,13 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.answer_records import AnswerRecordsAsyncClient from google.cloud.dialogflow_v2.services.answer_records import AnswerRecordsClient from google.cloud.dialogflow_v2.services.answer_records import pagers from google.cloud.dialogflow_v2.services.answer_records import transports -from google.cloud.dialogflow_v2.services.answer_records.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import answer_record from google.cloud.dialogflow_v2.types import answer_record as gcd_answer_record from google.cloud.dialogflow_v2.types import participant @@ -47,20 +44,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -217,7 +200,7 @@ def test_answer_records_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -234,7 +217,7 @@ def test_answer_records_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -251,7 +234,7 @@ def test_answer_records_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -280,7 +263,7 @@ def test_answer_records_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -339,7 +322,7 @@ def test_answer_records_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -381,7 +364,7 @@ def test_answer_records_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -403,7 +386,7 @@ def test_answer_records_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -434,7 +417,7 @@ def test_answer_records_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -465,7 +448,7 @@ def test_answer_records_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -663,7 +646,9 @@ def test_list_answer_records_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_answer_records_flattened_error(): @@ -701,7 +686,9 @@ async def test_list_answer_records_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1060,10 +1047,12 @@ def test_update_answer_record_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].answer_record == gcd_answer_record.AnswerRecord( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].answer_record + mock_val = gcd_answer_record.AnswerRecord(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_answer_record_flattened_error(): @@ -1106,10 +1095,12 @@ async def test_update_answer_record_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].answer_record == gcd_answer_record.AnswerRecord( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].answer_record + mock_val = gcd_answer_record.AnswerRecord(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1232,8 +1223,10 @@ def test_answer_records_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_answer_records_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1257,29 +1250,6 @@ def test_answer_records_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_answer_records_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.answer_records.transports.AnswerRecordsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.AnswerRecordsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_answer_records_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1291,7 +1261,6 @@ def test_answer_records_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_answer_records_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1307,21 +1276,6 @@ def test_answer_records_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_answer_records_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - AnswerRecordsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -1329,7 +1283,6 @@ def test_answer_records_auth_adc_old_google_auth(): transports.AnswerRecordsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_answer_records_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1346,29 +1299,6 @@ def test_answer_records_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.AnswerRecordsGrpcTransport, - transports.AnswerRecordsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_answer_records_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -1731,3 +1661,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = AnswerRecordsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = AnswerRecordsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = AnswerRecordsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_contexts.py b/tests/unit/gapic/dialogflow_v2/test_contexts.py index ce304f252..f2a087a9c 100644 --- a/tests/unit/gapic/dialogflow_v2/test_contexts.py +++ b/tests/unit/gapic/dialogflow_v2/test_contexts.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,15 +28,13 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.contexts import ContextsAsyncClient from google.cloud.dialogflow_v2.services.contexts import ContextsClient from google.cloud.dialogflow_v2.services.contexts import pagers from google.cloud.dialogflow_v2.services.contexts import transports -from google.cloud.dialogflow_v2.services.contexts.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import context from google.cloud.dialogflow_v2.types import context as gcd_context from google.oauth2 import service_account @@ -46,20 +43,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -199,7 +182,7 @@ def test_contexts_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -216,7 +199,7 @@ def test_contexts_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -233,7 +216,7 @@ def test_contexts_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +245,7 @@ def test_contexts_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -319,7 +302,7 @@ def test_contexts_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -361,7 +344,7 @@ def test_contexts_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -383,7 +366,7 @@ def test_contexts_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -410,7 +393,7 @@ def test_contexts_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -437,7 +420,7 @@ def test_contexts_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -617,7 +600,9 @@ def test_list_contexts_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_contexts_flattened_error(): @@ -651,7 +636,9 @@ async def test_list_contexts_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -933,7 +920,9 @@ def test_get_context_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_context_flattened_error(): @@ -965,7 +954,9 @@ async def test_get_context_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1129,8 +1120,12 @@ def test_create_context_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].context == gcd_context.Context(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].context + mock_val = gcd_context.Context(name="name_value") + assert arg == mock_val def test_create_context_flattened_error(): @@ -1166,8 +1161,12 @@ async def test_create_context_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].context == gcd_context.Context(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].context + mock_val = gcd_context.Context(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1338,8 +1337,12 @@ def test_update_context_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].context == gcd_context.Context(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].context + mock_val = gcd_context.Context(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_context_flattened_error(): @@ -1376,8 +1379,12 @@ async def test_update_context_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].context == gcd_context.Context(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].context + mock_val = gcd_context.Context(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1535,7 +1542,9 @@ def test_delete_context_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_context_flattened_error(): @@ -1567,7 +1576,9 @@ async def test_delete_context_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1735,7 +1746,9 @@ def test_delete_all_contexts_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_delete_all_contexts_flattened_error(): @@ -1769,7 +1782,9 @@ async def test_delete_all_contexts_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1889,8 +1904,10 @@ def test_contexts_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_contexts_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1914,29 +1931,6 @@ def test_contexts_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_contexts_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.contexts.transports.ContextsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.ContextsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_contexts_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1948,7 +1942,6 @@ def test_contexts_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_contexts_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1964,26 +1957,10 @@ def test_contexts_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_contexts_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - ContextsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.ContextsGrpcTransport, transports.ContextsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_contexts_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2000,26 +1977,6 @@ def test_contexts_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.ContextsGrpcTransport, transports.ContextsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_contexts_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2375,3 +2332,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = ContextsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = ContextsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = ContextsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_conversation_profiles.py b/tests/unit/gapic/dialogflow_v2/test_conversation_profiles.py index f44a0dcdc..a7f488276 100644 --- a/tests/unit/gapic/dialogflow_v2/test_conversation_profiles.py +++ b/tests/unit/gapic/dialogflow_v2/test_conversation_profiles.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.conversation_profiles import ( @@ -39,9 +39,6 @@ ) from google.cloud.dialogflow_v2.services.conversation_profiles import pagers from google.cloud.dialogflow_v2.services.conversation_profiles import transports -from google.cloud.dialogflow_v2.services.conversation_profiles.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import audio_config from google.cloud.dialogflow_v2.types import conversation_profile from google.cloud.dialogflow_v2.types import ( @@ -53,20 +50,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -228,7 +211,7 @@ def test_conversation_profiles_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -245,7 +228,7 @@ def test_conversation_profiles_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +245,7 @@ def test_conversation_profiles_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -291,7 +274,7 @@ def test_conversation_profiles_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -360,7 +343,7 @@ def test_conversation_profiles_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -402,7 +385,7 @@ def test_conversation_profiles_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -424,7 +407,7 @@ def test_conversation_profiles_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -459,7 +442,7 @@ def test_conversation_profiles_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -494,7 +477,7 @@ def test_conversation_profiles_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -698,7 +681,9 @@ def test_list_conversation_profiles_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_conversation_profiles_flattened_error(): @@ -739,7 +724,9 @@ async def test_list_conversation_profiles_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -960,6 +947,8 @@ def test_get_conversation_profile( name="name_value", display_name="display_name_value", language_code="language_code_value", + time_zone="time_zone_value", + security_settings="security_settings_value", ) response = client.get_conversation_profile(request) @@ -973,6 +962,8 @@ def test_get_conversation_profile( assert response.name == "name_value" assert response.display_name == "display_name_value" assert response.language_code == "language_code_value" + assert response.time_zone == "time_zone_value" + assert response.security_settings == "security_settings_value" def test_get_conversation_profile_from_dict(): @@ -1019,6 +1010,8 @@ async def test_get_conversation_profile_async( name="name_value", display_name="display_name_value", language_code="language_code_value", + time_zone="time_zone_value", + security_settings="security_settings_value", ) ) response = await client.get_conversation_profile(request) @@ -1033,6 +1026,8 @@ async def test_get_conversation_profile_async( assert response.name == "name_value" assert response.display_name == "display_name_value" assert response.language_code == "language_code_value" + assert response.time_zone == "time_zone_value" + assert response.security_settings == "security_settings_value" @pytest.mark.asyncio @@ -1118,7 +1113,9 @@ def test_get_conversation_profile_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_conversation_profile_flattened_error(): @@ -1158,7 +1155,9 @@ async def test_get_conversation_profile_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1196,6 +1195,8 @@ def test_create_conversation_profile( name="name_value", display_name="display_name_value", language_code="language_code_value", + time_zone="time_zone_value", + security_settings="security_settings_value", ) response = client.create_conversation_profile(request) @@ -1209,6 +1210,8 @@ def test_create_conversation_profile( assert response.name == "name_value" assert response.display_name == "display_name_value" assert response.language_code == "language_code_value" + assert response.time_zone == "time_zone_value" + assert response.security_settings == "security_settings_value" def test_create_conversation_profile_from_dict(): @@ -1255,6 +1258,8 @@ async def test_create_conversation_profile_async( name="name_value", display_name="display_name_value", language_code="language_code_value", + time_zone="time_zone_value", + security_settings="security_settings_value", ) ) response = await client.create_conversation_profile(request) @@ -1269,6 +1274,8 @@ async def test_create_conversation_profile_async( assert response.name == "name_value" assert response.display_name == "display_name_value" assert response.language_code == "language_code_value" + assert response.time_zone == "time_zone_value" + assert response.security_settings == "security_settings_value" @pytest.mark.asyncio @@ -1359,12 +1366,12 @@ def test_create_conversation_profile_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[ - 0 - ].conversation_profile == gcd_conversation_profile.ConversationProfile( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].conversation_profile + mock_val = gcd_conversation_profile.ConversationProfile(name="name_value") + assert arg == mock_val def test_create_conversation_profile_flattened_error(): @@ -1413,12 +1420,12 @@ async def test_create_conversation_profile_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[ - 0 - ].conversation_profile == gcd_conversation_profile.ConversationProfile( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].conversation_profile + mock_val = gcd_conversation_profile.ConversationProfile(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1460,6 +1467,8 @@ def test_update_conversation_profile( name="name_value", display_name="display_name_value", language_code="language_code_value", + time_zone="time_zone_value", + security_settings="security_settings_value", ) response = client.update_conversation_profile(request) @@ -1473,6 +1482,8 @@ def test_update_conversation_profile( assert response.name == "name_value" assert response.display_name == "display_name_value" assert response.language_code == "language_code_value" + assert response.time_zone == "time_zone_value" + assert response.security_settings == "security_settings_value" def test_update_conversation_profile_from_dict(): @@ -1519,6 +1530,8 @@ async def test_update_conversation_profile_async( name="name_value", display_name="display_name_value", language_code="language_code_value", + time_zone="time_zone_value", + security_settings="security_settings_value", ) ) response = await client.update_conversation_profile(request) @@ -1533,6 +1546,8 @@ async def test_update_conversation_profile_async( assert response.name == "name_value" assert response.display_name == "display_name_value" assert response.language_code == "language_code_value" + assert response.time_zone == "time_zone_value" + assert response.security_settings == "security_settings_value" @pytest.mark.asyncio @@ -1629,12 +1644,12 @@ def test_update_conversation_profile_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[ - 0 - ].conversation_profile == gcd_conversation_profile.ConversationProfile( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].conversation_profile + mock_val = gcd_conversation_profile.ConversationProfile(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_conversation_profile_flattened_error(): @@ -1683,12 +1698,12 @@ async def test_update_conversation_profile_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[ - 0 - ].conversation_profile == gcd_conversation_profile.ConversationProfile( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].conversation_profile + mock_val = gcd_conversation_profile.ConversationProfile(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1870,7 +1885,9 @@ def test_delete_conversation_profile_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_conversation_profile_flattened_error(): @@ -1908,7 +1925,9 @@ async def test_delete_conversation_profile_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2034,8 +2053,10 @@ def test_conversation_profiles_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_conversation_profiles_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2059,29 +2080,6 @@ def test_conversation_profiles_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_conversation_profiles_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.conversation_profiles.transports.ConversationProfilesTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.ConversationProfilesTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_conversation_profiles_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2093,7 +2091,6 @@ def test_conversation_profiles_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_conversation_profiles_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2109,21 +2106,6 @@ def test_conversation_profiles_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_conversation_profiles_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - ConversationProfilesClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2131,7 +2113,6 @@ def test_conversation_profiles_auth_adc_old_google_auth(): transports.ConversationProfilesGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_conversation_profiles_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2148,29 +2129,6 @@ def test_conversation_profiles_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.ConversationProfilesGrpcTransport, - transports.ConversationProfilesGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_conversation_profiles_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2468,10 +2426,36 @@ def test_parse_conversation_profile_path(): assert expected == actual -def test_document_path(): +def test_cx_security_settings_path(): project = "squid" - knowledge_base = "clam" - document = "whelk" + location = "clam" + security_settings = "whelk" + expected = "projects/{project}/locations/{location}/securitySettings/{security_settings}".format( + project=project, location=location, security_settings=security_settings, + ) + actual = ConversationProfilesClient.cx_security_settings_path( + project, location, security_settings + ) + assert expected == actual + + +def test_parse_cx_security_settings_path(): + expected = { + "project": "octopus", + "location": "oyster", + "security_settings": "nudibranch", + } + path = ConversationProfilesClient.cx_security_settings_path(**expected) + + # Check that the path construction is reversible. + actual = ConversationProfilesClient.parse_cx_security_settings_path(path) + assert expected == actual + + +def test_document_path(): + project = "cuttlefish" + knowledge_base = "mussel" + document = "winkle" expected = "projects/{project}/knowledgeBases/{knowledge_base}/documents/{document}".format( project=project, knowledge_base=knowledge_base, document=document, ) @@ -2481,9 +2465,9 @@ def test_document_path(): def test_parse_document_path(): expected = { - "project": "octopus", - "knowledge_base": "oyster", - "document": "nudibranch", + "project": "nautilus", + "knowledge_base": "scallop", + "document": "abalone", } path = ConversationProfilesClient.document_path(**expected) @@ -2493,8 +2477,8 @@ def test_parse_document_path(): def test_knowledge_base_path(): - project = "cuttlefish" - knowledge_base = "mussel" + project = "squid" + knowledge_base = "clam" expected = "projects/{project}/knowledgeBases/{knowledge_base}".format( project=project, knowledge_base=knowledge_base, ) @@ -2504,8 +2488,8 @@ def test_knowledge_base_path(): def test_parse_knowledge_base_path(): expected = { - "project": "winkle", - "knowledge_base": "nautilus", + "project": "whelk", + "knowledge_base": "octopus", } path = ConversationProfilesClient.knowledge_base_path(**expected) @@ -2515,7 +2499,7 @@ def test_parse_knowledge_base_path(): def test_common_billing_account_path(): - billing_account = "scallop" + billing_account = "oyster" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -2525,7 +2509,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "abalone", + "billing_account": "nudibranch", } path = ConversationProfilesClient.common_billing_account_path(**expected) @@ -2535,7 +2519,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "squid" + folder = "cuttlefish" expected = "folders/{folder}".format(folder=folder,) actual = ConversationProfilesClient.common_folder_path(folder) assert expected == actual @@ -2543,7 +2527,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "clam", + "folder": "mussel", } path = ConversationProfilesClient.common_folder_path(**expected) @@ -2553,7 +2537,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "whelk" + organization = "winkle" expected = "organizations/{organization}".format(organization=organization,) actual = ConversationProfilesClient.common_organization_path(organization) assert expected == actual @@ -2561,7 +2545,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "octopus", + "organization": "nautilus", } path = ConversationProfilesClient.common_organization_path(**expected) @@ -2571,7 +2555,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "oyster" + project = "scallop" expected = "projects/{project}".format(project=project,) actual = ConversationProfilesClient.common_project_path(project) assert expected == actual @@ -2579,7 +2563,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "nudibranch", + "project": "abalone", } path = ConversationProfilesClient.common_project_path(**expected) @@ -2589,8 +2573,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "cuttlefish" - location = "mussel" + project = "squid" + location = "clam" expected = "projects/{project}/locations/{location}".format( project=project, location=location, ) @@ -2600,8 +2584,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "winkle", - "location": "nautilus", + "project": "whelk", + "location": "octopus", } path = ConversationProfilesClient.common_location_path(**expected) @@ -2629,3 +2613,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = ConversationProfilesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = ConversationProfilesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = ConversationProfilesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_conversations.py b/tests/unit/gapic/dialogflow_v2/test_conversations.py index 7ad642f4a..d8aaef6df 100644 --- a/tests/unit/gapic/dialogflow_v2/test_conversations.py +++ b/tests/unit/gapic/dialogflow_v2/test_conversations.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,15 +28,13 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.conversations import ConversationsAsyncClient from google.cloud.dialogflow_v2.services.conversations import ConversationsClient from google.cloud.dialogflow_v2.services.conversations import pagers from google.cloud.dialogflow_v2.services.conversations import transports -from google.cloud.dialogflow_v2.services.conversations.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import conversation from google.cloud.dialogflow_v2.types import conversation as gcd_conversation from google.cloud.dialogflow_v2.types import participant @@ -46,20 +43,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -216,7 +199,7 @@ def test_conversations_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -233,7 +216,7 @@ def test_conversations_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -250,7 +233,7 @@ def test_conversations_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -279,7 +262,7 @@ def test_conversations_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -338,7 +321,7 @@ def test_conversations_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -380,7 +363,7 @@ def test_conversations_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -402,7 +385,7 @@ def test_conversations_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -433,7 +416,7 @@ def test_conversations_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -464,7 +447,7 @@ def test_conversations_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -690,8 +673,12 @@ def test_create_conversation_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].conversation == gcd_conversation.Conversation(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].conversation + mock_val = gcd_conversation.Conversation(name="name_value") + assert arg == mock_val def test_create_conversation_flattened_error(): @@ -734,8 +721,12 @@ async def test_create_conversation_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].conversation == gcd_conversation.Conversation(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].conversation + mock_val = gcd_conversation.Conversation(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -919,7 +910,9 @@ def test_list_conversations_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_conversations_flattened_error(): @@ -957,7 +950,9 @@ async def test_list_conversations_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1315,7 +1310,9 @@ def test_get_conversation_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_conversation_flattened_error(): @@ -1351,7 +1348,9 @@ async def test_get_conversation_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1556,7 +1555,9 @@ def test_complete_conversation_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_complete_conversation_flattened_error(): @@ -1594,7 +1595,9 @@ async def test_complete_conversation_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1762,7 +1765,9 @@ def test_list_messages_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_messages_flattened_error(): @@ -1798,7 +1803,9 @@ async def test_list_messages_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2060,8 +2067,10 @@ def test_conversations_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_conversations_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2085,29 +2094,6 @@ def test_conversations_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_conversations_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.conversations.transports.ConversationsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.ConversationsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_conversations_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2119,7 +2105,6 @@ def test_conversations_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_conversations_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2135,21 +2120,6 @@ def test_conversations_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_conversations_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - ConversationsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2157,7 +2127,6 @@ def test_conversations_auth_adc_old_google_auth(): transports.ConversationsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_conversations_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2174,29 +2143,6 @@ def test_conversations_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.ConversationsGrpcTransport, - transports.ConversationsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_conversations_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2607,3 +2553,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = ConversationsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = ConversationsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = ConversationsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_documents.py b/tests/unit/gapic/dialogflow_v2/test_documents.py index 4c9f30aef..842f8581d 100644 --- a/tests/unit/gapic/dialogflow_v2/test_documents.py +++ b/tests/unit/gapic/dialogflow_v2/test_documents.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -32,15 +31,13 @@ from google.api_core import grpc_helpers_async from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.documents import DocumentsAsyncClient from google.cloud.dialogflow_v2.services.documents import DocumentsClient from google.cloud.dialogflow_v2.services.documents import pagers from google.cloud.dialogflow_v2.services.documents import transports -from google.cloud.dialogflow_v2.services.documents.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import document from google.cloud.dialogflow_v2.types import document as gcd_document from google.longrunning import operations_pb2 @@ -52,20 +49,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -209,7 +192,7 @@ def test_documents_client_client_options(client_class, transport_class, transpor options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -226,7 +209,7 @@ def test_documents_client_client_options(client_class, transport_class, transpor with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -243,7 +226,7 @@ def test_documents_client_client_options(client_class, transport_class, transpor with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -272,7 +255,7 @@ def test_documents_client_client_options(client_class, transport_class, transpor options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -329,7 +312,7 @@ def test_documents_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -371,7 +354,7 @@ def test_documents_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -393,7 +376,7 @@ def test_documents_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -424,7 +407,7 @@ def test_documents_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -455,7 +438,7 @@ def test_documents_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -635,7 +618,9 @@ def test_list_documents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_documents_flattened_error(): @@ -669,7 +654,9 @@ async def test_list_documents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -988,7 +975,9 @@ def test_get_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_document_flattened_error(): @@ -1020,7 +1009,9 @@ async def test_get_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1182,8 +1173,12 @@ def test_create_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].document == gcd_document.Document(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].document + mock_val = gcd_document.Document(name="name_value") + assert arg == mock_val def test_create_document_flattened_error(): @@ -1221,8 +1216,12 @@ async def test_create_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].document == gcd_document.Document(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].document + mock_val = gcd_document.Document(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1384,7 +1383,9 @@ def test_delete_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_document_flattened_error(): @@ -1418,7 +1419,9 @@ async def test_delete_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1585,8 +1588,12 @@ def test_update_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].document == gcd_document.Document(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].document + mock_val = gcd_document.Document(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_document_flattened_error(): @@ -1625,8 +1632,12 @@ async def test_update_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].document == gcd_document.Document(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].document + mock_val = gcd_document.Document(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1790,7 +1801,9 @@ def test_reload_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val assert args[0].content_uri == "content_uri_value" @@ -1829,7 +1842,9 @@ async def test_reload_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val assert args[0].content_uri == "content_uri_value" @@ -1952,13 +1967,15 @@ def test_documents_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + # Additionally, the LRO client (a property) should # also raise NotImplementedError with pytest.raises(NotImplementedError): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_documents_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1982,29 +1999,6 @@ def test_documents_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_documents_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.documents.transports.DocumentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.DocumentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_documents_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2016,7 +2010,6 @@ def test_documents_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_documents_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2032,26 +2025,10 @@ def test_documents_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_documents_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - DocumentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.DocumentsGrpcTransport, transports.DocumentsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_documents_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2068,26 +2045,6 @@ def test_documents_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.DocumentsGrpcTransport, transports.DocumentsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_documents_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2469,3 +2426,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = DocumentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = DocumentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = DocumentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_entity_types.py b/tests/unit/gapic/dialogflow_v2/test_entity_types.py index 67e11ff5a..7c6ce3960 100644 --- a/tests/unit/gapic/dialogflow_v2/test_entity_types.py +++ b/tests/unit/gapic/dialogflow_v2/test_entity_types.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -32,15 +31,13 @@ from google.api_core import grpc_helpers_async from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.entity_types import EntityTypesAsyncClient from google.cloud.dialogflow_v2.services.entity_types import EntityTypesClient from google.cloud.dialogflow_v2.services.entity_types import pagers from google.cloud.dialogflow_v2.services.entity_types import transports -from google.cloud.dialogflow_v2.services.entity_types.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import entity_type from google.cloud.dialogflow_v2.types import entity_type as gcd_entity_type from google.longrunning import operations_pb2 @@ -50,20 +47,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -211,7 +194,7 @@ def test_entity_types_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -228,7 +211,7 @@ def test_entity_types_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -245,7 +228,7 @@ def test_entity_types_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -274,7 +257,7 @@ def test_entity_types_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -331,7 +314,7 @@ def test_entity_types_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -373,7 +356,7 @@ def test_entity_types_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -395,7 +378,7 @@ def test_entity_types_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -426,7 +409,7 @@ def test_entity_types_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -457,7 +440,7 @@ def test_entity_types_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -653,8 +636,12 @@ def test_list_entity_types_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_list_entity_types_flattened_error(): @@ -694,8 +681,12 @@ async def test_list_entity_types_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1041,8 +1032,12 @@ def test_get_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].language_code == "language_code_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_get_entity_type_flattened_error(): @@ -1080,8 +1075,12 @@ async def test_get_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].language_code == "language_code_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1288,9 +1287,15 @@ def test_create_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_type == gcd_entity_type.EntityType(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_type + mock_val = gcd_entity_type.EntityType(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_create_entity_type_flattened_error(): @@ -1333,9 +1338,15 @@ async def test_create_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_type == gcd_entity_type.EntityType(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_type + mock_val = gcd_entity_type.EntityType(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1546,8 +1557,12 @@ def test_update_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].entity_type == gcd_entity_type.EntityType(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].entity_type + mock_val = gcd_entity_type.EntityType(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_update_entity_type_flattened_error(): @@ -1588,8 +1603,12 @@ async def test_update_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].entity_type == gcd_entity_type.EntityType(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].entity_type + mock_val = gcd_entity_type.EntityType(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1759,7 +1778,9 @@ def test_delete_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_entity_type_flattened_error(): @@ -1793,7 +1814,9 @@ async def test_delete_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2109,8 +2132,12 @@ def test_batch_delete_entity_types_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_type_names == ["entity_type_names_value"] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_type_names + mock_val = ["entity_type_names_value"] + assert arg == mock_val def test_batch_delete_entity_types_flattened_error(): @@ -2150,8 +2177,12 @@ async def test_batch_delete_entity_types_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_type_names == ["entity_type_names_value"] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_type_names + mock_val = ["entity_type_names_value"] + assert arg == mock_val @pytest.mark.asyncio @@ -2329,9 +2360,15 @@ def test_batch_create_entities_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entities == [entity_type.EntityType.Entity(value="value_value")] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entities + mock_val = [entity_type.EntityType.Entity(value="value_value")] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_batch_create_entities_flattened_error(): @@ -2374,9 +2411,15 @@ async def test_batch_create_entities_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entities == [entity_type.EntityType.Entity(value="value_value")] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entities + mock_val = [entity_type.EntityType.Entity(value="value_value")] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2555,9 +2598,15 @@ def test_batch_update_entities_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entities == [entity_type.EntityType.Entity(value="value_value")] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entities + mock_val = [entity_type.EntityType.Entity(value="value_value")] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_batch_update_entities_flattened_error(): @@ -2600,9 +2649,15 @@ async def test_batch_update_entities_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entities == [entity_type.EntityType.Entity(value="value_value")] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entities + mock_val = [entity_type.EntityType.Entity(value="value_value")] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2781,9 +2836,15 @@ def test_batch_delete_entities_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_values == ["entity_values_value"] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_values + mock_val = ["entity_values_value"] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_batch_delete_entities_flattened_error(): @@ -2826,9 +2887,15 @@ async def test_batch_delete_entities_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_values == ["entity_values_value"] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_values + mock_val = ["entity_values_value"] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2955,13 +3022,15 @@ def test_entity_types_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + # Additionally, the LRO client (a property) should # also raise NotImplementedError with pytest.raises(NotImplementedError): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_entity_types_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2985,29 +3054,6 @@ def test_entity_types_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_entity_types_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.entity_types.transports.EntityTypesTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.EntityTypesTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_entity_types_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -3019,7 +3065,6 @@ def test_entity_types_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_entity_types_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -3035,26 +3080,10 @@ def test_entity_types_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_entity_types_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - EntityTypesClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.EntityTypesGrpcTransport, transports.EntityTypesGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_entity_types_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -3071,26 +3100,6 @@ def test_entity_types_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.EntityTypesGrpcTransport, transports.EntityTypesGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_entity_types_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -3470,3 +3479,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = EntityTypesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = EntityTypesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = EntityTypesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_environments.py b/tests/unit/gapic/dialogflow_v2/test_environments.py index 6965f6afa..00ceb70bc 100644 --- a/tests/unit/gapic/dialogflow_v2/test_environments.py +++ b/tests/unit/gapic/dialogflow_v2/test_environments.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,15 +28,13 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.environments import EnvironmentsAsyncClient from google.cloud.dialogflow_v2.services.environments import EnvironmentsClient from google.cloud.dialogflow_v2.services.environments import pagers from google.cloud.dialogflow_v2.services.environments import transports -from google.cloud.dialogflow_v2.services.environments.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import audio_config from google.cloud.dialogflow_v2.types import environment from google.cloud.dialogflow_v2.types import fulfillment @@ -47,20 +44,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -208,7 +191,7 @@ def test_environments_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -225,7 +208,7 @@ def test_environments_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -242,7 +225,7 @@ def test_environments_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -271,7 +254,7 @@ def test_environments_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -328,7 +311,7 @@ def test_environments_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -370,7 +353,7 @@ def test_environments_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -392,7 +375,7 @@ def test_environments_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -423,7 +406,7 @@ def test_environments_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -454,7 +437,7 @@ def test_environments_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -648,7 +631,9 @@ def test_list_environments_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_environments_flattened_error(): @@ -684,7 +669,9 @@ async def test_list_environments_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1878,8 +1865,10 @@ def test_environments_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_environments_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1903,29 +1892,6 @@ def test_environments_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_environments_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.environments.transports.EnvironmentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.EnvironmentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_environments_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1937,7 +1903,6 @@ def test_environments_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_environments_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1953,21 +1918,6 @@ def test_environments_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_environments_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - EnvironmentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -1975,7 +1925,6 @@ def test_environments_auth_adc_old_google_auth(): transports.EnvironmentsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_environments_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1992,29 +1941,6 @@ def test_environments_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.EnvironmentsGrpcTransport, - transports.EnvironmentsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_environments_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2408,3 +2334,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = EnvironmentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = EnvironmentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = EnvironmentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_fulfillments.py b/tests/unit/gapic/dialogflow_v2/test_fulfillments.py index 7d333c9b3..6a2360877 100644 --- a/tests/unit/gapic/dialogflow_v2/test_fulfillments.py +++ b/tests/unit/gapic/dialogflow_v2/test_fulfillments.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,14 +28,12 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.fulfillments import FulfillmentsAsyncClient from google.cloud.dialogflow_v2.services.fulfillments import FulfillmentsClient from google.cloud.dialogflow_v2.services.fulfillments import transports -from google.cloud.dialogflow_v2.services.fulfillments.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import fulfillment from google.cloud.dialogflow_v2.types import fulfillment as gcd_fulfillment from google.oauth2 import service_account @@ -44,20 +41,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -205,7 +188,7 @@ def test_fulfillments_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -222,7 +205,7 @@ def test_fulfillments_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -239,7 +222,7 @@ def test_fulfillments_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -268,7 +251,7 @@ def test_fulfillments_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -325,7 +308,7 @@ def test_fulfillments_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -367,7 +350,7 @@ def test_fulfillments_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -389,7 +372,7 @@ def test_fulfillments_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -420,7 +403,7 @@ def test_fulfillments_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -451,7 +434,7 @@ def test_fulfillments_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -642,7 +625,9 @@ def test_get_fulfillment_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_fulfillment_flattened_error(): @@ -676,7 +661,9 @@ async def test_get_fulfillment_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -871,8 +858,12 @@ def test_update_fulfillment_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].fulfillment == gcd_fulfillment.Fulfillment(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].fulfillment + mock_val = gcd_fulfillment.Fulfillment(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_fulfillment_flattened_error(): @@ -913,8 +904,12 @@ async def test_update_fulfillment_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].fulfillment == gcd_fulfillment.Fulfillment(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].fulfillment + mock_val = gcd_fulfillment.Fulfillment(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1035,8 +1030,10 @@ def test_fulfillments_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_fulfillments_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1060,29 +1057,6 @@ def test_fulfillments_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_fulfillments_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.fulfillments.transports.FulfillmentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.FulfillmentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_fulfillments_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1094,7 +1068,6 @@ def test_fulfillments_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_fulfillments_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1110,21 +1083,6 @@ def test_fulfillments_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_fulfillments_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - FulfillmentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -1132,7 +1090,6 @@ def test_fulfillments_auth_adc_old_google_auth(): transports.FulfillmentsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_fulfillments_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1149,29 +1106,6 @@ def test_fulfillments_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.FulfillmentsGrpcTransport, - transports.FulfillmentsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_fulfillments_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -1521,3 +1455,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = FulfillmentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = FulfillmentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = FulfillmentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_intents.py b/tests/unit/gapic/dialogflow_v2/test_intents.py index c0859159e..d5c2ac54a 100644 --- a/tests/unit/gapic/dialogflow_v2/test_intents.py +++ b/tests/unit/gapic/dialogflow_v2/test_intents.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -32,15 +31,13 @@ from google.api_core import grpc_helpers_async from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.intents import IntentsAsyncClient from google.cloud.dialogflow_v2.services.intents import IntentsClient from google.cloud.dialogflow_v2.services.intents import pagers from google.cloud.dialogflow_v2.services.intents import transports -from google.cloud.dialogflow_v2.services.intents.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import context from google.cloud.dialogflow_v2.types import intent from google.cloud.dialogflow_v2.types import intent as gcd_intent @@ -51,20 +48,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -199,7 +182,7 @@ def test_intents_client_client_options(client_class, transport_class, transport_ options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -216,7 +199,7 @@ def test_intents_client_client_options(client_class, transport_class, transport_ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -233,7 +216,7 @@ def test_intents_client_client_options(client_class, transport_class, transport_ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +245,7 @@ def test_intents_client_client_options(client_class, transport_class, transport_ options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -317,7 +300,7 @@ def test_intents_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -359,7 +342,7 @@ def test_intents_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -381,7 +364,7 @@ def test_intents_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -408,7 +391,7 @@ def test_intents_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -435,7 +418,7 @@ def test_intents_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -615,8 +598,12 @@ def test_list_intents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_list_intents_flattened_error(): @@ -654,8 +641,12 @@ async def test_list_intents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -995,8 +986,12 @@ def test_get_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].language_code == "language_code_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_get_intent_flattened_error(): @@ -1032,8 +1027,12 @@ async def test_get_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].language_code == "language_code_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1269,9 +1268,15 @@ def test_create_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].intent == gcd_intent.Intent(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].intent + mock_val = gcd_intent.Intent(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_create_intent_flattened_error(): @@ -1310,9 +1315,15 @@ async def test_create_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].intent == gcd_intent.Intent(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].intent + mock_val = gcd_intent.Intent(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1549,9 +1560,15 @@ def test_update_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].intent == gcd_intent.Intent(name="name_value") - assert args[0].language_code == "language_code_value" - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].intent + mock_val = gcd_intent.Intent(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_intent_flattened_error(): @@ -1590,9 +1607,15 @@ async def test_update_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].intent == gcd_intent.Intent(name="name_value") - assert args[0].language_code == "language_code_value" - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].intent + mock_val = gcd_intent.Intent(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1751,7 +1774,9 @@ def test_delete_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_intent_flattened_error(): @@ -1783,7 +1808,9 @@ async def test_delete_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1961,7 +1988,9 @@ def test_batch_update_intents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val assert args[0].intent_batch_inline == intent.IntentBatch( intents=[intent.Intent(name="name_value")] ) @@ -2011,7 +2040,9 @@ async def test_batch_update_intents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val assert args[0].intent_batch_inline == intent.IntentBatch( intents=[intent.Intent(name="name_value")] ) @@ -2193,8 +2224,12 @@ def test_batch_delete_intents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].intents == [intent.Intent(name="name_value")] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].intents + mock_val = [intent.Intent(name="name_value")] + assert arg == mock_val def test_batch_delete_intents_flattened_error(): @@ -2234,8 +2269,12 @@ async def test_batch_delete_intents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].intents == [intent.Intent(name="name_value")] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].intents + mock_val = [intent.Intent(name="name_value")] + assert arg == mock_val @pytest.mark.asyncio @@ -2358,13 +2397,15 @@ def test_intents_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + # Additionally, the LRO client (a property) should # also raise NotImplementedError with pytest.raises(NotImplementedError): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_intents_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2388,29 +2429,6 @@ def test_intents_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_intents_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.intents.transports.IntentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.IntentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_intents_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2422,7 +2440,6 @@ def test_intents_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_intents_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2438,26 +2455,10 @@ def test_intents_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_intents_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - IntentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.IntentsGrpcTransport, transports.IntentsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_intents_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2474,26 +2475,6 @@ def test_intents_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.IntentsGrpcTransport, transports.IntentsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_intents_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2897,3 +2878,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = IntentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = IntentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = IntentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_knowledge_bases.py b/tests/unit/gapic/dialogflow_v2/test_knowledge_bases.py index 37f0fb813..d49c11ebe 100644 --- a/tests/unit/gapic/dialogflow_v2/test_knowledge_bases.py +++ b/tests/unit/gapic/dialogflow_v2/test_knowledge_bases.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.knowledge_bases import ( @@ -37,9 +37,6 @@ from google.cloud.dialogflow_v2.services.knowledge_bases import KnowledgeBasesClient from google.cloud.dialogflow_v2.services.knowledge_bases import pagers from google.cloud.dialogflow_v2.services.knowledge_bases import transports -from google.cloud.dialogflow_v2.services.knowledge_bases.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import knowledge_base from google.cloud.dialogflow_v2.types import knowledge_base as gcd_knowledge_base from google.oauth2 import service_account @@ -47,20 +44,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -217,7 +200,7 @@ def test_knowledge_bases_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -234,7 +217,7 @@ def test_knowledge_bases_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -251,7 +234,7 @@ def test_knowledge_bases_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -280,7 +263,7 @@ def test_knowledge_bases_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -339,7 +322,7 @@ def test_knowledge_bases_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -381,7 +364,7 @@ def test_knowledge_bases_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -403,7 +386,7 @@ def test_knowledge_bases_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -434,7 +417,7 @@ def test_knowledge_bases_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -465,7 +448,7 @@ def test_knowledge_bases_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -664,7 +647,9 @@ def test_list_knowledge_bases_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_knowledge_bases_flattened_error(): @@ -702,7 +687,9 @@ async def test_list_knowledge_bases_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1062,7 +1049,9 @@ def test_get_knowledge_base_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_knowledge_base_flattened_error(): @@ -1100,7 +1089,9 @@ async def test_get_knowledge_base_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1294,10 +1285,12 @@ def test_create_knowledge_base_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].knowledge_base == gcd_knowledge_base.KnowledgeBase( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].knowledge_base + mock_val = gcd_knowledge_base.KnowledgeBase(name="name_value") + assert arg == mock_val def test_create_knowledge_base_flattened_error(): @@ -1340,10 +1333,12 @@ async def test_create_knowledge_base_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].knowledge_base == gcd_knowledge_base.KnowledgeBase( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].knowledge_base + mock_val = gcd_knowledge_base.KnowledgeBase(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1518,7 +1513,9 @@ def test_delete_knowledge_base_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_knowledge_base_flattened_error(): @@ -1554,7 +1551,9 @@ async def test_delete_knowledge_base_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1754,10 +1753,12 @@ def test_update_knowledge_base_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].knowledge_base == gcd_knowledge_base.KnowledgeBase( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].knowledge_base + mock_val = gcd_knowledge_base.KnowledgeBase(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_knowledge_base_flattened_error(): @@ -1800,10 +1801,12 @@ async def test_update_knowledge_base_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].knowledge_base == gcd_knowledge_base.KnowledgeBase( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].knowledge_base + mock_val = gcd_knowledge_base.KnowledgeBase(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1929,8 +1932,10 @@ def test_knowledge_bases_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_knowledge_bases_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1954,29 +1959,6 @@ def test_knowledge_bases_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_knowledge_bases_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.knowledge_bases.transports.KnowledgeBasesTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.KnowledgeBasesTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_knowledge_bases_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1988,7 +1970,6 @@ def test_knowledge_bases_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_knowledge_bases_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2004,21 +1985,6 @@ def test_knowledge_bases_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_knowledge_bases_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - KnowledgeBasesClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2026,7 +1992,6 @@ def test_knowledge_bases_auth_adc_old_google_auth(): transports.KnowledgeBasesGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_knowledge_bases_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2043,29 +2008,6 @@ def test_knowledge_bases_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.KnowledgeBasesGrpcTransport, - transports.KnowledgeBasesGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_knowledge_bases_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2430,3 +2372,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = KnowledgeBasesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = KnowledgeBasesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = KnowledgeBasesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_participants.py b/tests/unit/gapic/dialogflow_v2/test_participants.py index 423abaadc..84c4d9683 100644 --- a/tests/unit/gapic/dialogflow_v2/test_participants.py +++ b/tests/unit/gapic/dialogflow_v2/test_participants.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,15 +28,13 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.participants import ParticipantsAsyncClient from google.cloud.dialogflow_v2.services.participants import ParticipantsClient from google.cloud.dialogflow_v2.services.participants import pagers from google.cloud.dialogflow_v2.services.participants import transports -from google.cloud.dialogflow_v2.services.participants.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import audio_config from google.cloud.dialogflow_v2.types import context from google.cloud.dialogflow_v2.types import entity_type @@ -52,20 +49,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -213,7 +196,7 @@ def test_participants_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -230,7 +213,7 @@ def test_participants_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -247,7 +230,7 @@ def test_participants_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -276,7 +259,7 @@ def test_participants_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -333,7 +316,7 @@ def test_participants_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -375,7 +358,7 @@ def test_participants_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -397,7 +380,7 @@ def test_participants_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -428,7 +411,7 @@ def test_participants_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -459,7 +442,7 @@ def test_participants_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -665,8 +648,12 @@ def test_create_participant_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].participant == gcd_participant.Participant(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].participant + mock_val = gcd_participant.Participant(name="name_value") + assert arg == mock_val def test_create_participant_flattened_error(): @@ -707,8 +694,12 @@ async def test_create_participant_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].participant == gcd_participant.Participant(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].participant + mock_val = gcd_participant.Participant(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -884,7 +875,9 @@ def test_get_participant_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_participant_flattened_error(): @@ -918,7 +911,9 @@ async def test_get_participant_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1096,7 +1091,9 @@ def test_list_participants_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_participants_flattened_error(): @@ -1132,7 +1129,9 @@ async def test_list_participants_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1480,8 +1479,12 @@ def test_update_participant_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].participant == gcd_participant.Participant(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].participant + mock_val = gcd_participant.Participant(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_participant_flattened_error(): @@ -1522,8 +1525,12 @@ async def test_update_participant_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].participant == gcd_participant.Participant(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].participant + mock_val = gcd_participant.Participant(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1693,7 +1700,9 @@ def test_analyze_content_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].participant == "participant_value" + arg = args[0].participant + mock_val = "participant_value" + assert arg == mock_val assert args[0].event_input == session.EventInput(name="name_value") @@ -1735,7 +1744,9 @@ async def test_analyze_content_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].participant == "participant_value" + arg = args[0].participant + mock_val = "participant_value" + assert arg == mock_val assert args[0].event_input == session.EventInput(name="name_value") @@ -1907,7 +1918,9 @@ def test_suggest_articles_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_suggest_articles_flattened_error(): @@ -1941,7 +1954,9 @@ async def test_suggest_articles_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2121,7 +2136,9 @@ def test_suggest_faq_answers_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_suggest_faq_answers_flattened_error(): @@ -2157,7 +2174,9 @@ async def test_suggest_faq_answers_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2281,8 +2300,10 @@ def test_participants_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_participants_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2306,29 +2327,6 @@ def test_participants_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_participants_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.participants.transports.ParticipantsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.ParticipantsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_participants_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2340,7 +2338,6 @@ def test_participants_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_participants_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2356,21 +2353,6 @@ def test_participants_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_participants_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - ParticipantsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2378,7 +2360,6 @@ def test_participants_auth_adc_old_google_auth(): transports.ParticipantsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_participants_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2395,29 +2376,6 @@ def test_participants_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.ParticipantsGrpcTransport, - transports.ParticipantsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_participants_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2867,3 +2825,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = ParticipantsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = ParticipantsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = ParticipantsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_session_entity_types.py b/tests/unit/gapic/dialogflow_v2/test_session_entity_types.py index 99853d150..f6a4d4877 100644 --- a/tests/unit/gapic/dialogflow_v2/test_session_entity_types.py +++ b/tests/unit/gapic/dialogflow_v2/test_session_entity_types.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.session_entity_types import ( @@ -39,9 +39,6 @@ ) from google.cloud.dialogflow_v2.services.session_entity_types import pagers from google.cloud.dialogflow_v2.services.session_entity_types import transports -from google.cloud.dialogflow_v2.services.session_entity_types.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import entity_type from google.cloud.dialogflow_v2.types import session_entity_type from google.cloud.dialogflow_v2.types import ( @@ -52,20 +49,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -223,7 +206,7 @@ def test_session_entity_types_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -240,7 +223,7 @@ def test_session_entity_types_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -257,7 +240,7 @@ def test_session_entity_types_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -286,7 +269,7 @@ def test_session_entity_types_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -355,7 +338,7 @@ def test_session_entity_types_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -397,7 +380,7 @@ def test_session_entity_types_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -419,7 +402,7 @@ def test_session_entity_types_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -450,7 +433,7 @@ def test_session_entity_types_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -481,7 +464,7 @@ def test_session_entity_types_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -685,7 +668,9 @@ def test_list_session_entity_types_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_session_entity_types_flattened_error(): @@ -725,7 +710,9 @@ async def test_list_session_entity_types_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1101,7 +1088,9 @@ def test_get_session_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_session_entity_type_flattened_error(): @@ -1141,7 +1130,9 @@ async def test_get_session_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1344,10 +1335,12 @@ def test_create_session_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].session_entity_type == gcd_session_entity_type.SessionEntityType( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].session_entity_type + mock_val = gcd_session_entity_type.SessionEntityType(name="name_value") + assert arg == mock_val def test_create_session_entity_type_flattened_error(): @@ -1396,10 +1389,12 @@ async def test_create_session_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].session_entity_type == gcd_session_entity_type.SessionEntityType( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].session_entity_type + mock_val = gcd_session_entity_type.SessionEntityType(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1612,10 +1607,12 @@ def test_update_session_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].session_entity_type == gcd_session_entity_type.SessionEntityType( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].session_entity_type + mock_val = gcd_session_entity_type.SessionEntityType(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_session_entity_type_flattened_error(): @@ -1664,10 +1661,12 @@ async def test_update_session_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].session_entity_type == gcd_session_entity_type.SessionEntityType( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].session_entity_type + mock_val = gcd_session_entity_type.SessionEntityType(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1849,7 +1848,9 @@ def test_delete_session_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_session_entity_type_flattened_error(): @@ -1887,7 +1888,9 @@ async def test_delete_session_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2013,8 +2016,10 @@ def test_session_entity_types_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_session_entity_types_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2038,29 +2043,6 @@ def test_session_entity_types_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_session_entity_types_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.session_entity_types.transports.SessionEntityTypesTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.SessionEntityTypesTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_session_entity_types_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2072,7 +2054,6 @@ def test_session_entity_types_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_session_entity_types_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2088,21 +2069,6 @@ def test_session_entity_types_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_session_entity_types_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - SessionEntityTypesClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2110,7 +2076,6 @@ def test_session_entity_types_auth_adc_old_google_auth(): transports.SessionEntityTypesGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_session_entity_types_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2127,29 +2092,6 @@ def test_session_entity_types_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.SessionEntityTypesGrpcTransport, - transports.SessionEntityTypesGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_session_entity_types_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2520,3 +2462,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = SessionEntityTypesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = SessionEntityTypesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = SessionEntityTypesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_sessions.py b/tests/unit/gapic/dialogflow_v2/test_sessions.py index 16d28e830..4450d9cfa 100644 --- a/tests/unit/gapic/dialogflow_v2/test_sessions.py +++ b/tests/unit/gapic/dialogflow_v2/test_sessions.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,14 +28,12 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.sessions import SessionsAsyncClient from google.cloud.dialogflow_v2.services.sessions import SessionsClient from google.cloud.dialogflow_v2.services.sessions import transports -from google.cloud.dialogflow_v2.services.sessions.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import audio_config from google.cloud.dialogflow_v2.types import context from google.cloud.dialogflow_v2.types import entity_type @@ -51,20 +48,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -204,7 +187,7 @@ def test_sessions_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -221,7 +204,7 @@ def test_sessions_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -238,7 +221,7 @@ def test_sessions_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -267,7 +250,7 @@ def test_sessions_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -324,7 +307,7 @@ def test_sessions_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -366,7 +349,7 @@ def test_sessions_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -388,7 +371,7 @@ def test_sessions_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -415,7 +398,7 @@ def test_sessions_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -442,7 +425,7 @@ def test_sessions_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -633,12 +616,16 @@ def test_detect_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].session == "session_value" - assert args[0].query_input == gcd_session.QueryInput( + arg = args[0].session + mock_val = "session_value" + assert arg == mock_val + arg = args[0].query_input + mock_val = gcd_session.QueryInput( audio_config=audio_config.InputAudioConfig( audio_encoding=audio_config.AudioEncoding.AUDIO_ENCODING_LINEAR_16 ) ) + assert arg == mock_val def test_detect_intent_flattened_error(): @@ -685,12 +672,16 @@ async def test_detect_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].session == "session_value" - assert args[0].query_input == gcd_session.QueryInput( + arg = args[0].session + mock_val = "session_value" + assert arg == mock_val + arg = args[0].query_input + mock_val = gcd_session.QueryInput( audio_config=audio_config.InputAudioConfig( audio_encoding=audio_config.AudioEncoding.AUDIO_ENCODING_LINEAR_16 ) ) + assert arg == mock_val @pytest.mark.asyncio @@ -885,8 +876,10 @@ def test_sessions_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_sessions_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -910,29 +903,6 @@ def test_sessions_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_sessions_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.sessions.transports.SessionsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.SessionsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_sessions_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -944,7 +914,6 @@ def test_sessions_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_sessions_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -960,26 +929,10 @@ def test_sessions_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_sessions_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - SessionsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.SessionsGrpcTransport, transports.SessionsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_sessions_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -996,26 +949,6 @@ def test_sessions_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.SessionsGrpcTransport, transports.SessionsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_sessions_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -1439,3 +1372,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = SessionsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = SessionsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = SessionsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2/test_versions.py b/tests/unit/gapic/dialogflow_v2/test_versions.py index c385b4980..e2fad9e8d 100644 --- a/tests/unit/gapic/dialogflow_v2/test_versions.py +++ b/tests/unit/gapic/dialogflow_v2/test_versions.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,15 +28,13 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2.services.versions import VersionsAsyncClient from google.cloud.dialogflow_v2.services.versions import VersionsClient from google.cloud.dialogflow_v2.services.versions import pagers from google.cloud.dialogflow_v2.services.versions import transports -from google.cloud.dialogflow_v2.services.versions.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2.types import version from google.cloud.dialogflow_v2.types import version as gcd_version from google.oauth2 import service_account @@ -46,20 +43,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -199,7 +182,7 @@ def test_versions_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -216,7 +199,7 @@ def test_versions_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -233,7 +216,7 @@ def test_versions_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +245,7 @@ def test_versions_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -319,7 +302,7 @@ def test_versions_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -361,7 +344,7 @@ def test_versions_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -383,7 +366,7 @@ def test_versions_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -410,7 +393,7 @@ def test_versions_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -437,7 +420,7 @@ def test_versions_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -617,7 +600,9 @@ def test_list_versions_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_versions_flattened_error(): @@ -651,7 +636,9 @@ async def test_list_versions_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -947,7 +934,9 @@ def test_get_version_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_version_flattened_error(): @@ -979,7 +968,9 @@ async def test_get_version_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1157,8 +1148,12 @@ def test_create_version_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].version == gcd_version.Version(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].version + mock_val = gcd_version.Version(name="name_value") + assert arg == mock_val def test_create_version_flattened_error(): @@ -1194,8 +1189,12 @@ async def test_create_version_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].version == gcd_version.Version(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].version + mock_val = gcd_version.Version(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1380,8 +1379,12 @@ def test_update_version_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].version == gcd_version.Version(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].version + mock_val = gcd_version.Version(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_version_flattened_error(): @@ -1418,8 +1421,12 @@ async def test_update_version_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].version == gcd_version.Version(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].version + mock_val = gcd_version.Version(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1577,7 +1584,9 @@ def test_delete_version_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_version_flattened_error(): @@ -1609,7 +1618,9 @@ async def test_delete_version_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1728,8 +1739,10 @@ def test_versions_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_versions_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1753,29 +1766,6 @@ def test_versions_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_versions_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2.services.versions.transports.VersionsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.VersionsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_versions_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1787,7 +1777,6 @@ def test_versions_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_versions_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1803,26 +1792,10 @@ def test_versions_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_versions_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - VersionsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.VersionsGrpcTransport, transports.VersionsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_versions_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1839,26 +1812,6 @@ def test_versions_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.VersionsGrpcTransport, transports.VersionsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_versions_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2212,3 +2165,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = VersionsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = VersionsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = VersionsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_agents.py b/tests/unit/gapic/dialogflow_v2beta1/test_agents.py index 499c1a598..35423f578 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_agents.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_agents.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -32,15 +31,13 @@ from google.api_core import grpc_helpers_async from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.agents import AgentsAsyncClient from google.cloud.dialogflow_v2beta1.services.agents import AgentsClient from google.cloud.dialogflow_v2beta1.services.agents import pagers from google.cloud.dialogflow_v2beta1.services.agents import transports -from google.cloud.dialogflow_v2beta1.services.agents.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import agent from google.cloud.dialogflow_v2beta1.types import agent as gcd_agent from google.cloud.dialogflow_v2beta1.types import validation_result @@ -51,20 +48,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -199,7 +182,7 @@ def test_agents_client_client_options(client_class, transport_class, transport_n options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -216,7 +199,7 @@ def test_agents_client_client_options(client_class, transport_class, transport_n with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -233,7 +216,7 @@ def test_agents_client_client_options(client_class, transport_class, transport_n with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +245,7 @@ def test_agents_client_client_options(client_class, transport_class, transport_n options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -317,7 +300,7 @@ def test_agents_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -359,7 +342,7 @@ def test_agents_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -381,7 +364,7 @@ def test_agents_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -408,7 +391,7 @@ def test_agents_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -435,7 +418,7 @@ def test_agents_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -661,7 +644,9 @@ def test_get_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_get_agent_flattened_error(): @@ -693,7 +678,9 @@ async def test_get_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -907,7 +894,9 @@ def test_set_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].agent == gcd_agent.Agent(parent="parent_value") + arg = args[0].agent + mock_val = gcd_agent.Agent(parent="parent_value") + assert arg == mock_val def test_set_agent_flattened_error(): @@ -939,7 +928,9 @@ async def test_set_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].agent == gcd_agent.Agent(parent="parent_value") + arg = args[0].agent + mock_val = gcd_agent.Agent(parent="parent_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1093,7 +1084,9 @@ def test_delete_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_delete_agent_flattened_error(): @@ -1125,7 +1118,9 @@ async def test_delete_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1287,7 +1282,9 @@ def test_search_agents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_search_agents_flattened_error(): @@ -1321,7 +1318,9 @@ async def test_search_agents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1585,7 +1584,9 @@ def test_train_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_train_agent_flattened_error(): @@ -1619,7 +1620,9 @@ async def test_train_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1777,7 +1780,9 @@ def test_export_agent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_export_agent_flattened_error(): @@ -1811,7 +1816,9 @@ async def test_export_agent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2330,13 +2337,15 @@ def test_agents_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + # Additionally, the LRO client (a property) should # also raise NotImplementedError with pytest.raises(NotImplementedError): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_agents_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2360,29 +2369,6 @@ def test_agents_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_agents_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.agents.transports.AgentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.AgentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_agents_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2394,7 +2380,6 @@ def test_agents_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_agents_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2410,26 +2395,10 @@ def test_agents_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_agents_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - AgentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.AgentsGrpcTransport, transports.AgentsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_agents_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2446,26 +2415,6 @@ def test_agents_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.AgentsGrpcTransport, transports.AgentsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_agents_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2841,3 +2790,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = AgentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = AgentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = AgentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_answer_records.py b/tests/unit/gapic/dialogflow_v2beta1/test_answer_records.py index 08d54de6e..ced898e69 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_answer_records.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_answer_records.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.answer_records import ( @@ -37,9 +37,6 @@ from google.cloud.dialogflow_v2beta1.services.answer_records import AnswerRecordsClient from google.cloud.dialogflow_v2beta1.services.answer_records import pagers from google.cloud.dialogflow_v2beta1.services.answer_records import transports -from google.cloud.dialogflow_v2beta1.services.answer_records.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import answer_record from google.cloud.dialogflow_v2beta1.types import answer_record as gcd_answer_record from google.cloud.dialogflow_v2beta1.types import participant @@ -49,20 +46,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -219,7 +202,7 @@ def test_answer_records_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -236,7 +219,7 @@ def test_answer_records_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -253,7 +236,7 @@ def test_answer_records_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -282,7 +265,7 @@ def test_answer_records_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -341,7 +324,7 @@ def test_answer_records_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -383,7 +366,7 @@ def test_answer_records_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -405,7 +388,7 @@ def test_answer_records_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -436,7 +419,7 @@ def test_answer_records_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -467,7 +450,7 @@ def test_answer_records_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -814,7 +797,9 @@ def test_list_answer_records_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_answer_records_flattened_error(): @@ -852,7 +837,9 @@ async def test_list_answer_records_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1211,10 +1198,12 @@ def test_update_answer_record_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].answer_record == gcd_answer_record.AnswerRecord( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].answer_record + mock_val = gcd_answer_record.AnswerRecord(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_answer_record_flattened_error(): @@ -1257,10 +1246,12 @@ async def test_update_answer_record_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].answer_record == gcd_answer_record.AnswerRecord( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].answer_record + mock_val = gcd_answer_record.AnswerRecord(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1384,8 +1375,10 @@ def test_answer_records_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_answer_records_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1409,29 +1402,6 @@ def test_answer_records_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_answer_records_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.answer_records.transports.AnswerRecordsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.AnswerRecordsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_answer_records_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1443,7 +1413,6 @@ def test_answer_records_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_answer_records_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1459,21 +1428,6 @@ def test_answer_records_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_answer_records_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - AnswerRecordsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -1481,7 +1435,6 @@ def test_answer_records_auth_adc_old_google_auth(): transports.AnswerRecordsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_answer_records_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1498,29 +1451,6 @@ def test_answer_records_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.AnswerRecordsGrpcTransport, - transports.AnswerRecordsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_answer_records_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -1883,3 +1813,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = AnswerRecordsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = AnswerRecordsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = AnswerRecordsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_contexts.py b/tests/unit/gapic/dialogflow_v2beta1/test_contexts.py index 36be09c2e..9951713d9 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_contexts.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_contexts.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,15 +28,13 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.contexts import ContextsAsyncClient from google.cloud.dialogflow_v2beta1.services.contexts import ContextsClient from google.cloud.dialogflow_v2beta1.services.contexts import pagers from google.cloud.dialogflow_v2beta1.services.contexts import transports -from google.cloud.dialogflow_v2beta1.services.contexts.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import context from google.cloud.dialogflow_v2beta1.types import context as gcd_context from google.oauth2 import service_account @@ -46,20 +43,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -199,7 +182,7 @@ def test_contexts_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -216,7 +199,7 @@ def test_contexts_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -233,7 +216,7 @@ def test_contexts_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +245,7 @@ def test_contexts_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -319,7 +302,7 @@ def test_contexts_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -361,7 +344,7 @@ def test_contexts_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -383,7 +366,7 @@ def test_contexts_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -410,7 +393,7 @@ def test_contexts_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -437,7 +420,7 @@ def test_contexts_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -617,7 +600,9 @@ def test_list_contexts_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_contexts_flattened_error(): @@ -651,7 +636,9 @@ async def test_list_contexts_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -933,7 +920,9 @@ def test_get_context_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_context_flattened_error(): @@ -965,7 +954,9 @@ async def test_get_context_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1129,8 +1120,12 @@ def test_create_context_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].context == gcd_context.Context(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].context + mock_val = gcd_context.Context(name="name_value") + assert arg == mock_val def test_create_context_flattened_error(): @@ -1166,8 +1161,12 @@ async def test_create_context_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].context == gcd_context.Context(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].context + mock_val = gcd_context.Context(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1338,8 +1337,12 @@ def test_update_context_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].context == gcd_context.Context(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].context + mock_val = gcd_context.Context(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_context_flattened_error(): @@ -1376,8 +1379,12 @@ async def test_update_context_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].context == gcd_context.Context(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].context + mock_val = gcd_context.Context(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1535,7 +1542,9 @@ def test_delete_context_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_context_flattened_error(): @@ -1567,7 +1576,9 @@ async def test_delete_context_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1735,7 +1746,9 @@ def test_delete_all_contexts_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_delete_all_contexts_flattened_error(): @@ -1769,7 +1782,9 @@ async def test_delete_all_contexts_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1889,8 +1904,10 @@ def test_contexts_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_contexts_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1914,29 +1931,6 @@ def test_contexts_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_contexts_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.contexts.transports.ContextsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.ContextsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_contexts_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1948,7 +1942,6 @@ def test_contexts_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_contexts_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1964,26 +1957,10 @@ def test_contexts_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_contexts_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - ContextsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.ContextsGrpcTransport, transports.ContextsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_contexts_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2000,26 +1977,6 @@ def test_contexts_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.ContextsGrpcTransport, transports.ContextsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_contexts_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2375,3 +2332,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = ContextsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = ContextsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = ContextsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_conversation_profiles.py b/tests/unit/gapic/dialogflow_v2beta1/test_conversation_profiles.py index 8ba444c94..c00233ed7 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_conversation_profiles.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_conversation_profiles.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.conversation_profiles import ( @@ -39,9 +39,6 @@ ) from google.cloud.dialogflow_v2beta1.services.conversation_profiles import pagers from google.cloud.dialogflow_v2beta1.services.conversation_profiles import transports -from google.cloud.dialogflow_v2beta1.services.conversation_profiles.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import audio_config from google.cloud.dialogflow_v2beta1.types import conversation_profile from google.cloud.dialogflow_v2beta1.types import ( @@ -54,20 +51,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -229,7 +212,7 @@ def test_conversation_profiles_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -246,7 +229,7 @@ def test_conversation_profiles_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -263,7 +246,7 @@ def test_conversation_profiles_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -292,7 +275,7 @@ def test_conversation_profiles_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -361,7 +344,7 @@ def test_conversation_profiles_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -403,7 +386,7 @@ def test_conversation_profiles_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -425,7 +408,7 @@ def test_conversation_profiles_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -460,7 +443,7 @@ def test_conversation_profiles_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -495,7 +478,7 @@ def test_conversation_profiles_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -699,7 +682,9 @@ def test_list_conversation_profiles_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_conversation_profiles_flattened_error(): @@ -740,7 +725,9 @@ async def test_list_conversation_profiles_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1127,7 +1114,9 @@ def test_get_conversation_profile_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_conversation_profile_flattened_error(): @@ -1167,7 +1156,9 @@ async def test_get_conversation_profile_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1376,12 +1367,12 @@ def test_create_conversation_profile_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[ - 0 - ].conversation_profile == gcd_conversation_profile.ConversationProfile( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].conversation_profile + mock_val = gcd_conversation_profile.ConversationProfile(name="name_value") + assert arg == mock_val def test_create_conversation_profile_flattened_error(): @@ -1430,12 +1421,12 @@ async def test_create_conversation_profile_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[ - 0 - ].conversation_profile == gcd_conversation_profile.ConversationProfile( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].conversation_profile + mock_val = gcd_conversation_profile.ConversationProfile(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1654,12 +1645,12 @@ def test_update_conversation_profile_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[ - 0 - ].conversation_profile == gcd_conversation_profile.ConversationProfile( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].conversation_profile + mock_val = gcd_conversation_profile.ConversationProfile(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_conversation_profile_flattened_error(): @@ -1708,12 +1699,12 @@ async def test_update_conversation_profile_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[ - 0 - ].conversation_profile == gcd_conversation_profile.ConversationProfile( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].conversation_profile + mock_val = gcd_conversation_profile.ConversationProfile(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1895,7 +1886,9 @@ def test_delete_conversation_profile_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_conversation_profile_flattened_error(): @@ -1933,7 +1926,9 @@ async def test_delete_conversation_profile_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2059,8 +2054,10 @@ def test_conversation_profiles_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_conversation_profiles_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2084,29 +2081,6 @@ def test_conversation_profiles_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_conversation_profiles_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.conversation_profiles.transports.ConversationProfilesTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.ConversationProfilesTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_conversation_profiles_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2118,7 +2092,6 @@ def test_conversation_profiles_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_conversation_profiles_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2134,21 +2107,6 @@ def test_conversation_profiles_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_conversation_profiles_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - ConversationProfilesClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2156,7 +2114,6 @@ def test_conversation_profiles_auth_adc_old_google_auth(): transports.ConversationProfilesGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_conversation_profiles_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2173,29 +2130,6 @@ def test_conversation_profiles_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.ConversationProfilesGrpcTransport, - transports.ConversationProfilesGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_conversation_profiles_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2680,3 +2614,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = ConversationProfilesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = ConversationProfilesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = ConversationProfilesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_conversations.py b/tests/unit/gapic/dialogflow_v2beta1/test_conversations.py index 7ffc811ee..c65a290d3 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_conversations.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_conversations.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.conversations import ( @@ -37,9 +37,6 @@ from google.cloud.dialogflow_v2beta1.services.conversations import ConversationsClient from google.cloud.dialogflow_v2beta1.services.conversations import pagers from google.cloud.dialogflow_v2beta1.services.conversations import transports -from google.cloud.dialogflow_v2beta1.services.conversations.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import conversation from google.cloud.dialogflow_v2beta1.types import conversation as gcd_conversation from google.cloud.dialogflow_v2beta1.types import participant @@ -50,20 +47,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -220,7 +203,7 @@ def test_conversations_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -237,7 +220,7 @@ def test_conversations_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -254,7 +237,7 @@ def test_conversations_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -283,7 +266,7 @@ def test_conversations_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -342,7 +325,7 @@ def test_conversations_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -384,7 +367,7 @@ def test_conversations_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -406,7 +389,7 @@ def test_conversations_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -437,7 +420,7 @@ def test_conversations_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -468,7 +451,7 @@ def test_conversations_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -694,8 +677,12 @@ def test_create_conversation_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].conversation == gcd_conversation.Conversation(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].conversation + mock_val = gcd_conversation.Conversation(name="name_value") + assert arg == mock_val def test_create_conversation_flattened_error(): @@ -738,8 +725,12 @@ async def test_create_conversation_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].conversation == gcd_conversation.Conversation(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].conversation + mock_val = gcd_conversation.Conversation(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -923,7 +914,9 @@ def test_list_conversations_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_conversations_flattened_error(): @@ -961,7 +954,9 @@ async def test_list_conversations_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1319,7 +1314,9 @@ def test_get_conversation_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_conversation_flattened_error(): @@ -1355,7 +1352,9 @@ async def test_get_conversation_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1560,7 +1559,9 @@ def test_complete_conversation_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_complete_conversation_flattened_error(): @@ -1598,7 +1599,9 @@ async def test_complete_conversation_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1775,7 +1778,9 @@ def test_batch_create_messages_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_batch_create_messages_flattened_error(): @@ -1813,7 +1818,9 @@ async def test_batch_create_messages_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1981,7 +1988,9 @@ def test_list_messages_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_messages_flattened_error(): @@ -2017,7 +2026,9 @@ async def test_list_messages_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2280,8 +2291,10 @@ def test_conversations_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_conversations_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2305,29 +2318,6 @@ def test_conversations_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_conversations_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.conversations.transports.ConversationsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.ConversationsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_conversations_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2339,7 +2329,6 @@ def test_conversations_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_conversations_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2355,21 +2344,6 @@ def test_conversations_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_conversations_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - ConversationsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2377,7 +2351,6 @@ def test_conversations_auth_adc_old_google_auth(): transports.ConversationsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_conversations_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2394,29 +2367,6 @@ def test_conversations_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.ConversationsGrpcTransport, - transports.ConversationsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_conversations_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2827,3 +2777,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = ConversationsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = ConversationsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = ConversationsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_documents.py b/tests/unit/gapic/dialogflow_v2beta1/test_documents.py index ebf7c46b6..3d7d5a27e 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_documents.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_documents.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -32,15 +31,13 @@ from google.api_core import grpc_helpers_async from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.documents import DocumentsAsyncClient from google.cloud.dialogflow_v2beta1.services.documents import DocumentsClient from google.cloud.dialogflow_v2beta1.services.documents import pagers from google.cloud.dialogflow_v2beta1.services.documents import transports -from google.cloud.dialogflow_v2beta1.services.documents.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import document from google.cloud.dialogflow_v2beta1.types import document as gcd_document from google.cloud.dialogflow_v2beta1.types import gcs @@ -53,20 +50,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -210,7 +193,7 @@ def test_documents_client_client_options(client_class, transport_class, transpor options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -227,7 +210,7 @@ def test_documents_client_client_options(client_class, transport_class, transpor with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -244,7 +227,7 @@ def test_documents_client_client_options(client_class, transport_class, transpor with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -273,7 +256,7 @@ def test_documents_client_client_options(client_class, transport_class, transpor options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -330,7 +313,7 @@ def test_documents_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -372,7 +355,7 @@ def test_documents_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -394,7 +377,7 @@ def test_documents_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -425,7 +408,7 @@ def test_documents_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -456,7 +439,7 @@ def test_documents_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -636,7 +619,9 @@ def test_list_documents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_documents_flattened_error(): @@ -670,7 +655,9 @@ async def test_list_documents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -989,7 +976,9 @@ def test_get_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_document_flattened_error(): @@ -1021,7 +1010,9 @@ async def test_get_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1183,8 +1174,12 @@ def test_create_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].document == gcd_document.Document(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].document + mock_val = gcd_document.Document(name="name_value") + assert arg == mock_val def test_create_document_flattened_error(): @@ -1222,8 +1217,12 @@ async def test_create_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].document == gcd_document.Document(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].document + mock_val = gcd_document.Document(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1515,7 +1514,9 @@ def test_delete_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_document_flattened_error(): @@ -1549,7 +1550,9 @@ async def test_delete_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1716,8 +1719,12 @@ def test_update_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].document == gcd_document.Document(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].document + mock_val = gcd_document.Document(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_document_flattened_error(): @@ -1756,8 +1763,12 @@ async def test_update_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].document == gcd_document.Document(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].document + mock_val = gcd_document.Document(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1921,7 +1932,9 @@ def test_reload_document_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val assert args[0].gcs_source == gcs.GcsSource(uri="uri_value") @@ -1960,7 +1973,9 @@ async def test_reload_document_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val assert args[0].gcs_source == gcs.GcsSource(uri="uri_value") @@ -2084,13 +2099,15 @@ def test_documents_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + # Additionally, the LRO client (a property) should # also raise NotImplementedError with pytest.raises(NotImplementedError): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_documents_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2114,29 +2131,6 @@ def test_documents_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_documents_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.documents.transports.DocumentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.DocumentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_documents_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2148,7 +2142,6 @@ def test_documents_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_documents_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2164,26 +2157,10 @@ def test_documents_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_documents_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - DocumentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.DocumentsGrpcTransport, transports.DocumentsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_documents_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2200,26 +2177,6 @@ def test_documents_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.DocumentsGrpcTransport, transports.DocumentsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_documents_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2601,3 +2558,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = DocumentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = DocumentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = DocumentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_entity_types.py b/tests/unit/gapic/dialogflow_v2beta1/test_entity_types.py index 668c37cc5..52eb0d9bb 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_entity_types.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_entity_types.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -32,15 +31,13 @@ from google.api_core import grpc_helpers_async from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.entity_types import EntityTypesAsyncClient from google.cloud.dialogflow_v2beta1.services.entity_types import EntityTypesClient from google.cloud.dialogflow_v2beta1.services.entity_types import pagers from google.cloud.dialogflow_v2beta1.services.entity_types import transports -from google.cloud.dialogflow_v2beta1.services.entity_types.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import entity_type from google.cloud.dialogflow_v2beta1.types import entity_type as gcd_entity_type from google.longrunning import operations_pb2 @@ -50,20 +47,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -211,7 +194,7 @@ def test_entity_types_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -228,7 +211,7 @@ def test_entity_types_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -245,7 +228,7 @@ def test_entity_types_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -274,7 +257,7 @@ def test_entity_types_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -331,7 +314,7 @@ def test_entity_types_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -373,7 +356,7 @@ def test_entity_types_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -395,7 +378,7 @@ def test_entity_types_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -426,7 +409,7 @@ def test_entity_types_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -457,7 +440,7 @@ def test_entity_types_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -653,8 +636,12 @@ def test_list_entity_types_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_list_entity_types_flattened_error(): @@ -694,8 +681,12 @@ async def test_list_entity_types_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1041,8 +1032,12 @@ def test_get_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].language_code == "language_code_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_get_entity_type_flattened_error(): @@ -1080,8 +1075,12 @@ async def test_get_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].language_code == "language_code_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1288,9 +1287,15 @@ def test_create_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_type == gcd_entity_type.EntityType(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_type + mock_val = gcd_entity_type.EntityType(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_create_entity_type_flattened_error(): @@ -1333,9 +1338,15 @@ async def test_create_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_type == gcd_entity_type.EntityType(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_type + mock_val = gcd_entity_type.EntityType(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1547,9 +1558,15 @@ def test_update_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].entity_type == gcd_entity_type.EntityType(name="name_value") - assert args[0].language_code == "language_code_value" - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].entity_type + mock_val = gcd_entity_type.EntityType(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_entity_type_flattened_error(): @@ -1592,9 +1609,15 @@ async def test_update_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].entity_type == gcd_entity_type.EntityType(name="name_value") - assert args[0].language_code == "language_code_value" - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].entity_type + mock_val = gcd_entity_type.EntityType(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1765,7 +1788,9 @@ def test_delete_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_entity_type_flattened_error(): @@ -1799,7 +1824,9 @@ async def test_delete_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2115,8 +2142,12 @@ def test_batch_delete_entity_types_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_type_names == ["entity_type_names_value"] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_type_names + mock_val = ["entity_type_names_value"] + assert arg == mock_val def test_batch_delete_entity_types_flattened_error(): @@ -2156,8 +2187,12 @@ async def test_batch_delete_entity_types_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_type_names == ["entity_type_names_value"] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_type_names + mock_val = ["entity_type_names_value"] + assert arg == mock_val @pytest.mark.asyncio @@ -2335,9 +2370,15 @@ def test_batch_create_entities_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entities == [entity_type.EntityType.Entity(value="value_value")] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entities + mock_val = [entity_type.EntityType.Entity(value="value_value")] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_batch_create_entities_flattened_error(): @@ -2380,9 +2421,15 @@ async def test_batch_create_entities_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entities == [entity_type.EntityType.Entity(value="value_value")] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entities + mock_val = [entity_type.EntityType.Entity(value="value_value")] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2561,9 +2608,15 @@ def test_batch_update_entities_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entities == [entity_type.EntityType.Entity(value="value_value")] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entities + mock_val = [entity_type.EntityType.Entity(value="value_value")] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_batch_update_entities_flattened_error(): @@ -2606,9 +2659,15 @@ async def test_batch_update_entities_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entities == [entity_type.EntityType.Entity(value="value_value")] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entities + mock_val = [entity_type.EntityType.Entity(value="value_value")] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2787,9 +2846,15 @@ def test_batch_delete_entities_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_values == ["entity_values_value"] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_values + mock_val = ["entity_values_value"] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_batch_delete_entities_flattened_error(): @@ -2832,9 +2897,15 @@ async def test_batch_delete_entities_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].entity_values == ["entity_values_value"] - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].entity_values + mock_val = ["entity_values_value"] + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2961,13 +3032,15 @@ def test_entity_types_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + # Additionally, the LRO client (a property) should # also raise NotImplementedError with pytest.raises(NotImplementedError): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_entity_types_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2991,29 +3064,6 @@ def test_entity_types_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_entity_types_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.entity_types.transports.EntityTypesTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.EntityTypesTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_entity_types_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -3025,7 +3075,6 @@ def test_entity_types_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_entity_types_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -3041,26 +3090,10 @@ def test_entity_types_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_entity_types_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - EntityTypesClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.EntityTypesGrpcTransport, transports.EntityTypesGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_entity_types_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -3077,26 +3110,6 @@ def test_entity_types_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.EntityTypesGrpcTransport, transports.EntityTypesGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_entity_types_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -3476,3 +3489,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = EntityTypesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = EntityTypesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = EntityTypesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_environments.py b/tests/unit/gapic/dialogflow_v2beta1/test_environments.py index 5014e4a71..1c9635f21 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_environments.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_environments.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.environments import ( @@ -37,9 +37,6 @@ from google.cloud.dialogflow_v2beta1.services.environments import EnvironmentsClient from google.cloud.dialogflow_v2beta1.services.environments import pagers from google.cloud.dialogflow_v2beta1.services.environments import transports -from google.cloud.dialogflow_v2beta1.services.environments.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import audio_config from google.cloud.dialogflow_v2beta1.types import environment from google.cloud.dialogflow_v2beta1.types import fulfillment @@ -49,20 +46,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -210,7 +193,7 @@ def test_environments_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -227,7 +210,7 @@ def test_environments_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -244,7 +227,7 @@ def test_environments_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -273,7 +256,7 @@ def test_environments_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -330,7 +313,7 @@ def test_environments_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -372,7 +355,7 @@ def test_environments_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -394,7 +377,7 @@ def test_environments_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -425,7 +408,7 @@ def test_environments_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -456,7 +439,7 @@ def test_environments_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -650,7 +633,9 @@ def test_list_environments_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_environments_flattened_error(): @@ -686,7 +671,9 @@ async def test_list_environments_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1880,8 +1867,10 @@ def test_environments_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_environments_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1905,29 +1894,6 @@ def test_environments_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_environments_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.environments.transports.EnvironmentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.EnvironmentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_environments_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1939,7 +1905,6 @@ def test_environments_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_environments_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1955,21 +1920,6 @@ def test_environments_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_environments_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - EnvironmentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -1977,7 +1927,6 @@ def test_environments_auth_adc_old_google_auth(): transports.EnvironmentsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_environments_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1994,29 +1943,6 @@ def test_environments_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.EnvironmentsGrpcTransport, - transports.EnvironmentsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_environments_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2410,3 +2336,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = EnvironmentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = EnvironmentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = EnvironmentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_fulfillments.py b/tests/unit/gapic/dialogflow_v2beta1/test_fulfillments.py index 623eb96df..d5aa85a73 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_fulfillments.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_fulfillments.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.fulfillments import ( @@ -36,9 +36,6 @@ ) from google.cloud.dialogflow_v2beta1.services.fulfillments import FulfillmentsClient from google.cloud.dialogflow_v2beta1.services.fulfillments import transports -from google.cloud.dialogflow_v2beta1.services.fulfillments.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import fulfillment from google.cloud.dialogflow_v2beta1.types import fulfillment as gcd_fulfillment from google.oauth2 import service_account @@ -46,20 +43,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -207,7 +190,7 @@ def test_fulfillments_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -224,7 +207,7 @@ def test_fulfillments_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -241,7 +224,7 @@ def test_fulfillments_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -270,7 +253,7 @@ def test_fulfillments_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -327,7 +310,7 @@ def test_fulfillments_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -369,7 +352,7 @@ def test_fulfillments_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -391,7 +374,7 @@ def test_fulfillments_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -422,7 +405,7 @@ def test_fulfillments_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -453,7 +436,7 @@ def test_fulfillments_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -644,7 +627,9 @@ def test_get_fulfillment_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_fulfillment_flattened_error(): @@ -678,7 +663,9 @@ async def test_get_fulfillment_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -873,8 +860,12 @@ def test_update_fulfillment_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].fulfillment == gcd_fulfillment.Fulfillment(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].fulfillment + mock_val = gcd_fulfillment.Fulfillment(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_fulfillment_flattened_error(): @@ -915,8 +906,12 @@ async def test_update_fulfillment_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].fulfillment == gcd_fulfillment.Fulfillment(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].fulfillment + mock_val = gcd_fulfillment.Fulfillment(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1037,8 +1032,10 @@ def test_fulfillments_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_fulfillments_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1062,29 +1059,6 @@ def test_fulfillments_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_fulfillments_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.fulfillments.transports.FulfillmentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.FulfillmentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_fulfillments_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1096,7 +1070,6 @@ def test_fulfillments_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_fulfillments_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1112,21 +1085,6 @@ def test_fulfillments_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_fulfillments_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - FulfillmentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -1134,7 +1092,6 @@ def test_fulfillments_auth_adc_old_google_auth(): transports.FulfillmentsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_fulfillments_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1151,29 +1108,6 @@ def test_fulfillments_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.FulfillmentsGrpcTransport, - transports.FulfillmentsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_fulfillments_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -1523,3 +1457,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = FulfillmentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = FulfillmentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = FulfillmentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_intents.py b/tests/unit/gapic/dialogflow_v2beta1/test_intents.py index 423113bc7..1d09e6921 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_intents.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_intents.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -32,15 +31,13 @@ from google.api_core import grpc_helpers_async from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.intents import IntentsAsyncClient from google.cloud.dialogflow_v2beta1.services.intents import IntentsClient from google.cloud.dialogflow_v2beta1.services.intents import pagers from google.cloud.dialogflow_v2beta1.services.intents import transports -from google.cloud.dialogflow_v2beta1.services.intents.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import context from google.cloud.dialogflow_v2beta1.types import intent from google.cloud.dialogflow_v2beta1.types import intent as gcd_intent @@ -51,20 +48,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -199,7 +182,7 @@ def test_intents_client_client_options(client_class, transport_class, transport_ options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -216,7 +199,7 @@ def test_intents_client_client_options(client_class, transport_class, transport_ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -233,7 +216,7 @@ def test_intents_client_client_options(client_class, transport_class, transport_ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +245,7 @@ def test_intents_client_client_options(client_class, transport_class, transport_ options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -317,7 +300,7 @@ def test_intents_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -359,7 +342,7 @@ def test_intents_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -381,7 +364,7 @@ def test_intents_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -408,7 +391,7 @@ def test_intents_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -435,7 +418,7 @@ def test_intents_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -615,8 +598,12 @@ def test_list_intents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_list_intents_flattened_error(): @@ -654,8 +641,12 @@ async def test_list_intents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -999,8 +990,12 @@ def test_get_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].language_code == "language_code_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_get_intent_flattened_error(): @@ -1036,8 +1031,12 @@ async def test_get_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" - assert args[0].language_code == "language_code_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1277,9 +1276,15 @@ def test_create_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].intent == gcd_intent.Intent(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].intent + mock_val = gcd_intent.Intent(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_create_intent_flattened_error(): @@ -1318,9 +1323,15 @@ async def test_create_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].intent == gcd_intent.Intent(name="name_value") - assert args[0].language_code == "language_code_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].intent + mock_val = gcd_intent.Intent(name="name_value") + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1561,9 +1572,15 @@ def test_update_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].intent == gcd_intent.Intent(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) - assert args[0].language_code == "language_code_value" + arg = args[0].intent + mock_val = gcd_intent.Intent(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val def test_update_intent_flattened_error(): @@ -1602,9 +1619,15 @@ async def test_update_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].intent == gcd_intent.Intent(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) - assert args[0].language_code == "language_code_value" + arg = args[0].intent + mock_val = gcd_intent.Intent(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + arg = args[0].language_code + mock_val = "language_code_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1763,7 +1786,9 @@ def test_delete_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_intent_flattened_error(): @@ -1795,7 +1820,9 @@ async def test_delete_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1973,7 +2000,9 @@ def test_batch_update_intents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val assert args[0].intent_batch_inline == intent.IntentBatch( intents=[intent.Intent(name="name_value")] ) @@ -2023,7 +2052,9 @@ async def test_batch_update_intents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val assert args[0].intent_batch_inline == intent.IntentBatch( intents=[intent.Intent(name="name_value")] ) @@ -2205,8 +2236,12 @@ def test_batch_delete_intents_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].intents == [intent.Intent(name="name_value")] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].intents + mock_val = [intent.Intent(name="name_value")] + assert arg == mock_val def test_batch_delete_intents_flattened_error(): @@ -2246,8 +2281,12 @@ async def test_batch_delete_intents_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].intents == [intent.Intent(name="name_value")] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].intents + mock_val = [intent.Intent(name="name_value")] + assert arg == mock_val @pytest.mark.asyncio @@ -2370,13 +2409,15 @@ def test_intents_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + # Additionally, the LRO client (a property) should # also raise NotImplementedError with pytest.raises(NotImplementedError): transport.operations_client -@requires_google_auth_gte_1_25_0 def test_intents_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2400,29 +2441,6 @@ def test_intents_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_intents_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.intents.transports.IntentsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.IntentsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_intents_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2434,7 +2452,6 @@ def test_intents_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_intents_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2450,26 +2467,10 @@ def test_intents_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_intents_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - IntentsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.IntentsGrpcTransport, transports.IntentsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_intents_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2486,26 +2487,6 @@ def test_intents_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.IntentsGrpcTransport, transports.IntentsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_intents_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2909,3 +2890,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = IntentsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = IntentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = IntentsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_knowledge_bases.py b/tests/unit/gapic/dialogflow_v2beta1/test_knowledge_bases.py index b3df106bf..5d5e4c785 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_knowledge_bases.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_knowledge_bases.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.knowledge_bases import ( @@ -39,9 +39,6 @@ ) from google.cloud.dialogflow_v2beta1.services.knowledge_bases import pagers from google.cloud.dialogflow_v2beta1.services.knowledge_bases import transports -from google.cloud.dialogflow_v2beta1.services.knowledge_bases.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import knowledge_base from google.cloud.dialogflow_v2beta1.types import knowledge_base as gcd_knowledge_base from google.oauth2 import service_account @@ -49,20 +46,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -219,7 +202,7 @@ def test_knowledge_bases_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -236,7 +219,7 @@ def test_knowledge_bases_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -253,7 +236,7 @@ def test_knowledge_bases_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -282,7 +265,7 @@ def test_knowledge_bases_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -341,7 +324,7 @@ def test_knowledge_bases_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -383,7 +366,7 @@ def test_knowledge_bases_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -405,7 +388,7 @@ def test_knowledge_bases_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -436,7 +419,7 @@ def test_knowledge_bases_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -467,7 +450,7 @@ def test_knowledge_bases_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -666,7 +649,9 @@ def test_list_knowledge_bases_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_knowledge_bases_flattened_error(): @@ -704,7 +689,9 @@ async def test_list_knowledge_bases_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1064,7 +1051,9 @@ def test_get_knowledge_base_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_knowledge_base_flattened_error(): @@ -1102,7 +1091,9 @@ async def test_get_knowledge_base_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1296,10 +1287,12 @@ def test_create_knowledge_base_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].knowledge_base == gcd_knowledge_base.KnowledgeBase( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].knowledge_base + mock_val = gcd_knowledge_base.KnowledgeBase(name="name_value") + assert arg == mock_val def test_create_knowledge_base_flattened_error(): @@ -1342,10 +1335,12 @@ async def test_create_knowledge_base_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].knowledge_base == gcd_knowledge_base.KnowledgeBase( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].knowledge_base + mock_val = gcd_knowledge_base.KnowledgeBase(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1520,7 +1515,9 @@ def test_delete_knowledge_base_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_knowledge_base_flattened_error(): @@ -1556,7 +1553,9 @@ async def test_delete_knowledge_base_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1756,10 +1755,12 @@ def test_update_knowledge_base_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].knowledge_base == gcd_knowledge_base.KnowledgeBase( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].knowledge_base + mock_val = gcd_knowledge_base.KnowledgeBase(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_knowledge_base_flattened_error(): @@ -1802,10 +1803,12 @@ async def test_update_knowledge_base_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].knowledge_base == gcd_knowledge_base.KnowledgeBase( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].knowledge_base + mock_val = gcd_knowledge_base.KnowledgeBase(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1931,8 +1934,10 @@ def test_knowledge_bases_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_knowledge_bases_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1956,29 +1961,6 @@ def test_knowledge_bases_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_knowledge_bases_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.knowledge_bases.transports.KnowledgeBasesTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.KnowledgeBasesTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_knowledge_bases_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1990,7 +1972,6 @@ def test_knowledge_bases_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_knowledge_bases_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2006,21 +1987,6 @@ def test_knowledge_bases_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_knowledge_bases_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - KnowledgeBasesClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2028,7 +1994,6 @@ def test_knowledge_bases_auth_adc_old_google_auth(): transports.KnowledgeBasesGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_knowledge_bases_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2045,29 +2010,6 @@ def test_knowledge_bases_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.KnowledgeBasesGrpcTransport, - transports.KnowledgeBasesGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_knowledge_bases_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2432,3 +2374,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = KnowledgeBasesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = KnowledgeBasesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = KnowledgeBasesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_participants.py b/tests/unit/gapic/dialogflow_v2beta1/test_participants.py index c3b2713b0..dc2bfbac6 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_participants.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_participants.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.participants import ( @@ -37,9 +37,6 @@ from google.cloud.dialogflow_v2beta1.services.participants import ParticipantsClient from google.cloud.dialogflow_v2beta1.services.participants import pagers from google.cloud.dialogflow_v2beta1.services.participants import transports -from google.cloud.dialogflow_v2beta1.services.participants.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import agent from google.cloud.dialogflow_v2beta1.types import audio_config from google.cloud.dialogflow_v2beta1.types import context @@ -56,20 +53,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -217,7 +200,7 @@ def test_participants_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -234,7 +217,7 @@ def test_participants_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -251,7 +234,7 @@ def test_participants_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -280,7 +263,7 @@ def test_participants_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -337,7 +320,7 @@ def test_participants_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -379,7 +362,7 @@ def test_participants_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -401,7 +384,7 @@ def test_participants_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -432,7 +415,7 @@ def test_participants_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -463,7 +446,7 @@ def test_participants_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -669,8 +652,12 @@ def test_create_participant_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].participant == gcd_participant.Participant(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].participant + mock_val = gcd_participant.Participant(name="name_value") + assert arg == mock_val def test_create_participant_flattened_error(): @@ -711,8 +698,12 @@ async def test_create_participant_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].participant == gcd_participant.Participant(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].participant + mock_val = gcd_participant.Participant(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -888,7 +879,9 @@ def test_get_participant_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_participant_flattened_error(): @@ -922,7 +915,9 @@ async def test_get_participant_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1100,7 +1095,9 @@ def test_list_participants_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_participants_flattened_error(): @@ -1136,7 +1133,9 @@ async def test_list_participants_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1484,8 +1483,12 @@ def test_update_participant_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].participant == gcd_participant.Participant(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].participant + mock_val = gcd_participant.Participant(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_participant_flattened_error(): @@ -1526,8 +1529,12 @@ async def test_update_participant_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].participant == gcd_participant.Participant(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].participant + mock_val = gcd_participant.Participant(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1697,7 +1704,9 @@ def test_analyze_content_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].participant == "participant_value" + arg = args[0].participant + mock_val = "participant_value" + assert arg == mock_val assert args[0].event_input == session.EventInput(name="name_value") @@ -1739,7 +1748,9 @@ async def test_analyze_content_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].participant == "participant_value" + arg = args[0].participant + mock_val = "participant_value" + assert arg == mock_val assert args[0].event_input == session.EventInput(name="name_value") @@ -1911,7 +1922,9 @@ def test_suggest_articles_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_suggest_articles_flattened_error(): @@ -1945,7 +1958,9 @@ async def test_suggest_articles_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2125,7 +2140,9 @@ def test_suggest_faq_answers_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_suggest_faq_answers_flattened_error(): @@ -2161,7 +2178,9 @@ async def test_suggest_faq_answers_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2341,7 +2360,9 @@ def test_suggest_smart_replies_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_suggest_smart_replies_flattened_error(): @@ -2377,7 +2398,9 @@ async def test_suggest_smart_replies_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2926,8 +2949,10 @@ def test_participants_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_participants_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2951,29 +2976,6 @@ def test_participants_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_participants_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.participants.transports.ParticipantsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.ParticipantsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_participants_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2985,7 +2987,6 @@ def test_participants_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_participants_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -3001,21 +3002,6 @@ def test_participants_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_participants_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - ParticipantsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -3023,7 +3009,6 @@ def test_participants_auth_adc_old_google_auth(): transports.ParticipantsGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_participants_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -3040,29 +3025,6 @@ def test_participants_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.ParticipantsGrpcTransport, - transports.ParticipantsGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_participants_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -3536,3 +3498,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = ParticipantsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = ParticipantsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = ParticipantsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_session_entity_types.py b/tests/unit/gapic/dialogflow_v2beta1/test_session_entity_types.py index cf07bef1c..421b212a9 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_session_entity_types.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_session_entity_types.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,6 +28,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.session_entity_types import ( @@ -39,9 +39,6 @@ ) from google.cloud.dialogflow_v2beta1.services.session_entity_types import pagers from google.cloud.dialogflow_v2beta1.services.session_entity_types import transports -from google.cloud.dialogflow_v2beta1.services.session_entity_types.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import entity_type from google.cloud.dialogflow_v2beta1.types import session_entity_type from google.cloud.dialogflow_v2beta1.types import ( @@ -52,20 +49,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -223,7 +206,7 @@ def test_session_entity_types_client_client_options( options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -240,7 +223,7 @@ def test_session_entity_types_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -257,7 +240,7 @@ def test_session_entity_types_client_client_options( with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -286,7 +269,7 @@ def test_session_entity_types_client_client_options( options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -355,7 +338,7 @@ def test_session_entity_types_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -397,7 +380,7 @@ def test_session_entity_types_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -419,7 +402,7 @@ def test_session_entity_types_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -450,7 +433,7 @@ def test_session_entity_types_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -481,7 +464,7 @@ def test_session_entity_types_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -685,7 +668,9 @@ def test_list_session_entity_types_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_session_entity_types_flattened_error(): @@ -725,7 +710,9 @@ async def test_list_session_entity_types_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1101,7 +1088,9 @@ def test_get_session_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_session_entity_type_flattened_error(): @@ -1141,7 +1130,9 @@ async def test_get_session_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1344,10 +1335,12 @@ def test_create_session_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].session_entity_type == gcd_session_entity_type.SessionEntityType( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].session_entity_type + mock_val = gcd_session_entity_type.SessionEntityType(name="name_value") + assert arg == mock_val def test_create_session_entity_type_flattened_error(): @@ -1396,10 +1389,12 @@ async def test_create_session_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].session_entity_type == gcd_session_entity_type.SessionEntityType( - name="name_value" - ) + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].session_entity_type + mock_val = gcd_session_entity_type.SessionEntityType(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1612,10 +1607,12 @@ def test_update_session_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].session_entity_type == gcd_session_entity_type.SessionEntityType( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].session_entity_type + mock_val = gcd_session_entity_type.SessionEntityType(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_session_entity_type_flattened_error(): @@ -1664,10 +1661,12 @@ async def test_update_session_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].session_entity_type == gcd_session_entity_type.SessionEntityType( - name="name_value" - ) - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].session_entity_type + mock_val = gcd_session_entity_type.SessionEntityType(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1849,7 +1848,9 @@ def test_delete_session_entity_type_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_session_entity_type_flattened_error(): @@ -1887,7 +1888,9 @@ async def test_delete_session_entity_type_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -2013,8 +2016,10 @@ def test_session_entity_types_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_session_entity_types_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -2038,29 +2043,6 @@ def test_session_entity_types_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_session_entity_types_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.session_entity_types.transports.SessionEntityTypesTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.SessionEntityTypesTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_session_entity_types_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -2072,7 +2054,6 @@ def test_session_entity_types_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_session_entity_types_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -2088,21 +2069,6 @@ def test_session_entity_types_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_session_entity_types_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - SessionEntityTypesClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [ @@ -2110,7 +2076,6 @@ def test_session_entity_types_auth_adc_old_google_auth(): transports.SessionEntityTypesGrpcAsyncIOTransport, ], ) -@requires_google_auth_gte_1_25_0 def test_session_entity_types_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -2127,29 +2092,6 @@ def test_session_entity_types_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [ - transports.SessionEntityTypesGrpcTransport, - transports.SessionEntityTypesGrpcAsyncIOTransport, - ], -) -@requires_google_auth_lt_1_25_0 -def test_session_entity_types_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2520,3 +2462,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = SessionEntityTypesAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = SessionEntityTypesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = SessionEntityTypesClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_sessions.py b/tests/unit/gapic/dialogflow_v2beta1/test_sessions.py index 1869b3547..0095c44db 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_sessions.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_sessions.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,14 +28,12 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.sessions import SessionsAsyncClient from google.cloud.dialogflow_v2beta1.services.sessions import SessionsClient from google.cloud.dialogflow_v2beta1.services.sessions import transports -from google.cloud.dialogflow_v2beta1.services.sessions.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import agent from google.cloud.dialogflow_v2beta1.types import audio_config from google.cloud.dialogflow_v2beta1.types import context @@ -52,20 +49,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -205,7 +188,7 @@ def test_sessions_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -222,7 +205,7 @@ def test_sessions_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -239,7 +222,7 @@ def test_sessions_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -268,7 +251,7 @@ def test_sessions_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -325,7 +308,7 @@ def test_sessions_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -367,7 +350,7 @@ def test_sessions_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -389,7 +372,7 @@ def test_sessions_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -416,7 +399,7 @@ def test_sessions_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -443,7 +426,7 @@ def test_sessions_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -634,12 +617,16 @@ def test_detect_intent_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].session == "session_value" - assert args[0].query_input == gcd_session.QueryInput( + arg = args[0].session + mock_val = "session_value" + assert arg == mock_val + arg = args[0].query_input + mock_val = gcd_session.QueryInput( audio_config=audio_config.InputAudioConfig( audio_encoding=audio_config.AudioEncoding.AUDIO_ENCODING_LINEAR_16 ) ) + assert arg == mock_val def test_detect_intent_flattened_error(): @@ -686,12 +673,16 @@ async def test_detect_intent_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].session == "session_value" - assert args[0].query_input == gcd_session.QueryInput( + arg = args[0].session + mock_val = "session_value" + assert arg == mock_val + arg = args[0].query_input + mock_val = gcd_session.QueryInput( audio_config=audio_config.InputAudioConfig( audio_encoding=audio_config.AudioEncoding.AUDIO_ENCODING_LINEAR_16 ) ) + assert arg == mock_val @pytest.mark.asyncio @@ -886,8 +877,10 @@ def test_sessions_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_sessions_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -911,29 +904,6 @@ def test_sessions_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_sessions_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.sessions.transports.SessionsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.SessionsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_sessions_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -945,7 +915,6 @@ def test_sessions_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_sessions_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -961,26 +930,10 @@ def test_sessions_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_sessions_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - SessionsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.SessionsGrpcTransport, transports.SessionsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_sessions_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -997,26 +950,6 @@ def test_sessions_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.SessionsGrpcTransport, transports.SessionsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_sessions_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -1464,3 +1397,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = SessionsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = SessionsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = SessionsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() diff --git a/tests/unit/gapic/dialogflow_v2beta1/test_versions.py b/tests/unit/gapic/dialogflow_v2beta1/test_versions.py index bf5314ce9..a4fa212bf 100644 --- a/tests/unit/gapic/dialogflow_v2beta1/test_versions.py +++ b/tests/unit/gapic/dialogflow_v2beta1/test_versions.py @@ -15,7 +15,6 @@ # import os import mock -import packaging.version import grpc from grpc.experimental import aio @@ -29,15 +28,13 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async +from google.api_core import path_template from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError from google.cloud.dialogflow_v2beta1.services.versions import VersionsAsyncClient from google.cloud.dialogflow_v2beta1.services.versions import VersionsClient from google.cloud.dialogflow_v2beta1.services.versions import pagers from google.cloud.dialogflow_v2beta1.services.versions import transports -from google.cloud.dialogflow_v2beta1.services.versions.transports.base import ( - _GOOGLE_AUTH_VERSION, -) from google.cloud.dialogflow_v2beta1.types import version from google.cloud.dialogflow_v2beta1.types import version as gcd_version from google.oauth2 import service_account @@ -46,20 +43,6 @@ import google.auth -# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively -# through google-api-core: -# - Delete the auth "less than" test cases -# - Delete these pytest markers (Make the "greater than or equal to" tests the default). -requires_google_auth_lt_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), - reason="This test requires google-auth < 1.25.0", -) -requires_google_auth_gte_1_25_0 = pytest.mark.skipif( - packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), - reason="This test requires google-auth >= 1.25.0", -) - - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -199,7 +182,7 @@ def test_versions_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -216,7 +199,7 @@ def test_versions_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -233,7 +216,7 @@ def test_versions_client_client_options(client_class, transport_class, transport with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -262,7 +245,7 @@ def test_versions_client_client_options(client_class, transport_class, transport options = client_options.ClientOptions(quota_project_id="octopus") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -319,7 +302,7 @@ def test_versions_client_mtls_env_auto( ) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) if use_client_cert_env == "false": expected_client_cert_source = None @@ -361,7 +344,7 @@ def test_versions_client_mtls_env_auto( expected_client_cert_source = client_cert_source_callback patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -383,7 +366,7 @@ def test_versions_client_mtls_env_auto( return_value=False, ): patched.return_value = None - client = client_class() + client = client_class(transport=transport_name) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -410,7 +393,7 @@ def test_versions_client_client_options_scopes( options = client_options.ClientOptions(scopes=["1", "2"],) with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file=None, @@ -437,7 +420,7 @@ def test_versions_client_client_options_credentials_file( options = client_options.ClientOptions(credentials_file="credentials.json") with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None - client = client_class(client_options=options) + client = client_class(transport=transport_name, client_options=options) patched.assert_called_once_with( credentials=None, credentials_file="credentials.json", @@ -617,7 +600,9 @@ def test_list_versions_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val def test_list_versions_flattened_error(): @@ -651,7 +636,9 @@ async def test_list_versions_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val @pytest.mark.asyncio @@ -947,7 +934,9 @@ def test_get_version_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_get_version_flattened_error(): @@ -979,7 +968,9 @@ async def test_get_version_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1157,8 +1148,12 @@ def test_create_version_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].version == gcd_version.Version(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].version + mock_val = gcd_version.Version(name="name_value") + assert arg == mock_val def test_create_version_flattened_error(): @@ -1194,8 +1189,12 @@ async def test_create_version_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].parent == "parent_value" - assert args[0].version == gcd_version.Version(name="name_value") + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].version + mock_val = gcd_version.Version(name="name_value") + assert arg == mock_val @pytest.mark.asyncio @@ -1380,8 +1379,12 @@ def test_update_version_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].version == gcd_version.Version(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].version + mock_val = gcd_version.Version(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val def test_update_version_flattened_error(): @@ -1418,8 +1421,12 @@ async def test_update_version_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].version == gcd_version.Version(name="name_value") - assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + arg = args[0].version + mock_val = gcd_version.Version(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val @pytest.mark.asyncio @@ -1577,7 +1584,9 @@ def test_delete_version_flattened(): # request object values. assert len(call.mock_calls) == 1 _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val def test_delete_version_flattened_error(): @@ -1609,7 +1618,9 @@ async def test_delete_version_flattened_async(): # request object values. assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0].name == "name_value" + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val @pytest.mark.asyncio @@ -1728,8 +1739,10 @@ def test_versions_base_transport(): with pytest.raises(NotImplementedError): getattr(transport, method)(request=object()) + with pytest.raises(NotImplementedError): + transport.close() + -@requires_google_auth_gte_1_25_0 def test_versions_base_transport_with_credentials_file(): # Instantiate the base transport with a credentials file with mock.patch.object( @@ -1753,29 +1766,6 @@ def test_versions_base_transport_with_credentials_file(): ) -@requires_google_auth_lt_1_25_0 -def test_versions_base_transport_with_credentials_file_old_google_auth(): - # Instantiate the base transport with a credentials file - with mock.patch.object( - google.auth, "load_credentials_from_file", autospec=True - ) as load_creds, mock.patch( - "google.cloud.dialogflow_v2beta1.services.versions.transports.VersionsTransport._prep_wrapped_messages" - ) as Transport: - Transport.return_value = None - load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) - transport = transports.VersionsTransport( - credentials_file="credentials.json", quota_project_id="octopus", - ) - load_creds.assert_called_once_with( - "credentials.json", - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - def test_versions_base_transport_with_adc(): # Test the default credentials are used if credentials and credentials_file are None. with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( @@ -1787,7 +1777,6 @@ def test_versions_base_transport_with_adc(): adc.assert_called_once() -@requires_google_auth_gte_1_25_0 def test_versions_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(google.auth, "default", autospec=True) as adc: @@ -1803,26 +1792,10 @@ def test_versions_auth_adc(): ) -@requires_google_auth_lt_1_25_0 -def test_versions_auth_adc_old_google_auth(): - # If no credentials are provided, we should use ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - VersionsClient() - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id=None, - ) - - @pytest.mark.parametrize( "transport_class", [transports.VersionsGrpcTransport, transports.VersionsGrpcAsyncIOTransport,], ) -@requires_google_auth_gte_1_25_0 def test_versions_transport_auth_adc(transport_class): # If credentials and host are not provided, the transport class should use # ADC credentials. @@ -1839,26 +1812,6 @@ def test_versions_transport_auth_adc(transport_class): ) -@pytest.mark.parametrize( - "transport_class", - [transports.VersionsGrpcTransport, transports.VersionsGrpcAsyncIOTransport,], -) -@requires_google_auth_lt_1_25_0 -def test_versions_transport_auth_adc_old_google_auth(transport_class): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object(google.auth, "default", autospec=True) as adc: - adc.return_value = (ga_credentials.AnonymousCredentials(), None) - transport_class(quota_project_id="octopus") - adc.assert_called_once_with( - scopes=( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/dialogflow", - ), - quota_project_id="octopus", - ) - - @pytest.mark.parametrize( "transport_class,grpc_helpers", [ @@ -2212,3 +2165,49 @@ def test_client_withDEFAULT_CLIENT_INFO(): credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, ) prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = VersionsAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close(): + transports = { + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = VersionsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "grpc", + ] + for transport in transports: + client = VersionsClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called()