diff --git a/google/cloud/dialogflowcx_v3/services/agents/async_client.py b/google/cloud/dialogflowcx_v3/services/agents/async_client.py index 60e08061..89a55c6b 100644 --- a/google/cloud/dialogflowcx_v3/services/agents/async_client.py +++ b/google/cloud/dialogflowcx_v3/services/agents/async_client.py @@ -352,6 +352,10 @@ async def create_agent( ) -> gcdc_agent.Agent: r"""Creates an agent in the specified location. + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.CreateAgentRequest`): The request object. The request message for @@ -443,6 +447,10 @@ async def update_agent( ) -> gcdc_agent.Agent: r"""Updates the specified agent. + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.UpdateAgentRequest`): The request object. The request message for @@ -659,9 +667,14 @@ async def restore_agent( metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: r"""Restores the specified agent from a binary file. + Replaces the current agent with a new one. Note that all - existing resources in agent (e.g. intents, entity types, - flows) will be removed. + existing resources in agent (e.g. intents, entity types, flows) + will be removed. + + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. Args: request (:class:`google.cloud.dialogflowcx_v3.types.RestoreAgentRequest`): diff --git a/google/cloud/dialogflowcx_v3/services/agents/client.py b/google/cloud/dialogflowcx_v3/services/agents/client.py index 61cbe72c..516930ae 100644 --- a/google/cloud/dialogflowcx_v3/services/agents/client.py +++ b/google/cloud/dialogflowcx_v3/services/agents/client.py @@ -613,6 +613,10 @@ def create_agent( ) -> gcdc_agent.Agent: r"""Creates an agent in the specified location. + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.CreateAgentRequest): The request object. The request message for @@ -704,6 +708,10 @@ def update_agent( ) -> gcdc_agent.Agent: r"""Updates the specified agent. + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.UpdateAgentRequest): The request object. The request message for @@ -921,9 +929,14 @@ def restore_agent( metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: r"""Restores the specified agent from a binary file. + Replaces the current agent with a new one. Note that all - existing resources in agent (e.g. intents, entity types, - flows) will be removed. + existing resources in agent (e.g. intents, entity types, flows) + will be removed. + + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. Args: request (google.cloud.dialogflowcx_v3.types.RestoreAgentRequest): diff --git a/google/cloud/dialogflowcx_v3/services/agents/transports/base.py b/google/cloud/dialogflowcx_v3/services/agents/transports/base.py index 8fafde41..ee150fc4 100644 --- a/google/cloud/dialogflowcx_v3/services/agents/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/agents/transports/base.py @@ -25,6 +25,7 @@ from google.api_core import retry as retries # type: ignore from google.api_core import operations_v1 # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import agent from google.cloud.dialogflowcx_v3.types import agent as gcdc_agent @@ -49,8 +50,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class AgentsTransport(abc.ABC): """Abstract transport class for Agents.""" @@ -71,6 +70,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -94,6 +94,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -103,7 +105,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -122,13 +124,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -149,27 +158,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/agents/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/agents/transports/grpc.py index 99a98b9e..242f5237 100644 --- a/google/cloud/dialogflowcx_v3/services/agents/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/agents/transports/grpc.py @@ -61,6 +61,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -101,6 +102,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -154,6 +157,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -209,14 +213,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -299,6 +303,10 @@ def create_agent( Creates an agent in the specified location. + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateAgentRequest], ~.Agent]: @@ -325,6 +333,10 @@ def update_agent( Updates the specified agent. + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateAgentRequest], ~.Agent]: @@ -400,9 +412,14 @@ def restore_agent( r"""Return a callable for the restore agent method over gRPC. Restores the specified agent from a binary file. + Replaces the current agent with a new one. Note that all - existing resources in agent (e.g. intents, entity types, - flows) will be removed. + existing resources in agent (e.g. intents, entity types, flows) + will be removed. + + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. Returns: Callable[[~.RestoreAgentRequest], diff --git a/google/cloud/dialogflowcx_v3/services/agents/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/agents/transports/grpc_asyncio.py index a7b09070..540efbec 100644 --- a/google/cloud/dialogflowcx_v3/services/agents/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/agents/transports/grpc_asyncio.py @@ -82,14 +82,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -107,6 +107,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -148,6 +149,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -200,6 +203,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -304,6 +308,10 @@ def create_agent( Creates an agent in the specified location. + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateAgentRequest], Awaitable[~.Agent]]: @@ -330,6 +338,10 @@ def update_agent( Updates the specified agent. + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateAgentRequest], Awaitable[~.Agent]]: @@ -407,9 +419,14 @@ def restore_agent( r"""Return a callable for the restore agent method over gRPC. Restores the specified agent from a binary file. + Replaces the current agent with a new one. Note that all - existing resources in agent (e.g. intents, entity types, - flows) will be removed. + existing resources in agent (e.g. intents, entity types, flows) + will be removed. + + Note: You should always train flows prior to sending them + queries. See the `training + documentation `__. Returns: Callable[[~.RestoreAgentRequest], diff --git a/google/cloud/dialogflowcx_v3/services/entity_types/async_client.py b/google/cloud/dialogflowcx_v3/services/entity_types/async_client.py index 8ee7d941..cb98ab7e 100644 --- a/google/cloud/dialogflowcx_v3/services/entity_types/async_client.py +++ b/google/cloud/dialogflowcx_v3/services/entity_types/async_client.py @@ -358,6 +358,10 @@ async def create_entity_type( ) -> gcdc_entity_type.EntityType: r"""Creates an entity type in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.CreateEntityTypeRequest`): The request object. The request message for @@ -469,6 +473,10 @@ async def update_entity_type( ) -> gcdc_entity_type.EntityType: r"""Updates the specified entity type. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.UpdateEntityTypeRequest`): The request object. The request message for @@ -581,6 +589,10 @@ async def delete_entity_type( ) -> None: r"""Deletes the specified entity type. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.DeleteEntityTypeRequest`): The request object. The request message for diff --git a/google/cloud/dialogflowcx_v3/services/entity_types/client.py b/google/cloud/dialogflowcx_v3/services/entity_types/client.py index 6f12cfb0..4d9e1ade 100644 --- a/google/cloud/dialogflowcx_v3/services/entity_types/client.py +++ b/google/cloud/dialogflowcx_v3/services/entity_types/client.py @@ -547,6 +547,10 @@ def create_entity_type( ) -> gcdc_entity_type.EntityType: r"""Creates an entity type in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.CreateEntityTypeRequest): The request object. The request message for @@ -658,6 +662,10 @@ def update_entity_type( ) -> gcdc_entity_type.EntityType: r"""Updates the specified entity type. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.UpdateEntityTypeRequest): The request object. The request message for @@ -770,6 +778,10 @@ def delete_entity_type( ) -> None: r"""Deletes the specified entity type. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.DeleteEntityTypeRequest): The request object. The request message for diff --git a/google/cloud/dialogflowcx_v3/services/entity_types/transports/base.py b/google/cloud/dialogflowcx_v3/services/entity_types/transports/base.py index edd3e613..fe44ea0f 100644 --- a/google/cloud/dialogflowcx_v3/services/entity_types/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/entity_types/transports/base.py @@ -24,6 +24,7 @@ from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import entity_type from google.cloud.dialogflowcx_v3.types import entity_type as gcdc_entity_type @@ -47,8 +48,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class EntityTypesTransport(abc.ABC): """Abstract transport class for EntityTypes.""" @@ -69,6 +68,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -92,6 +92,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -101,7 +103,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -120,13 +122,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -147,27 +156,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/entity_types/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/entity_types/transports/grpc.py index f4fe8095..9ad26c81 100644 --- a/google/cloud/dialogflowcx_v3/services/entity_types/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/entity_types/transports/grpc.py @@ -60,6 +60,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -100,6 +101,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -152,6 +155,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -207,14 +211,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -289,6 +293,10 @@ def create_entity_type( Creates an entity type in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateEntityTypeRequest], ~.EntityType]: @@ -317,6 +325,10 @@ def update_entity_type( Updates the specified entity type. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateEntityTypeRequest], ~.EntityType]: @@ -343,6 +355,10 @@ def delete_entity_type( Deletes the specified entity type. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.DeleteEntityTypeRequest], ~.Empty]: diff --git a/google/cloud/dialogflowcx_v3/services/entity_types/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/entity_types/transports/grpc_asyncio.py index 38cec4de..167661be 100644 --- a/google/cloud/dialogflowcx_v3/services/entity_types/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/entity_types/transports/grpc_asyncio.py @@ -81,14 +81,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -106,6 +106,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -147,6 +148,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -198,6 +201,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -296,6 +300,10 @@ def create_entity_type( Creates an entity type in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateEntityTypeRequest], Awaitable[~.EntityType]]: @@ -325,6 +333,10 @@ def update_entity_type( Updates the specified entity type. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateEntityTypeRequest], Awaitable[~.EntityType]]: @@ -351,6 +363,10 @@ def delete_entity_type( Deletes the specified entity type. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.DeleteEntityTypeRequest], Awaitable[~.Empty]]: diff --git a/google/cloud/dialogflowcx_v3/services/environments/transports/base.py b/google/cloud/dialogflowcx_v3/services/environments/transports/base.py index e6683b3b..a065d0b1 100644 --- a/google/cloud/dialogflowcx_v3/services/environments/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/environments/transports/base.py @@ -25,6 +25,7 @@ from google.api_core import retry as retries # type: ignore from google.api_core import operations_v1 # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import environment from google.cloud.dialogflowcx_v3.types import environment as gcdc_environment @@ -49,8 +50,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class EnvironmentsTransport(abc.ABC): """Abstract transport class for Environments.""" @@ -71,6 +70,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -94,6 +94,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -103,7 +105,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -122,13 +124,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -149,27 +158,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/environments/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/environments/transports/grpc.py index 16fc53f2..1f2abf3d 100644 --- a/google/cloud/dialogflowcx_v3/services/environments/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/environments/transports/grpc.py @@ -62,6 +62,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -102,6 +103,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -155,6 +158,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -210,14 +214,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) diff --git a/google/cloud/dialogflowcx_v3/services/environments/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/environments/transports/grpc_asyncio.py index 37b55d5b..79606cbf 100644 --- a/google/cloud/dialogflowcx_v3/services/environments/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/environments/transports/grpc_asyncio.py @@ -83,14 +83,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -108,6 +108,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -149,6 +150,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -201,6 +204,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/google/cloud/dialogflowcx_v3/services/experiments/transports/base.py b/google/cloud/dialogflowcx_v3/services/experiments/transports/base.py index afba41e2..f783fa00 100644 --- a/google/cloud/dialogflowcx_v3/services/experiments/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/experiments/transports/base.py @@ -24,6 +24,7 @@ from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import experiment from google.cloud.dialogflowcx_v3.types import experiment as gcdc_experiment @@ -47,8 +48,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class ExperimentsTransport(abc.ABC): """Abstract transport class for Experiments.""" @@ -69,6 +68,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -92,6 +92,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -101,7 +103,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -120,13 +122,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -147,27 +156,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/experiments/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/experiments/transports/grpc.py index f1deea19..81456f08 100644 --- a/google/cloud/dialogflowcx_v3/services/experiments/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/experiments/transports/grpc.py @@ -60,6 +60,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -100,6 +101,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -152,6 +155,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -207,14 +211,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) diff --git a/google/cloud/dialogflowcx_v3/services/experiments/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/experiments/transports/grpc_asyncio.py index 2ce07e07..fd4a8100 100644 --- a/google/cloud/dialogflowcx_v3/services/experiments/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/experiments/transports/grpc_asyncio.py @@ -81,14 +81,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -106,6 +106,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -147,6 +148,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -198,6 +201,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/google/cloud/dialogflowcx_v3/services/flows/async_client.py b/google/cloud/dialogflowcx_v3/services/flows/async_client.py index 6815a427..e32af9c8 100644 --- a/google/cloud/dialogflowcx_v3/services/flows/async_client.py +++ b/google/cloud/dialogflowcx_v3/services/flows/async_client.py @@ -186,6 +186,10 @@ async def create_flow( ) -> gcdc_flow.Flow: r"""Creates a flow in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.CreateFlowRequest`): The request object. The request message for @@ -522,6 +526,10 @@ async def update_flow( ) -> gcdc_flow.Flow: r"""Updates the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.UpdateFlowRequest`): The request object. The request message for @@ -622,8 +630,12 @@ async def train_flow( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: - r"""Trains the specified flow. Note that only the flow in - 'draft' environment is trained. + r"""Trains the specified flow. Note that only the flow in 'draft' + environment is trained. + + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. Args: request (:class:`google.cloud.dialogflowcx_v3.types.TrainFlowRequest`): @@ -838,8 +850,12 @@ async def import_flow( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: - r"""Imports the specified flow to the specified agent - from a binary file. + r"""Imports the specified flow to the specified agent from a binary + file. + + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. Args: request (:class:`google.cloud.dialogflowcx_v3.types.ImportFlowRequest`): diff --git a/google/cloud/dialogflowcx_v3/services/flows/client.py b/google/cloud/dialogflowcx_v3/services/flows/client.py index dd6bbebf..f07e9f7e 100644 --- a/google/cloud/dialogflowcx_v3/services/flows/client.py +++ b/google/cloud/dialogflowcx_v3/services/flows/client.py @@ -455,6 +455,10 @@ def create_flow( ) -> gcdc_flow.Flow: r"""Creates a flow in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.CreateFlowRequest): The request object. The request message for @@ -791,6 +795,10 @@ def update_flow( ) -> gcdc_flow.Flow: r"""Updates the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.UpdateFlowRequest): The request object. The request message for @@ -891,8 +899,12 @@ def train_flow( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: - r"""Trains the specified flow. Note that only the flow in - 'draft' environment is trained. + r"""Trains the specified flow. Note that only the flow in 'draft' + environment is trained. + + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. Args: request (google.cloud.dialogflowcx_v3.types.TrainFlowRequest): @@ -1110,8 +1122,12 @@ def import_flow( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: - r"""Imports the specified flow to the specified agent - from a binary file. + r"""Imports the specified flow to the specified agent from a binary + file. + + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. Args: request (google.cloud.dialogflowcx_v3.types.ImportFlowRequest): diff --git a/google/cloud/dialogflowcx_v3/services/flows/transports/base.py b/google/cloud/dialogflowcx_v3/services/flows/transports/base.py index 3999d848..dc4046ea 100644 --- a/google/cloud/dialogflowcx_v3/services/flows/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/flows/transports/base.py @@ -25,6 +25,7 @@ from google.api_core import retry as retries # type: ignore from google.api_core import operations_v1 # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import flow from google.cloud.dialogflowcx_v3.types import flow as gcdc_flow @@ -49,8 +50,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class FlowsTransport(abc.ABC): """Abstract transport class for Flows.""" @@ -71,6 +70,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -94,6 +94,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -103,7 +105,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -122,13 +124,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -149,27 +158,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/flows/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/flows/transports/grpc.py index 92016ca2..ca5c69e2 100644 --- a/google/cloud/dialogflowcx_v3/services/flows/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/flows/transports/grpc.py @@ -61,6 +61,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -101,6 +102,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -154,6 +157,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -209,14 +213,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -246,6 +250,10 @@ def create_flow(self) -> Callable[[gcdc_flow.CreateFlowRequest], gcdc_flow.Flow] Creates a flow in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateFlowRequest], ~.Flow]: @@ -342,6 +350,10 @@ def update_flow(self) -> Callable[[gcdc_flow.UpdateFlowRequest], gcdc_flow.Flow] Updates the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateFlowRequest], ~.Flow]: @@ -364,8 +376,12 @@ def update_flow(self) -> Callable[[gcdc_flow.UpdateFlowRequest], gcdc_flow.Flow] def train_flow(self) -> Callable[[flow.TrainFlowRequest], operations_pb2.Operation]: r"""Return a callable for the train flow method over gRPC. - Trains the specified flow. Note that only the flow in - 'draft' environment is trained. + Trains the specified flow. Note that only the flow in 'draft' + environment is trained. + + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. Returns: Callable[[~.TrainFlowRequest], @@ -447,8 +463,12 @@ def import_flow( ) -> Callable[[flow.ImportFlowRequest], operations_pb2.Operation]: r"""Return a callable for the import flow method over gRPC. - Imports the specified flow to the specified agent - from a binary file. + Imports the specified flow to the specified agent from a binary + file. + + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. Returns: Callable[[~.ImportFlowRequest], diff --git a/google/cloud/dialogflowcx_v3/services/flows/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/flows/transports/grpc_asyncio.py index 2a73cf2f..b502f59c 100644 --- a/google/cloud/dialogflowcx_v3/services/flows/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/flows/transports/grpc_asyncio.py @@ -82,14 +82,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -107,6 +107,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -148,6 +149,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -200,6 +203,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -253,6 +257,10 @@ def create_flow( Creates a flow in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateFlowRequest], Awaitable[~.Flow]]: @@ -355,6 +363,10 @@ def update_flow( Updates the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateFlowRequest], Awaitable[~.Flow]]: @@ -379,8 +391,12 @@ def train_flow( ) -> Callable[[flow.TrainFlowRequest], Awaitable[operations_pb2.Operation]]: r"""Return a callable for the train flow method over gRPC. - Trains the specified flow. Note that only the flow in - 'draft' environment is trained. + Trains the specified flow. Note that only the flow in 'draft' + environment is trained. + + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. Returns: Callable[[~.TrainFlowRequest], @@ -464,8 +480,12 @@ def import_flow( ) -> Callable[[flow.ImportFlowRequest], Awaitable[operations_pb2.Operation]]: r"""Return a callable for the import flow method over gRPC. - Imports the specified flow to the specified agent - from a binary file. + Imports the specified flow to the specified agent from a binary + file. + + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. Returns: Callable[[~.ImportFlowRequest], diff --git a/google/cloud/dialogflowcx_v3/services/intents/async_client.py b/google/cloud/dialogflowcx_v3/services/intents/async_client.py index bdf87330..bc47f4ac 100644 --- a/google/cloud/dialogflowcx_v3/services/intents/async_client.py +++ b/google/cloud/dialogflowcx_v3/services/intents/async_client.py @@ -328,6 +328,10 @@ async def create_intent( ) -> gcdc_intent.Intent: r"""Creates an intent in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.CreateIntentRequest`): The request object. The request message for @@ -412,6 +416,10 @@ async def update_intent( ) -> gcdc_intent.Intent: r"""Updates the specified intent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.UpdateIntentRequest`): The request object. The request message for @@ -498,6 +506,10 @@ async def delete_intent( ) -> None: r"""Deletes the specified intent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.DeleteIntentRequest`): The request object. The request message for diff --git a/google/cloud/dialogflowcx_v3/services/intents/client.py b/google/cloud/dialogflowcx_v3/services/intents/client.py index c4a2fd9d..705dc5eb 100644 --- a/google/cloud/dialogflowcx_v3/services/intents/client.py +++ b/google/cloud/dialogflowcx_v3/services/intents/client.py @@ -535,6 +535,10 @@ def create_intent( ) -> gcdc_intent.Intent: r"""Creates an intent in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.CreateIntentRequest): The request object. The request message for @@ -619,6 +623,10 @@ def update_intent( ) -> gcdc_intent.Intent: r"""Updates the specified intent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.UpdateIntentRequest): The request object. The request message for @@ -705,6 +713,10 @@ def delete_intent( ) -> None: r"""Deletes the specified intent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.DeleteIntentRequest): The request object. The request message for diff --git a/google/cloud/dialogflowcx_v3/services/intents/transports/base.py b/google/cloud/dialogflowcx_v3/services/intents/transports/base.py index 7b147df4..90a38908 100644 --- a/google/cloud/dialogflowcx_v3/services/intents/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/intents/transports/base.py @@ -24,6 +24,7 @@ from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import intent from google.cloud.dialogflowcx_v3.types import intent as gcdc_intent @@ -47,8 +48,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class IntentsTransport(abc.ABC): """Abstract transport class for Intents.""" @@ -69,6 +68,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -92,6 +92,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -101,7 +103,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -120,13 +122,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -147,27 +156,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/intents/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/intents/transports/grpc.py index cf6512f0..f42155f4 100644 --- a/google/cloud/dialogflowcx_v3/services/intents/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/intents/transports/grpc.py @@ -60,6 +60,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -100,6 +101,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -152,6 +155,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -207,14 +211,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -283,6 +287,10 @@ def create_intent( Creates an intent in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateIntentRequest], ~.Intent]: @@ -309,6 +317,10 @@ def update_intent( Updates the specified intent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateIntentRequest], ~.Intent]: @@ -333,6 +345,10 @@ def delete_intent(self) -> Callable[[intent.DeleteIntentRequest], empty_pb2.Empt Deletes the specified intent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.DeleteIntentRequest], ~.Empty]: diff --git a/google/cloud/dialogflowcx_v3/services/intents/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/intents/transports/grpc_asyncio.py index b98be5ac..95f1dfb6 100644 --- a/google/cloud/dialogflowcx_v3/services/intents/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/intents/transports/grpc_asyncio.py @@ -81,14 +81,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -106,6 +106,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -147,6 +148,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -198,6 +201,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -288,6 +292,10 @@ def create_intent( Creates an intent in the specified agent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateIntentRequest], Awaitable[~.Intent]]: @@ -314,6 +322,10 @@ def update_intent( Updates the specified intent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateIntentRequest], Awaitable[~.Intent]]: @@ -340,6 +352,10 @@ def delete_intent( Deletes the specified intent. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.DeleteIntentRequest], Awaitable[~.Empty]]: diff --git a/google/cloud/dialogflowcx_v3/services/pages/async_client.py b/google/cloud/dialogflowcx_v3/services/pages/async_client.py index 79d410c1..0a7e9503 100644 --- a/google/cloud/dialogflowcx_v3/services/pages/async_client.py +++ b/google/cloud/dialogflowcx_v3/services/pages/async_client.py @@ -349,6 +349,10 @@ async def create_page( ) -> gcdc_page.Page: r"""Creates a page in the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.CreatePageRequest`): The request object. The request message for @@ -448,6 +452,10 @@ async def update_page( ) -> gcdc_page.Page: r"""Updates the specified page. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.UpdatePageRequest`): The request object. The request message for @@ -549,6 +557,10 @@ async def delete_page( ) -> None: r"""Deletes the specified page. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.DeletePageRequest`): The request object. The request message for diff --git a/google/cloud/dialogflowcx_v3/services/pages/client.py b/google/cloud/dialogflowcx_v3/services/pages/client.py index a74f7673..cec7c48a 100644 --- a/google/cloud/dialogflowcx_v3/services/pages/client.py +++ b/google/cloud/dialogflowcx_v3/services/pages/client.py @@ -620,6 +620,10 @@ def create_page( ) -> gcdc_page.Page: r"""Creates a page in the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.CreatePageRequest): The request object. The request message for @@ -719,6 +723,10 @@ def update_page( ) -> gcdc_page.Page: r"""Updates the specified page. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.UpdatePageRequest): The request object. The request message for @@ -820,6 +828,10 @@ def delete_page( ) -> None: r"""Deletes the specified page. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.DeletePageRequest): The request object. The request message for diff --git a/google/cloud/dialogflowcx_v3/services/pages/transports/base.py b/google/cloud/dialogflowcx_v3/services/pages/transports/base.py index 3325368a..a8a0312d 100644 --- a/google/cloud/dialogflowcx_v3/services/pages/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/pages/transports/base.py @@ -24,6 +24,7 @@ from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import page from google.cloud.dialogflowcx_v3.types import page as gcdc_page @@ -47,8 +48,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class PagesTransport(abc.ABC): """Abstract transport class for Pages.""" @@ -69,6 +68,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -92,6 +92,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -101,7 +103,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -120,13 +122,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -147,27 +156,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/pages/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/pages/transports/grpc.py index 8d8361f7..0fc211bf 100644 --- a/google/cloud/dialogflowcx_v3/services/pages/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/pages/transports/grpc.py @@ -59,6 +59,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -99,6 +100,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -151,6 +154,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -206,14 +210,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -277,6 +281,10 @@ def create_page(self) -> Callable[[gcdc_page.CreatePageRequest], gcdc_page.Page] Creates a page in the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreatePageRequest], ~.Page]: @@ -301,6 +309,10 @@ def update_page(self) -> Callable[[gcdc_page.UpdatePageRequest], gcdc_page.Page] Updates the specified page. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdatePageRequest], ~.Page]: @@ -325,6 +337,10 @@ def delete_page(self) -> Callable[[page.DeletePageRequest], empty_pb2.Empty]: Deletes the specified page. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.DeletePageRequest], ~.Empty]: diff --git a/google/cloud/dialogflowcx_v3/services/pages/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/pages/transports/grpc_asyncio.py index 3f084d95..c6c574bf 100644 --- a/google/cloud/dialogflowcx_v3/services/pages/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/pages/transports/grpc_asyncio.py @@ -80,14 +80,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -105,6 +105,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -146,6 +147,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -197,6 +200,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -284,6 +288,10 @@ def create_page( Creates a page in the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreatePageRequest], Awaitable[~.Page]]: @@ -310,6 +318,10 @@ def update_page( Updates the specified page. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdatePageRequest], Awaitable[~.Page]]: @@ -336,6 +348,10 @@ def delete_page( Deletes the specified page. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.DeletePageRequest], Awaitable[~.Empty]]: diff --git a/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/base.py b/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/base.py index 6ed6a73b..ad18cc76 100644 --- a/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/base.py @@ -24,6 +24,7 @@ from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import security_settings from google.cloud.dialogflowcx_v3.types import ( @@ -49,8 +50,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class SecuritySettingsServiceTransport(abc.ABC): """Abstract transport class for SecuritySettingsService.""" @@ -71,6 +70,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -94,6 +94,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -103,7 +105,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -122,13 +124,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -149,27 +158,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/grpc.py index cf0d1917..7ed00ca3 100644 --- a/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/grpc.py @@ -61,6 +61,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -101,6 +102,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -153,6 +156,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -208,14 +212,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) diff --git a/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/grpc_asyncio.py index 5fa7c384..5c7b6461 100644 --- a/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/security_settings_service/transports/grpc_asyncio.py @@ -82,14 +82,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -107,6 +107,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -148,6 +149,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -199,6 +202,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/base.py b/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/base.py index 76f2dd22..67c904a6 100644 --- a/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/base.py @@ -24,6 +24,7 @@ from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import session_entity_type from google.cloud.dialogflowcx_v3.types import ( @@ -49,8 +50,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class SessionEntityTypesTransport(abc.ABC): """Abstract transport class for SessionEntityTypes.""" @@ -71,6 +70,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -94,6 +94,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -103,7 +105,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -122,13 +124,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -149,27 +158,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/grpc.py index b1d2fcef..224ebcfd 100644 --- a/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/grpc.py @@ -62,6 +62,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -102,6 +103,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -154,6 +157,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -209,14 +213,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) diff --git a/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/grpc_asyncio.py index e9cc5a9d..d8afcfc7 100644 --- a/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/session_entity_types/transports/grpc_asyncio.py @@ -83,14 +83,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -108,6 +108,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -149,6 +150,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -200,6 +203,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/google/cloud/dialogflowcx_v3/services/sessions/transports/base.py b/google/cloud/dialogflowcx_v3/services/sessions/transports/base.py index e995fc1a..cce0d59f 100644 --- a/google/cloud/dialogflowcx_v3/services/sessions/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/sessions/transports/base.py @@ -24,6 +24,7 @@ from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import session @@ -45,8 +46,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class SessionsTransport(abc.ABC): """Abstract transport class for Sessions.""" @@ -67,6 +66,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -90,6 +90,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -99,7 +101,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -118,13 +120,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -145,27 +154,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/sessions/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/sessions/transports/grpc.py index 3b5a5fbd..a78d8c27 100644 --- a/google/cloud/dialogflowcx_v3/services/sessions/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/sessions/transports/grpc.py @@ -60,6 +60,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -100,6 +101,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -152,6 +155,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -207,14 +211,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) diff --git a/google/cloud/dialogflowcx_v3/services/sessions/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/sessions/transports/grpc_asyncio.py index 94a6f61c..ff58d6a2 100644 --- a/google/cloud/dialogflowcx_v3/services/sessions/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/sessions/transports/grpc_asyncio.py @@ -81,14 +81,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -106,6 +106,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -147,6 +148,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -198,6 +201,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/google/cloud/dialogflowcx_v3/services/test_cases/transports/base.py b/google/cloud/dialogflowcx_v3/services/test_cases/transports/base.py index 4cd9a366..5ec51667 100644 --- a/google/cloud/dialogflowcx_v3/services/test_cases/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/test_cases/transports/base.py @@ -25,6 +25,7 @@ from google.api_core import retry as retries # type: ignore from google.api_core import operations_v1 # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import test_case from google.cloud.dialogflowcx_v3.types import test_case as gcdc_test_case @@ -49,8 +50,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class TestCasesTransport(abc.ABC): """Abstract transport class for TestCases.""" @@ -71,6 +70,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -94,6 +94,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -103,7 +105,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -122,13 +124,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -149,27 +158,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/test_cases/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/test_cases/transports/grpc.py index 79b0442a..7f7ad9b9 100644 --- a/google/cloud/dialogflowcx_v3/services/test_cases/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/test_cases/transports/grpc.py @@ -63,6 +63,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -103,6 +104,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -156,6 +159,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -211,14 +215,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) diff --git a/google/cloud/dialogflowcx_v3/services/test_cases/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/test_cases/transports/grpc_asyncio.py index a1bb484d..84c36ecb 100644 --- a/google/cloud/dialogflowcx_v3/services/test_cases/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/test_cases/transports/grpc_asyncio.py @@ -84,14 +84,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -109,6 +109,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -150,6 +151,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -202,6 +205,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/google/cloud/dialogflowcx_v3/services/transition_route_groups/async_client.py b/google/cloud/dialogflowcx_v3/services/transition_route_groups/async_client.py index 49feee70..23095956 100644 --- a/google/cloud/dialogflowcx_v3/services/transition_route_groups/async_client.py +++ b/google/cloud/dialogflowcx_v3/services/transition_route_groups/async_client.py @@ -355,6 +355,10 @@ async def create_transition_route_group( [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup] in the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.CreateTransitionRouteGroupRequest`): The request object. The request message for @@ -441,6 +445,10 @@ async def update_transition_route_group( r"""Updates the specified [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup]. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.UpdateTransitionRouteGroupRequest`): The request object. The request message for @@ -526,6 +534,10 @@ async def delete_transition_route_group( r"""Deletes the specified [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup]. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (:class:`google.cloud.dialogflowcx_v3.types.DeleteTransitionRouteGroupRequest`): The request object. The request message for diff --git a/google/cloud/dialogflowcx_v3/services/transition_route_groups/client.py b/google/cloud/dialogflowcx_v3/services/transition_route_groups/client.py index 44903604..c16321f5 100644 --- a/google/cloud/dialogflowcx_v3/services/transition_route_groups/client.py +++ b/google/cloud/dialogflowcx_v3/services/transition_route_groups/client.py @@ -607,6 +607,10 @@ def create_transition_route_group( [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup] in the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.CreateTransitionRouteGroupRequest): The request object. The request message for @@ -699,6 +703,10 @@ def update_transition_route_group( r"""Updates the specified [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup]. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.UpdateTransitionRouteGroupRequest): The request object. The request message for @@ -790,6 +798,10 @@ def delete_transition_route_group( r"""Deletes the specified [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup]. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Args: request (google.cloud.dialogflowcx_v3.types.DeleteTransitionRouteGroupRequest): The request object. The request message for diff --git a/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/base.py b/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/base.py index 3a538d56..aeb1c799 100644 --- a/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/base.py @@ -24,6 +24,7 @@ from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import transition_route_group from google.cloud.dialogflowcx_v3.types import ( @@ -49,8 +50,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class TransitionRouteGroupsTransport(abc.ABC): """Abstract transport class for TransitionRouteGroups.""" @@ -71,6 +70,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -94,6 +94,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -103,7 +105,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -122,13 +124,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -149,27 +158,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/grpc.py index 8e38881e..256252a0 100644 --- a/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/grpc.py @@ -62,6 +62,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -102,6 +103,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -154,6 +157,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -209,14 +213,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -299,6 +303,10 @@ def create_transition_route_group( [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup] in the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateTransitionRouteGroupRequest], ~.TransitionRouteGroup]: @@ -331,6 +339,10 @@ def update_transition_route_group( Updates the specified [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup]. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateTransitionRouteGroupRequest], ~.TransitionRouteGroup]: @@ -362,6 +374,10 @@ def delete_transition_route_group( Deletes the specified [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup]. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.DeleteTransitionRouteGroupRequest], ~.Empty]: diff --git a/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/grpc_asyncio.py index 58e0ce08..f67f5d3f 100644 --- a/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/transition_route_groups/transports/grpc_asyncio.py @@ -83,14 +83,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -108,6 +108,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -149,6 +150,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -200,6 +203,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -302,6 +306,10 @@ def create_transition_route_group( [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup] in the specified flow. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.CreateTransitionRouteGroupRequest], Awaitable[~.TransitionRouteGroup]]: @@ -334,6 +342,10 @@ def update_transition_route_group( Updates the specified [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup]. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.UpdateTransitionRouteGroupRequest], Awaitable[~.TransitionRouteGroup]]: @@ -366,6 +378,10 @@ def delete_transition_route_group( Deletes the specified [TransitionRouteGroup][google.cloud.dialogflow.cx.v3.TransitionRouteGroup]. + Note: You should always train a flow prior to sending it + queries. See the `training + documentation `__. + Returns: Callable[[~.DeleteTransitionRouteGroupRequest], Awaitable[~.Empty]]: diff --git a/google/cloud/dialogflowcx_v3/services/versions/transports/base.py b/google/cloud/dialogflowcx_v3/services/versions/transports/base.py index 596f71d1..c6950934 100644 --- a/google/cloud/dialogflowcx_v3/services/versions/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/versions/transports/base.py @@ -25,6 +25,7 @@ from google.api_core import retry as retries # type: ignore from google.api_core import operations_v1 # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import version from google.cloud.dialogflowcx_v3.types import version as gcdc_version @@ -49,8 +50,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class VersionsTransport(abc.ABC): """Abstract transport class for Versions.""" @@ -71,6 +70,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -94,6 +94,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -103,7 +105,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -122,13 +124,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -149,27 +158,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/versions/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/versions/transports/grpc.py index 55989b8a..d26c214c 100644 --- a/google/cloud/dialogflowcx_v3/services/versions/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/versions/transports/grpc.py @@ -62,6 +62,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -102,6 +103,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -155,6 +158,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -210,14 +214,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) diff --git a/google/cloud/dialogflowcx_v3/services/versions/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/versions/transports/grpc_asyncio.py index e61f15a6..f58db509 100644 --- a/google/cloud/dialogflowcx_v3/services/versions/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/versions/transports/grpc_asyncio.py @@ -83,14 +83,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -108,6 +108,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -149,6 +150,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -201,6 +204,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/google/cloud/dialogflowcx_v3/services/webhooks/transports/base.py b/google/cloud/dialogflowcx_v3/services/webhooks/transports/base.py index 1ececbf7..ff16859b 100644 --- a/google/cloud/dialogflowcx_v3/services/webhooks/transports/base.py +++ b/google/cloud/dialogflowcx_v3/services/webhooks/transports/base.py @@ -24,6 +24,7 @@ from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.dialogflowcx_v3.types import webhook from google.cloud.dialogflowcx_v3.types import webhook as gcdc_webhook @@ -47,8 +48,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class WebhooksTransport(abc.ABC): """Abstract transport class for Webhooks.""" @@ -69,6 +68,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -92,6 +92,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -101,7 +103,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. @@ -120,13 +122,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # 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-api-core - # and google-auth are increased. + # 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 @@ -147,27 +156,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/dialogflowcx_v3/services/webhooks/transports/grpc.py b/google/cloud/dialogflowcx_v3/services/webhooks/transports/grpc.py index 7ce092c6..91cbe743 100644 --- a/google/cloud/dialogflowcx_v3/services/webhooks/transports/grpc.py +++ b/google/cloud/dialogflowcx_v3/services/webhooks/transports/grpc.py @@ -60,6 +60,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -100,6 +101,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -152,6 +155,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: @@ -207,14 +211,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) diff --git a/google/cloud/dialogflowcx_v3/services/webhooks/transports/grpc_asyncio.py b/google/cloud/dialogflowcx_v3/services/webhooks/transports/grpc_asyncio.py index 7947152f..8fb5962e 100644 --- a/google/cloud/dialogflowcx_v3/services/webhooks/transports/grpc_asyncio.py +++ b/google/cloud/dialogflowcx_v3/services/webhooks/transports/grpc_asyncio.py @@ -81,14 +81,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -106,6 +106,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -147,6 +148,8 @@ def __init__( API requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -198,6 +201,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/google/cloud/dialogflowcx_v3/types/agent.py b/google/cloud/dialogflowcx_v3/types/agent.py index 52bec47e..2bdab12a 100644 --- a/google/cloud/dialogflowcx_v3/types/agent.py +++ b/google/cloud/dialogflowcx_v3/types/agent.py @@ -77,8 +77,8 @@ class Agent(proto.Message): Required. The human-readable name of the agent, unique within the location. default_language_code (str): - Immutable. The default language of the agent as a language - tag. See `Language + Required. Immutable. The default language of the agent as a + language tag. See `Language Support `__ for a list of the currently supported language codes. This field cannot be set by the diff --git a/google/cloud/dialogflowcx_v3/types/fulfillment.py b/google/cloud/dialogflowcx_v3/types/fulfillment.py index a4cf0283..c5f9a941 100644 --- a/google/cloud/dialogflowcx_v3/types/fulfillment.py +++ b/google/cloud/dialogflowcx_v3/types/fulfillment.py @@ -52,6 +52,19 @@ class Fulfillment(proto.Message): webhook (str): The webhook to call. Format: ``projects//locations//agents//webhooks/``. + return_partial_responses (bool): + Whether Dialogflow should return currently + queued fulfillment response messages in + streaming APIs. If a webhook is specified, it + happens before Dialogflow invokes webhook. + Warning: + 1) This flag only affects streaming API. + Responses are still queued and returned once in + non-streaming API. + 2) The flag can be enabled in any fulfillment + but only the first 3 partial responses will be + returned. You may only want to apply it to + fulfillments that have slow webhooks. tag (str): The tag used by the webhook to identify which fulfillment is being called. This field is required if ``webhook`` is @@ -143,6 +156,7 @@ class CaseContent(proto.Message): proto.MESSAGE, number=1, message=response_message.ResponseMessage, ) webhook = proto.Field(proto.STRING, number=2,) + return_partial_responses = proto.Field(proto.BOOL, number=8,) tag = proto.Field(proto.STRING, number=3,) set_parameter_actions = proto.RepeatedField( proto.MESSAGE, number=4, message=SetParameterAction, diff --git a/google/cloud/dialogflowcx_v3/types/intent.py b/google/cloud/dialogflowcx_v3/types/intent.py index 76c3bd0a..4ea72c20 100644 --- a/google/cloud/dialogflowcx_v3/types/intent.py +++ b/google/cloud/dialogflowcx_v3/types/intent.py @@ -95,12 +95,12 @@ class Intent(proto.Message): and values can be no longer than 63 characters and no more than 128 bytes. - Prefix "sys." is reserved for Dialogflow defined labels. + Prefix "sys-" is reserved for Dialogflow defined labels. Currently allowed Dialogflow defined labels include: - - sys.head - - sys.contextual The above labels do not require value. - "sys.head" means the intent is a head intent. + - sys-head + - sys-contextual The above labels do not require value. + "sys-head" means the intent is a head intent. "sys.contextual" means the intent is a contextual intent. description (str): Human readable description for better diff --git a/google/cloud/dialogflowcx_v3/types/security_settings.py b/google/cloud/dialogflowcx_v3/types/security_settings.py index 4267d511..4dec351e 100644 --- a/google/cloud/dialogflowcx_v3/types/security_settings.py +++ b/google/cloud/dialogflowcx_v3/types/security_settings.py @@ -165,8 +165,10 @@ class SecuritySettings(proto.Message): If empty, we use the default DLP inspect config. The template name will have one of the following formats: - ``projects/PROJECT_ID/inspectTemplates/TEMPLATE_ID`` OR - ``organizations/ORGANIZATION_ID/inspectTemplates/TEMPLATE_ID`` + ``projects//inspectTemplates/